diff --git a/examples/common_components/led_strip/CMakeLists.txt b/examples/common_components/led_strip/CMakeLists.txt new file mode 100644 index 00000000000..fe4ca413a21 --- /dev/null +++ b/examples/common_components/led_strip/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "led_strip_rmt_ws2812.c" + INCLUDE_DIRS "include" + PRIV_REQUIRES "driver" + ) diff --git a/examples/common_components/led_strip/README.md b/examples/common_components/led_strip/README.md new file mode 100644 index 00000000000..abf07898a57 --- /dev/null +++ b/examples/common_components/led_strip/README.md @@ -0,0 +1,16 @@ +# LED Strip Component + +This directory contains an implementation for addressable LEDs using the RMT peripheral. + +It's compatible with: + +* [WS2812](http://www.world-semi.com/Certifications/WS2812B.html) +* SK68XX + +This component is used as part of the following ESP-IDF examples: +- [Blink Example](../../get-started/blink). +- [LED Strip Example](../../peripherals/rmt/led_strip). + +To learn more about how to use this component, please check API Documentation from header file [led_strip.h](./include/led_strip.h). + +Please note that this component is not considered to be a part of ESP-IDF stable API. It may change and it may be removed in the future releases. diff --git a/examples/common_components/led_strip/component.mk b/examples/common_components/led_strip/component.mk new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/peripherals/rmt/led_strip/components/led_strip/include/led_strip.h b/examples/common_components/led_strip/include/led_strip.h similarity index 86% rename from examples/peripherals/rmt/led_strip/components/led_strip/include/led_strip.h rename to examples/common_components/led_strip/include/led_strip.h index a9dffc32580..2e1d6334953 100644 --- a/examples/peripherals/rmt/led_strip/components/led_strip/include/led_strip.h +++ b/examples/common_components/led_strip/include/led_strip.h @@ -121,6 +121,27 @@ typedef struct { */ led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); +/** + * @brief Init the RMT peripheral and LED strip configuration. + * + * @param[in] channel: RMT peripheral channel number. + * @param[in] gpio: GPIO number for the RMT data output. + * @param[in] led_num: number of addressable LEDs. + * @return + * LED strip instance or NULL + */ +led_strip_t * led_strip_init(uint8_t channel, uint8_t gpio, uint16_t led_num); + +/** + * @brief Denit the RMT peripheral. + * + * @param[in] strip: LED strip + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t led_strip_denit(led_strip_t *strip); + #ifdef __cplusplus } #endif diff --git a/examples/peripherals/rmt/led_strip/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/common_components/led_strip/led_strip_rmt_ws2812.c similarity index 86% rename from examples/peripherals/rmt/led_strip/components/led_strip/src/led_strip_rmt_ws2812.c rename to examples/common_components/led_strip/led_strip_rmt_ws2812.c index 025d3c59016..4beaf78f04e 100644 --- a/examples/peripherals/rmt/led_strip/components/led_strip/src/led_strip_rmt_ws2812.c +++ b/examples/common_components/led_strip/led_strip_rmt_ws2812.c @@ -19,6 +19,8 @@ #include "led_strip.h" #include "driver/rmt.h" +#define RMT_TX_CHANNEL RMT_CHANNEL_0 + static const char *TAG = "ws2812"; #define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ do \ @@ -169,3 +171,37 @@ led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) err: return ret; } + +led_strip_t * led_strip_init(uint8_t channel, uint8_t gpio, uint16_t led_num) +{ + static led_strip_t *pStrip; + + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(gpio, channel); + // set counter clock to 40MHz + config.clk_div = 2; + + ESP_ERROR_CHECK(rmt_config(&config)); + ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); + + // install ws2812 driver + led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(led_num, (led_strip_dev_t)config.channel); + + pStrip = led_strip_new_rmt_ws2812(&strip_config); + + if ( !pStrip ) { + ESP_LOGE(TAG, "install WS2812 driver failed"); + return NULL; + } + + // Clear LED strip (turn off all LEDs) + ESP_ERROR_CHECK(pStrip->clear(pStrip, 100)); + + return pStrip; +} + +esp_err_t led_strip_denit(led_strip_t *strip) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + ESP_ERROR_CHECK(rmt_driver_uninstall(ws2812->rmt_channel)); + return strip->del(strip); +} diff --git a/examples/get-started/blink/CMakeLists.txt b/examples/get-started/blink/CMakeLists.txt index 33a52a5d5da..0543ecd6f23 100644 --- a/examples/get-started/blink/CMakeLists.txt +++ b/examples/get-started/blink/CMakeLists.txt @@ -2,5 +2,7 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(blink) diff --git a/examples/get-started/blink/Makefile b/examples/get-started/blink/Makefile index 5a04497aa6a..1ad06118b3e 100644 --- a/examples/get-started/blink/Makefile +++ b/examples/get-started/blink/Makefile @@ -5,4 +5,6 @@ PROJECT_NAME := blink +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/led_strip + include $(IDF_PATH)/make/project.mk diff --git a/examples/get-started/blink/README.md b/examples/get-started/blink/README.md index 10590f623e6..b8b21da6a8e 100644 --- a/examples/get-started/blink/README.md +++ b/examples/get-started/blink/README.md @@ -1,5 +1,63 @@ # Blink Example -Starts a FreeRTOS task to blink an LED +(See the README.md file in the upper level 'examples' directory for more information about examples.) -See the README.md file in the upper level 'examples' directory for more information about examples. +This example demonstrates how to blink a LED using GPIO or RMT for the addressable LED, i.e. [WS2812](http://www.world-semi.com/Certifications/WS2812B.html). + +See the RMT examples in the [RMT Peripheral](../../peripherals/rmt) for more information about how to use it. + +## How to Use Example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. + +### Hardware Required + +* A development board with ESP32/ESP32-S2/ESP32-C3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for Power supply and programming + +Some development boards use an addressable LED instead of a regular one. These development boards include: + +| Board | LED type | Pin | +| -------------------- | -------------------- | -------------------- | +| ESP32-C3-DevKitC-1 | Addressable | GPIO8 | +| ESP32-C3-DevKitM-1 | Addressable | GPIO8 | +| ESP32-S2-DevKitM-1 | Addressable | GPIO18 | +| ESP32-S2-Saola-1 | Addressable | GPIO18 | + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it. + +### Configure the Project + +Open the project configuration menu (`idf.py menuconfig`). + +In the `Example Configuration` menu: + +* Select the LED type in the `Blink LED type` option. + * * Use `GPIO` for regular LED blink. + * * Use `RMT` for addressable LED blink. + * * * Use `RMT Channel` to select the RMT peripheral channel. +* Set the GPIO number used for the signal in the `Blink GPIO number` option. +* Set the blinking period in the `Blink period in ms` option. + + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +As you run the example, you will see the LED blinking, according to the previously defined period. For the addressable LED, you can also change the LED color by setting the `pStrip_a->set_pixel(pStrip_a, 0, 16, 16, 16);` (LED Strip, Pixel Number, Red, Green, Blue) with values from 0 to 255 in the `blink.c` file. + +Note: The color order could be different according to the LED model. + +The pixel number indicates the pixel position in the LED strip. For a single LED, use 0. + +## Troubleshooting + +* If the LED isn't blinking, check the GPIO or the LED type selection in the `Example Configuration` menu. + +For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/get-started/blink/main/Kconfig.projbuild b/examples/get-started/blink/main/Kconfig.projbuild index 09f282c826b..98bc61b8a78 100644 --- a/examples/get-started/blink/main/Kconfig.projbuild +++ b/examples/get-started/blink/main/Kconfig.projbuild @@ -1,14 +1,46 @@ menu "Example Configuration" + choice BLINK_LED + prompt "Blink LED type" + default BLINK_LED_RMT if IDF_TARGET_ESP32C3 + default BLINK_LED_RMT if IDF_TARGET_ESP32S2 + default BLINK_LED_GPIO + help + Defines the default peripheral for blink example + + config BLINK_LED_GPIO + bool "GPIO" + config BLINK_LED_RMT + bool "RMT - Addressable LED" + endchoice + + config BLINK_LED_RMT_CHANNEL + depends on BLINK_LED_RMT + int "RMT Channel" + range 0 7 + default 0 + help + Set the RMT peripheral channel. + ESP32 RMT channel from 0 to 7 + ESP32-S2 RMT channel from 0 to 3 + ESP32-C3 RMT channel from 0 to 1 + config BLINK_GPIO int "Blink GPIO number" range 0 34 + default 8 if IDF_TARGET_ESP32C3 + default 18 if IDF_TARGET_ESP32S2 default 5 help - GPIO number (IOxx) to blink on and off. - + GPIO number (IOxx) to blink on and off or the RMT signal for the addressable LED. Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink. - GPIOs 35-39 are input-only so cannot be used as outputs. + config BLINK_PERIOD + int "Blink period in ms" + range 10 3600000 + default 1000 + help + Define the blinking period in milliseconds. + endmenu diff --git a/examples/get-started/blink/main/blink.c b/examples/get-started/blink/main/blink.c index 8d41246e84d..94f48b2d1bf 100644 --- a/examples/get-started/blink/main/blink.c +++ b/examples/get-started/blink/main/blink.c @@ -10,32 +10,74 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" +#include "esp_log.h" +#include "led_strip.h" #include "sdkconfig.h" -/* Can use project configuration menu (idf.py menuconfig) to choose the GPIO to blink, +static const char *TAG = "example"; + +/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink, or you can edit the following line and set a number here. */ #define BLINK_GPIO CONFIG_BLINK_GPIO -void app_main(void) +static uint8_t s_led_state = 0; + +#ifdef CONFIG_BLINK_LED_RMT +static led_strip_t *pStrip_a; + +static void blink_led(void) +{ + /* If the addressable LED is enabled */ + if (s_led_state) { + /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */ + pStrip_a->set_pixel(pStrip_a, 0, 16, 16, 16); + /* Refresh the strip to send data */ + pStrip_a->refresh(pStrip_a, 100); + } else { + /* Set all LED off to clear all pixels */ + pStrip_a->clear(pStrip_a, 50); + } +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink addressable LED!"); + /* LED strip initialization with the GPIO and pixels number*/ + pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, BLINK_GPIO, 1); + /* Set all LED off to clear all pixels */ + pStrip_a->clear(pStrip_a, 50); +} + +#elif CONFIG_BLINK_LED_GPIO + +static void blink_led(void) +{ + /* Set the GPIO level according to the state (LOW or HIGH)*/ + gpio_set_level(BLINK_GPIO, s_led_state); +} + +static void configure_led(void) { - /* Configure the IOMUX register for pad BLINK_GPIO (some pads are - muxed to GPIO on reset already, but some default to other - functions and need to be switched to GPIO. Consult the - Technical Reference for a list of pads and their default - functions.) - */ + ESP_LOGI(TAG, "Example configured to blink GPIO LED!"); gpio_reset_pin(BLINK_GPIO); /* Set the GPIO as a push/pull output */ gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); - while(1) { - /* Blink off (output low) */ - printf("Turning off the LED\n"); - gpio_set_level(BLINK_GPIO, 0); - vTaskDelay(1000 / portTICK_PERIOD_MS); - /* Blink on (output high) */ - printf("Turning on the LED\n"); - gpio_set_level(BLINK_GPIO, 1); - vTaskDelay(1000 / portTICK_PERIOD_MS); +} + +#endif + +void app_main(void) +{ + + /* Configure the peripheral according to the LED type */ + configure_led(); + + while (1) { + ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF"); + blink_led(); + /* Toggle the LED state */ + s_led_state = !s_led_state; + vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); } } diff --git a/examples/peripherals/rmt/led_strip/CMakeLists.txt b/examples/peripherals/rmt/led_strip/CMakeLists.txt index 4ccaa434154..020754f1e18 100644 --- a/examples/peripherals/rmt/led_strip/CMakeLists.txt +++ b/examples/peripherals/rmt/led_strip/CMakeLists.txt @@ -2,5 +2,7 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(led_strip) diff --git a/examples/peripherals/rmt/led_strip/Makefile b/examples/peripherals/rmt/led_strip/Makefile index ff7ac7ce6b5..8baa6346271 100644 --- a/examples/peripherals/rmt/led_strip/Makefile +++ b/examples/peripherals/rmt/led_strip/Makefile @@ -5,4 +5,6 @@ PROJECT_NAME := led_strip +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/led_strip + include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/rmt/led_strip/README.md b/examples/peripherals/rmt/led_strip/README.md index 0560e735986..23759277dd4 100644 --- a/examples/peripherals/rmt/led_strip/README.md +++ b/examples/peripherals/rmt/led_strip/README.md @@ -28,9 +28,9 @@ GPIO18 +-----------------+---|>| (WS2812) Open the project configuration menu (`idf.py menuconfig`). -In the `Example Connection Configuration` menu: +In the `Example Configuration` menu: -* Set the GPIO number used for transmitting the IR signal under `RMT TX GPIO` optin. +* Set the GPIO number used for transmitting the IR signal under `RMT TX GPIO` option. * Set the number of LEDs in a strip under `Number of LEDS in a strip` option. ### Build and Flash diff --git a/examples/peripherals/rmt/led_strip/components/led_strip/CMakeLists.txt b/examples/peripherals/rmt/led_strip/components/led_strip/CMakeLists.txt deleted file mode 100644 index 8266c5a1c80..00000000000 --- a/examples/peripherals/rmt/led_strip/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") diff --git a/examples/peripherals/rmt/led_strip/components/led_strip/component.mk b/examples/peripherals/rmt/led_strip/components/led_strip/component.mk deleted file mode 100644 index 24cab8b6375..00000000000 --- a/examples/peripherals/rmt/led_strip/components/led_strip/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := include - -COMPONENT_SRCDIRS := src