Переглянути джерело

Get started example update for addressable LED compatibility.

 Added the RMT/addr LED blink to the example and more detailed README.md
 Moved component/led_strip to common_components
 Added missing README file to common_components/led_strip
 README file update
 Makefile and Kconfig fixed for led_strip component
 Fixing end-of-line on main/blink.c
 Component updated to handle multiple instances
 Added note on the RMT channel number (ESP32 and ESP32-S2)
 Removed components folder from rmt/led_strip example and README updated
 Changed the led_strip_denit function and added ESP32-C3 RMT info on channel configuration
 Updates on README, Kconfig default settings and configure_led() function added
pedro.minatel 5 роки тому
батько
коміт
cccdb3e4aa

+ 4 - 0
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"
+                    )

+ 16 - 0
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.

+ 0 - 0
examples/common_components/led_strip/component.mk


+ 21 - 0
examples/peripherals/rmt/led_strip/components/led_strip/include/led_strip.h → 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

+ 36 - 0
examples/peripherals/rmt/led_strip/components/led_strip/src/led_strip_rmt_ws2812.c → 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);
+}

+ 2 - 0
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)

+ 2 - 0
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

+ 60 - 2
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 <chip_name>`.
+
+### 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.

+ 35 - 3
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

+ 59 - 17
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);
     }
 }

+ 2 - 0
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)

+ 2 - 0
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

+ 2 - 2
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

+ 0 - 7
examples/peripherals/rmt/led_strip/components/led_strip/CMakeLists.txt

@@ -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 "")

+ 0 - 3
examples/peripherals/rmt/led_strip/components/led_strip/component.mk

@@ -1,3 +0,0 @@
-COMPONENT_ADD_INCLUDEDIRS := include
-
-COMPONENT_SRCDIRS := src