From 640d3d9411e8752ef92501cf29c20c089bd297cc Mon Sep 17 00:00:00 2001 From: Li Junru Date: Wed, 17 Jan 2024 15:08:59 +0800 Subject: [PATCH] example: add led indicator example --- .gitlab/ci/build.yml | 11 + .gitlab/ci/rules.yml | 15 ++ components/led/led_indicator/CHANGELOG.md | 6 + .../led/led_indicator/idf_component.yml | 4 +- .../led/led_indicator/include/led_ledc.h | 1 - .../led/led_indicator/src/led_indicator.c | 14 +- .../test_apps/main/test_led_indicator.c | 2 +- examples/.build-rules.yml | 8 + .../cmd_led_indicator/CMakeLists.txt | 3 + .../cmd_led_indicator/cmd_led_indicator.c | 102 ++++++++ .../cmd_led_indicator/cmd_led_indicator.h | 40 +++ .../lighting/indicator/gpio/CMakeLists.txt | 6 + examples/lighting/indicator/gpio/README.md | 42 ++++ .../indicator/gpio/main/CMakeLists.txt | 2 + .../indicator/gpio/main/Kconfig.projbuild | 19 ++ .../indicator/gpio/main/idf_component.yml | 9 + examples/lighting/indicator/gpio/main/main.c | 152 ++++++++++++ .../lighting/indicator/ledc/CMakeLists.txt | 6 + examples/lighting/indicator/ledc/README.md | 44 ++++ .../indicator/ledc/main/CMakeLists.txt | 2 + .../indicator/ledc/main/Kconfig.projbuild | 25 ++ .../indicator/ledc/main/idf_component.yml | 9 + examples/lighting/indicator/ledc/main/main.c | 180 ++++++++++++++ .../lighting/indicator/rgb/CMakeLists.txt | 6 + examples/lighting/indicator/rgb/README.md | 47 ++++ .../indicator/rgb/main/CMakeLists.txt | 2 + .../indicator/rgb/main/Kconfig.projbuild | 49 ++++ .../indicator/rgb/main/idf_component.yml | 9 + examples/lighting/indicator/rgb/main/main.c | 199 +++++++++++++++ .../indicator/ws2812_strips/CMakeLists.txt | 6 + .../indicator/ws2812_strips/README.md | 52 ++++ .../ws2812_strips/main/CMakeLists.txt | 2 + .../ws2812_strips/main/Kconfig.projbuild | 24 ++ .../ws2812_strips/main/idf_component.yml | 9 + .../indicator/ws2812_strips/main/main.c | 229 ++++++++++++++++++ 35 files changed, 1328 insertions(+), 8 deletions(-) create mode 100644 examples/lighting/indicator/components/cmd_led_indicator/CMakeLists.txt create mode 100644 examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.c create mode 100644 examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.h create mode 100644 examples/lighting/indicator/gpio/CMakeLists.txt create mode 100644 examples/lighting/indicator/gpio/README.md create mode 100644 examples/lighting/indicator/gpio/main/CMakeLists.txt create mode 100644 examples/lighting/indicator/gpio/main/Kconfig.projbuild create mode 100644 examples/lighting/indicator/gpio/main/idf_component.yml create mode 100644 examples/lighting/indicator/gpio/main/main.c create mode 100644 examples/lighting/indicator/ledc/CMakeLists.txt create mode 100644 examples/lighting/indicator/ledc/README.md create mode 100644 examples/lighting/indicator/ledc/main/CMakeLists.txt create mode 100644 examples/lighting/indicator/ledc/main/Kconfig.projbuild create mode 100644 examples/lighting/indicator/ledc/main/idf_component.yml create mode 100644 examples/lighting/indicator/ledc/main/main.c create mode 100644 examples/lighting/indicator/rgb/CMakeLists.txt create mode 100644 examples/lighting/indicator/rgb/README.md create mode 100644 examples/lighting/indicator/rgb/main/CMakeLists.txt create mode 100644 examples/lighting/indicator/rgb/main/Kconfig.projbuild create mode 100644 examples/lighting/indicator/rgb/main/idf_component.yml create mode 100644 examples/lighting/indicator/rgb/main/main.c create mode 100644 examples/lighting/indicator/ws2812_strips/CMakeLists.txt create mode 100644 examples/lighting/indicator/ws2812_strips/README.md create mode 100644 examples/lighting/indicator/ws2812_strips/main/CMakeLists.txt create mode 100644 examples/lighting/indicator/ws2812_strips/main/Kconfig.projbuild create mode 100644 examples/lighting/indicator/ws2812_strips/main/idf_component.yml create mode 100644 examples/lighting/indicator/ws2812_strips/main/main.c diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index ff394865f..49a9af00f 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -318,6 +318,17 @@ build_example_gprof_gprof_simple: variables: EXAMPLE_DIR: examples/gprof/gprof_simple +build_example_lighting_indicator: + extends: + - .build_examples_template + - .rules:build:example_lighting_indicator + parallel: + matrix: + - IMAGE: espressif/idf:release-v5.1 + - IMAGE: espressif/idf:release-v4.4 + variables: + EXAMPLE_DIR: examples/lighting/indicator + build_example_lighting_lightbulb: extends: - .build_examples_template diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index d1405d176..26bdd92e5 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -314,6 +314,9 @@ .patterns-example_get_started_button_power_save: &patterns-example_get_started_button_power_save - "examples/get-started/button_power_save/**/*" +.patterns-example_lighting_indicator: &patterns-example_lighting_indicator + - "examples/lighting/indicator/**/*" + .patterns-example_lighting_lightbulb: &patterns-example_lighting_lightbulb - "examples/lighting/lightbulb/**/*" @@ -683,6 +686,18 @@ - <<: *if-dev-push changes: *patterns-example_gprof_gprof_simple +.rules:build:example_lighting_indicator: + rules: + - <<: *if-protected + - <<: *if-label-build + - <<: *if-trigger-job + - <<: *if-dev-push + changes: *patterns-build_system + - <<: *if-dev-push + changes: *patterns-components_led_led_indicator + - <<: *if-dev-push + changes: *patterns-example_lighting_indicator + .rules:build:example_lighting_lightbulb: rules: - <<: *if-protected diff --git a/components/led/led_indicator/CHANGELOG.md b/components/led/led_indicator/CHANGELOG.md index 734e3e98d..1a3026455 100644 --- a/components/led/led_indicator/CHANGELOG.md +++ b/components/led/led_indicator/CHANGELOG.md @@ -1,6 +1,12 @@ # ChangeLog +## v0.9.1 - 2024-1-17 + +* Resolve the issue of calling preempt_stop with a specified blink_type that is not running, causing the current preemptive blink to stop. +* Resolve the issue of the RGB ring not functioning. +* Ensure that preempt_start stops the previous preemptive blink. + ## v0.9.0 - 2023-11-28 ### BUG FIX diff --git a/components/led/led_indicator/idf_component.yml b/components/led/led_indicator/idf_component.yml index 9cb76f932..8660966d1 100644 --- a/components/led/led_indicator/idf_component.yml +++ b/components/led/led_indicator/idf_component.yml @@ -1,4 +1,4 @@ -version: "0.9.0" +version: "0.9.1" description: LED indicator driver url: https://github.com/espressif/esp-iot-solution/tree/master/components/led/led_indicator dependencies: @@ -7,3 +7,5 @@ dependencies: version: ">=2.5.2" public: true cmake_utilities: "0.*" +examples: + - path: ../../../examples/lighting/indicator diff --git a/components/led/led_indicator/include/led_ledc.h b/components/led/led_indicator/include/led_ledc.h index ff8dab97e..3b76b23c7 100644 --- a/components/led/led_indicator/include/led_ledc.h +++ b/components/led/led_indicator/include/led_ledc.h @@ -7,7 +7,6 @@ #pragma once #include "driver/ledc.h" -// #include "led_common.h" #ifdef __cplusplus extern "C" { diff --git a/components/led/led_indicator/src/led_indicator.c b/components/led/led_indicator/src/led_indicator.c index 9109c7b33..f538aed09 100644 --- a/components/led/led_indicator/src/led_indicator.c +++ b/components/led/led_indicator/src/led_indicator.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -276,8 +276,7 @@ static void _blink_list_runner(TimerHandle_t xTimer) led_indicator_hsv2rgb(p_led_indicator->current_fade_value.value, &r, &g, &b); led_indicator_ihsv_t irgb_value = { - .value = (r << 16) | (g << 8) | b, - .i = p_blink_step_value.i, + .value = SET_IRGB(p_blink_step_value.i, r, g, b), }; p_led_indicator->hal_indicator_set_rgb(p_led_indicator->hardware_data, irgb_value.value); @@ -701,6 +700,9 @@ esp_err_t led_indicator_preempt_start(led_indicator_handle_t handle, int blink_t LED_INDICATOR_CHECK(p_led_indicator->blink_lists[blink_type] != NULL, "undefined blink_type", return ESP_ERR_INVALID_ARG); xSemaphoreTake(p_led_indicator->mutex, portMAX_DELAY); + if (p_led_indicator->preempt_blink != NULL_PREEMPT_BLINK) { + p_led_indicator->p_blink_steps[p_led_indicator->preempt_blink] = LED_BLINK_STOP; // Maker sure the last preempt blink is stopped + } p_led_indicator->p_blink_steps[blink_type] = 0; p_led_indicator->preempt_blink = blink_type; _blink_list_switch(p_led_indicator); //stop and switch to next blink steps @@ -720,8 +722,10 @@ esp_err_t led_indicator_preempt_stop(led_indicator_handle_t handle, int blink_ty LED_INDICATOR_CHECK(blink_type >= 0 && blink_type < p_led_indicator->blink_list_num, "blink_type out of range", return ESP_FAIL); LED_INDICATOR_CHECK(p_led_indicator->blink_lists[blink_type] != NULL, "undefined blink_type", return ESP_ERR_INVALID_ARG); xSemaphoreTake(p_led_indicator->mutex, portMAX_DELAY); - p_led_indicator->p_blink_steps[blink_type] = LED_BLINK_STOP; - p_led_indicator->preempt_blink = NULL_PREEMPT_BLINK; + if (p_led_indicator->preempt_blink == blink_type) { + p_led_indicator->p_blink_steps[blink_type] = LED_BLINK_STOP; + p_led_indicator->preempt_blink = NULL_PREEMPT_BLINK; + } _blink_list_switch(p_led_indicator); //stop and switch to next blink steps xSemaphoreGive(p_led_indicator->mutex); diff --git a/components/led/led_indicator/test_apps/main/test_led_indicator.c b/components/led/led_indicator/test_apps/main/test_led_indicator.c index faa6439ba..e654608f6 100644 --- a/components/led/led_indicator/test_apps/main/test_led_indicator.c +++ b/components/led/led_indicator/test_apps/main/test_led_indicator.c @@ -927,7 +927,7 @@ TEST_CASE("TEST LED RGB control Real time ", "[LED RGB][Real time]") { led_strip_config_t strip_config = { .strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line - .max_leds = MAX_LED_NUM, // The number of LEDs in the strip, + .max_leds = MAX_LED_NUM, // The number of LEDs in the strip, .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip .led_model = LED_MODEL_WS2812, // LED strip model .flags.invert_out = false, // whether to invert the output signal diff --git a/examples/.build-rules.yml b/examples/.build-rules.yml index 851ca1ee1..6db0c9d11 100644 --- a/examples/.build-rules.yml +++ b/examples/.build-rules.yml @@ -102,6 +102,14 @@ examples/get-started/button_power_save: enable: - if: INCLUDE_DEFAULT == 1 +examples/lighting/indicator: + enable: + - if: INCLUDE_DEFAULT == 1 + +examples/lighting/indicator/ws2812_strips: + enable: + - if: SOC_RMT_SUPPORTED == 1 + examples/lighting/lightbulb: enable: - if: INCLUDE_DEFAULT == 1 diff --git a/examples/lighting/indicator/components/cmd_led_indicator/CMakeLists.txt b/examples/lighting/indicator/components/cmd_led_indicator/CMakeLists.txt new file mode 100644 index 000000000..f969640e5 --- /dev/null +++ b/examples/lighting/indicator/components/cmd_led_indicator/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + INCLUDE_DIRS "." + REQUIRES console) diff --git a/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.c b/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.c new file mode 100644 index 000000000..957244644 --- /dev/null +++ b/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.c @@ -0,0 +1,102 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cmd_led_indicator.h" +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "esp_log.h" +#include "esp_check.h" + +static struct { + struct arg_int *start; + struct arg_int *stop; + struct arg_int *preempt_start; + struct arg_int *preempt_stop; + struct arg_end *end; +} cmd_indicator_args; + +typedef struct { + led_indicator_cmd_cb cmd_cb; +} cmd_led_indicator_cmd_t; + +static const char *TAG = "cmd_led_indicator"; +static cmd_led_indicator_cmd_t cmd_led_indicator_cmd = {0}; + +static int cmd_br_fdb_remove(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &cmd_indicator_args); \ + if (nerrors != 0) { + arg_print_errors(stderr, cmd_indicator_args.end, argv[0]); + return 1; + } + + if (cmd_indicator_args.start->count > 0) { + cmd_led_indicator_cmd.cmd_cb(START, cmd_indicator_args.start->ival[0]); + } else if (cmd_indicator_args.stop->count > 0) { + cmd_led_indicator_cmd.cmd_cb(STOP, cmd_indicator_args.stop->ival[0]); + } else if (cmd_indicator_args.preempt_start->count > 0) { + cmd_led_indicator_cmd.cmd_cb(PREEMPT_START, cmd_indicator_args.preempt_start->ival[0]); + } else if (cmd_indicator_args.preempt_stop->count > 0) { + cmd_led_indicator_cmd.cmd_cb(PREEMPT_STOP, cmd_indicator_args.preempt_stop->ival[0]); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + + return 0; +} + +esp_err_t cmd_led_indicator_init(cmd_led_indicator_t *cmd_led_indicator) +{ + ESP_RETURN_ON_FALSE(cmd_led_indicator != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd_led_indicator is NULL"); + ESP_RETURN_ON_FALSE(cmd_led_indicator->cmd_cb != NULL, ESP_ERR_INVALID_ARG, TAG, "cmd_led_indicator->cmd_cb is NULL"); + + cmd_led_indicator_cmd.cmd_cb = cmd_led_indicator->cmd_cb; + uint32_t max_mode = cmd_led_indicator->mode_count - 1; + + esp_console_repl_t *repl = NULL; + esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); + + /* Register commands */ + esp_console_register_help_command(); + +#if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) || defined(CONFIG_ESP_CONSOLE_UART_CUSTOM) + esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); + ESP_RETURN_ON_ERROR(esp_console_new_repl_uart(&hw_config, &repl_config, &repl), TAG, "Failed to initialize UART REPL"); + +#elif defined(CONFIG_ESP_CONSOLE_USB_CDC) + esp_console_dev_usb_cdc_config_t hw_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT(); + ESP_RETURN_ON_ERROR(esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl), TAG, "Failed to initialize USB CDC REPL"); + +#elif defined(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) + esp_console_dev_usb_serial_jtag_config_t hw_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT(); + ESP_RETURN_ON_ERROR(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl), TAG, "Failed to initialize USB serial REPL"); + +#else +#error Unsupported console type +#endif + + cmd_indicator_args.start = arg_intn("s", "start", "", 0, max_mode, "Start blinking the mode with given index"); + cmd_indicator_args.stop = arg_intn("e", "stop", "", 0, max_mode, "Stop blinking the mode with given index"); + cmd_indicator_args.preempt_start = arg_intn("p", "preempt_start", "", 0, max_mode, "Preemptively start blinking the mode with given index"); + cmd_indicator_args.preempt_stop = arg_intn("x", "preempt_stop", "", 0, max_mode, "Preemptively stop blinking the mode with given index"); + cmd_indicator_args.end = arg_end(4); + + const esp_console_cmd_t cmd = { + .command = "led", + .help = "LED indicator commands", + .hint = NULL, + .func = &cmd_br_fdb_remove, + .argtable = &cmd_indicator_args + }; + + ESP_RETURN_ON_ERROR(esp_console_cmd_register(&cmd), TAG, "Failed to register command"); + ESP_RETURN_ON_ERROR(esp_console_start_repl(repl), TAG, "Failed to start REPL"); + + return ESP_OK; +} diff --git a/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.h b/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.h new file mode 100644 index 000000000..7caff507d --- /dev/null +++ b/examples/lighting/indicator/components/cmd_led_indicator/cmd_led_indicator.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" + +typedef enum { + START = 0, + STOP, + PREEMPT_START, + PREEMPT_STOP, +} cmd_type_t; + +typedef void (*led_indicator_cmd_cb)(cmd_type_t cmd_type, uint32_t mode_index); + +typedef struct { + uint32_t mode_count; + led_indicator_cmd_cb cmd_cb; +} cmd_led_indicator_t; + +/** + * @brief install led indicator cmd + * + * @param cmd_led_indicator led indicator cmd cfg + * @return + * ESP_OK success + * ESP_FAIL failed + */ +esp_err_t cmd_led_indicator_init(cmd_led_indicator_t *cmd_led_indicator); + +#ifdef __cplusplus +} +#endif diff --git a/examples/lighting/indicator/gpio/CMakeLists.txt b/examples/lighting/indicator/gpio/CMakeLists.txt new file mode 100644 index 000000000..26113ae4b --- /dev/null +++ b/examples/lighting/indicator/gpio/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gpio_led_indicator) diff --git a/examples/lighting/indicator/gpio/README.md b/examples/lighting/indicator/gpio/README.md new file mode 100644 index 000000000..022fa5d9c --- /dev/null +++ b/examples/lighting/indicator/gpio/README.md @@ -0,0 +1,42 @@ +## LED Indicator WS2812 + +* Support ON/OFF + +### Hardware Required + +* LED + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set `EXAMPLE_GPIO_NUM` to set led gpio. +* Set `EXAMPLE_GPIO_ACTIVE_LEVEL` to set gpio level when led light + +### How to USE + +If the macro `EXAMPLE_ENABLE_CONSOLE_CONTROL` is enabled, please use the following method for control; otherwise, the indicator lights will flash sequentially in order. + +* Help + ```shell + help + ``` + +* Immediate display mode, without considering priority. + ```shell + led -p 0 # Start + led -p 2 # Start + led -x 2 # Stop + ``` + +* Display mode based on priority. + ```shell + led -s 0 # Start 0 + led -s 2 # Start 2 + led -e 2 # Stop 2 + ``` + +Note: +> Support replacing the LED with an active buzzer to achieve the functionality of a buzzer indicator. \ No newline at end of file diff --git a/examples/lighting/indicator/gpio/main/CMakeLists.txt b/examples/lighting/indicator/gpio/main/CMakeLists.txt new file mode 100644 index 000000000..8a9d914e1 --- /dev/null +++ b/examples/lighting/indicator/gpio/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/lighting/indicator/gpio/main/Kconfig.projbuild b/examples/lighting/indicator/gpio/main/Kconfig.projbuild new file mode 100644 index 000000000..b93dae6e8 --- /dev/null +++ b/examples/lighting/indicator/gpio/main/Kconfig.projbuild @@ -0,0 +1,19 @@ +menu "Example Configuration" + + config EXAMPLE_GPIO_NUM + int "GPIO number" + default 1 + help + GPIO number to use for example. + + config EXAMPLE_GPIO_ACTIVE_LEVEL + bool "GPIO active level" + default y + help + GPIO active level. + + config EXAMPLE_ENABLE_CONSOLE_CONTROL + bool "Enable console control" + default n + +endmenu diff --git a/examples/lighting/indicator/gpio/main/idf_component.yml b/examples/lighting/indicator/gpio/main/idf_component.yml new file mode 100644 index 000000000..5f328acff --- /dev/null +++ b/examples/lighting/indicator/gpio/main/idf_component.yml @@ -0,0 +1,9 @@ +version: "0.0.1" +dependencies: + idf: ">=4.4" + cmd_led_indicator: + version: "*" + override_path: "../../components/cmd_led_indicator" + led_indicator: + version: "*" + override_path: "../../../../../components/led/led_indicator" diff --git a/examples/lighting/indicator/gpio/main/main.c b/examples/lighting/indicator/gpio/main/main.c new file mode 100644 index 000000000..244554a10 --- /dev/null +++ b/examples/lighting/indicator/gpio/main/main.c @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "cmd_led_indicator.h" +#include "esp_log.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "led_indicator.h" +#include "inttypes.h" + +#define GPIO_LED_PIN CONFIG_EXAMPLE_GPIO_NUM +#define GPIO_ACTIVE_LEVEL CONFIG_EXAMPLE_GPIO_ACTIVE_LEVEL + +static const char *TAG = "led_gpio"; +static led_indicator_handle_t led_handle = NULL; + +/** + * @brief Define blinking type and priority. + * + */ +enum { + BLINK_DOUBLE = 0, + BLINK_TRIPLE, + BLINK_SLOW, + BLINK_FAST, + BLINK_MAX, +}; + +/** + * @brief Blinking twice times has a priority level of 0 (highest). + * + */ +static const blink_step_t double_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Blinking three times has a priority level of 1. + * + */ +static const blink_step_t triple_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Slow blinking takes priority level 2. + * + */ +static const blink_step_t slow_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 1000}, + {LED_BLINK_HOLD, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Fast blinking has priority level 3(lowest). + * + */ +static const blink_step_t fast_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 100}, + {LED_BLINK_HOLD, LED_STATE_OFF, 100}, + {LED_BLINK_LOOP, 0, 0}, +}; + +blink_step_t const *led_mode[] = { + [BLINK_DOUBLE] = double_blink, + [BLINK_TRIPLE] = triple_blink, + [BLINK_SLOW] = slow_blink, + [BLINK_FAST] = fast_blink, + [BLINK_MAX] = NULL, +}; + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL +static void led_cmd_cb(cmd_type_t cmd_type, uint32_t mode_index) +{ + switch (cmd_type) { + case START: + led_indicator_start(led_handle, mode_index); + ESP_LOGI(TAG, "start blink: %"PRIu32"", mode_index); + break; + case STOP: + led_indicator_stop(led_handle, mode_index); + ESP_LOGI(TAG, "stop blink: %"PRIu32"", mode_index); + break; + case PREEMPT_START: + led_indicator_preempt_start(led_handle, mode_index); + ESP_LOGI(TAG, "preempt start blink: %"PRIu32"", mode_index); + break; + case PREEMPT_STOP: + led_indicator_preempt_stop(led_handle, mode_index); + ESP_LOGI(TAG, "preempt stop blink: %"PRIu32"", mode_index); + break; + default: + ESP_LOGE(TAG, "unknown cmd type: %d", cmd_type); + break; + } +} +#endif + +void app_main(void) +{ + led_indicator_gpio_config_t gpio_config = { + .gpio_num = GPIO_LED_PIN, + .is_active_level_high = GPIO_ACTIVE_LEVEL, + }; + + const led_indicator_config_t config = { + .mode = LED_GPIO_MODE, + .led_indicator_gpio_config = &gpio_config, + .blink_lists = led_mode, + .blink_list_num = BLINK_MAX, + }; + + led_handle = led_indicator_create(&config); + assert(led_handle != NULL); + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL + cmd_led_indicator_t cmd_led_indicator = { + .cmd_cb = led_cmd_cb, + .mode_count = BLINK_MAX, + }; + + ESP_ERROR_CHECK(cmd_led_indicator_init(&cmd_led_indicator)); +#else + while (1) { + for (int i = 0; i < BLINK_MAX; i++) { + led_indicator_start(led_handle, i); + ESP_LOGI(TAG, "start blink: %d", i); + vTaskDelay(4000 / portTICK_PERIOD_MS); + led_indicator_stop(led_handle, i); + ESP_LOGI(TAG, "stop blink: %d", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +#endif +} diff --git a/examples/lighting/indicator/ledc/CMakeLists.txt b/examples/lighting/indicator/ledc/CMakeLists.txt new file mode 100644 index 000000000..b329c3cdd --- /dev/null +++ b/examples/lighting/indicator/ledc/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ledc_led_indicator) diff --git a/examples/lighting/indicator/ledc/README.md b/examples/lighting/indicator/ledc/README.md new file mode 100644 index 000000000..ecfa00761 --- /dev/null +++ b/examples/lighting/indicator/ledc/README.md @@ -0,0 +1,44 @@ +## LED Indicator WS2812 + +* Support ON/OFF +* Support set brightness +* Support breathe with brightness + +### Hardware Required + +* LED + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set `EXAMPLE_GPIO_NUM` to set led gpio. +* Set `EXAMPLE_GPIO_ACTIVE_LEVEL` to set gpio level when led light + +### How to USE + +If the macro `EXAMPLE_ENABLE_CONSOLE_CONTROL` is enabled, please use the following method for control; otherwise, the indicator lights will flash sequentially in order. + +* Help + ```shell + help + ``` + +* Immediate display mode, without considering priority. + ```shell + led -p 0 # Start + led -p 2 # Start + led -x 2 # Stop + ``` + +* Display mode based on priority. + ```shell + led -s 0 # Start 0 + led -s 2 # Start 2 + led -e 2 # Stop 2 + ``` + +Note: +> Support replacing the LED with a passive buzzer to accomplish the functionality of a buzzer indicator light. \ No newline at end of file diff --git a/examples/lighting/indicator/ledc/main/CMakeLists.txt b/examples/lighting/indicator/ledc/main/CMakeLists.txt new file mode 100644 index 000000000..8a9d914e1 --- /dev/null +++ b/examples/lighting/indicator/ledc/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/lighting/indicator/ledc/main/Kconfig.projbuild b/examples/lighting/indicator/ledc/main/Kconfig.projbuild new file mode 100644 index 000000000..971b21a8c --- /dev/null +++ b/examples/lighting/indicator/ledc/main/Kconfig.projbuild @@ -0,0 +1,25 @@ +menu "Example Configuration" + + config EXAMPLE_GPIO_NUM + int "GPIO number" + default 1 + help + GPIO number to use for example. + + config EXAMPLE_LEDC_CHANNEL + int "LED channel" + default 0 + help + LED channel to use for example. + + config EXAMPLE_GPIO_ACTIVE_LEVEL + bool "GPIO active level" + default y + help + GPIO active level. + + config EXAMPLE_ENABLE_CONSOLE_CONTROL + bool "Enable console control" + default n + +endmenu diff --git a/examples/lighting/indicator/ledc/main/idf_component.yml b/examples/lighting/indicator/ledc/main/idf_component.yml new file mode 100644 index 000000000..5f328acff --- /dev/null +++ b/examples/lighting/indicator/ledc/main/idf_component.yml @@ -0,0 +1,9 @@ +version: "0.0.1" +dependencies: + idf: ">=4.4" + cmd_led_indicator: + version: "*" + override_path: "../../components/cmd_led_indicator" + led_indicator: + version: "*" + override_path: "../../../../../components/led/led_indicator" diff --git a/examples/lighting/indicator/ledc/main/main.c b/examples/lighting/indicator/ledc/main/main.c new file mode 100644 index 000000000..c6e56ebaa --- /dev/null +++ b/examples/lighting/indicator/ledc/main/main.c @@ -0,0 +1,180 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "cmd_led_indicator.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "led_indicator.h" +#include "inttypes.h" + +#define GPIO_LED_PIN CONFIG_EXAMPLE_GPIO_NUM +#define GPIO_ACTIVE_LEVEL CONFIG_EXAMPLE_GPIO_ACTIVE_LEVEL +#define LEDC_LED_CHANNEL CONFIG_EXAMPLE_LEDC_CHANNEL + +static const char *TAG = "led_ledc"; +static led_indicator_handle_t led_handle = NULL; + +/** + * @brief Define blinking type and priority. + * + */ +enum { + BLINK_DOUBLE = 0, + BLINK_TRIPLE, + BLINK_BRIGHT_75_PERCENT, + BLINK_BRIGHT_25_PERCENT, + BLINK_BREATHE_SLOW, + BLINK_BREATHE_FAST, + BLINK_MAX, +}; + +/** + * @brief Blinking twice times has a priority level of 0 (highest). + * + */ +static const blink_step_t double_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Blinking three times has a priority level of 1. + * + */ +static const blink_step_t triple_blink[] = { + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Brightness set to 75% with a priority level of 2. + * + */ +static const blink_step_t bright_75_percent[] = { + {LED_BLINK_BRIGHTNESS, LED_STATE_75_PERCENT, 0}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Brightness set to 25% with a priority level of 3. + * + */ +static const blink_step_t bright_25_percent[] = { + {LED_BLINK_BRIGHTNESS, LED_STATE_25_PERCENT, 0}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Slow breathing with a priority level of 4. + * + */ +static const blink_step_t breath_slow_blink[] = { + {LED_BLINK_HOLD, LED_STATE_OFF, 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 1000}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Fast breathing with a priority level of 5(lowest). + * + */ +static const blink_step_t breath_fast_blink[] = { + {LED_BLINK_HOLD, LED_STATE_OFF, 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 500}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 500}, + {LED_BLINK_LOOP, 0, 0}, +}; + +blink_step_t const *led_mode[] = { + [BLINK_DOUBLE] = double_blink, + [BLINK_TRIPLE] = triple_blink, + [BLINK_BRIGHT_75_PERCENT] = bright_75_percent, + [BLINK_BRIGHT_25_PERCENT] = bright_25_percent, + [BLINK_BREATHE_SLOW] = breath_slow_blink, + [BLINK_BREATHE_FAST] = breath_fast_blink, + [BLINK_MAX] = NULL, +}; + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL +static void led_cmd_cb(cmd_type_t cmd_type, uint32_t mode_index) +{ + switch (cmd_type) { + case START: + led_indicator_start(led_handle, mode_index); + ESP_LOGI(TAG, "start blink: %"PRIu32"", mode_index); + break; + case STOP: + led_indicator_stop(led_handle, mode_index); + ESP_LOGI(TAG, "stop blink: %"PRIu32"", mode_index); + break; + case PREEMPT_START: + led_indicator_preempt_start(led_handle, mode_index); + ESP_LOGI(TAG, "preempt start blink: %"PRIu32"", mode_index); + break; + case PREEMPT_STOP: + led_indicator_preempt_stop(led_handle, mode_index); + ESP_LOGI(TAG, "preempt stop blink: %"PRIu32"", mode_index); + break; + default: + ESP_LOGE(TAG, "unknown cmd type: %d", cmd_type); + break; + } +} +#endif + +void app_main(void) +{ + led_indicator_ledc_config_t ledc_config = { + .is_active_level_high = GPIO_ACTIVE_LEVEL, + .timer_inited = false, + .timer_num = LEDC_TIMER_0, + .gpio_num = GPIO_LED_PIN, + .channel = LEDC_LED_CHANNEL, + }; + + const led_indicator_config_t config = { + .mode = LED_LEDC_MODE, + .led_indicator_ledc_config = &ledc_config, + .blink_lists = led_mode, + .blink_list_num = BLINK_MAX, + }; + + led_handle = led_indicator_create(&config); + assert(led_handle != NULL); + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL + cmd_led_indicator_t cmd_led_indicator = { + .cmd_cb = led_cmd_cb, + .mode_count = BLINK_MAX, + }; + + ESP_ERROR_CHECK(cmd_led_indicator_init(&cmd_led_indicator)); +#else + while (1) { + for (int i = 0; i < BLINK_MAX; i++) { + led_indicator_start(led_handle, i); + ESP_LOGI(TAG, "start blink: %d", i); + vTaskDelay(4000 / portTICK_PERIOD_MS); + led_indicator_stop(led_handle, i); + ESP_LOGI(TAG, "stop blink: %d", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +#endif +} diff --git a/examples/lighting/indicator/rgb/CMakeLists.txt b/examples/lighting/indicator/rgb/CMakeLists.txt new file mode 100644 index 000000000..1e7c038fb --- /dev/null +++ b/examples/lighting/indicator/rgb/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(rgb_led_indicator) diff --git a/examples/lighting/indicator/rgb/README.md b/examples/lighting/indicator/rgb/README.md new file mode 100644 index 000000000..6b193c1df --- /dev/null +++ b/examples/lighting/indicator/rgb/README.md @@ -0,0 +1,47 @@ +## LED Indicator WS2812 + +* Support ON/OFF +* Support set brightness +* Support breathe with brightness +* Support set hsv color +* Support set rgb color +* Support color ring with hsv +* Support color ring with rgb + +### Hardware Required + +* RGB LED + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set `EXAMPLE_GPIO_RED_NUM` to set led red gpio. +* Set `EXAMPLE_GPIO_GREEN_NUM` to set led green gpio. +* Set `EXAMPLE_GPIO_BLUE_NUM` to set led blue gpio. +* Set `EXAMPLE_GPIO_ACTIVE_LEVEL` to set gpio level when led light + +### How to USE + +If the macro `EXAMPLE_ENABLE_CONSOLE_CONTROL` is enabled, please use the following method for control; otherwise, the indicator lights will flash sequentially in order. + +* Help + ```shell + help + ``` + +* Immediate display mode, without considering priority. + ```shell + led -p 0 # Start + led -p 2 # Start + led -x 2 # Stop + ``` + +* Display mode based on priority. + ```shell + led -s 0 # Start 0 + led -s 2 # Start 2 + led -e 2 # Stop 2 + ``` diff --git a/examples/lighting/indicator/rgb/main/CMakeLists.txt b/examples/lighting/indicator/rgb/main/CMakeLists.txt new file mode 100644 index 000000000..8a9d914e1 --- /dev/null +++ b/examples/lighting/indicator/rgb/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/lighting/indicator/rgb/main/Kconfig.projbuild b/examples/lighting/indicator/rgb/main/Kconfig.projbuild new file mode 100644 index 000000000..3a6d89284 --- /dev/null +++ b/examples/lighting/indicator/rgb/main/Kconfig.projbuild @@ -0,0 +1,49 @@ +menu "Example Configuration" + + config EXAMPLE_GPIO_RED_NUM + int "GPIO red number" + default 1 + help + GPIO red number to use for example. + + config EXAMPLE_GPIO_GREEN_NUM + int "GPIO green number" + default 2 + help + GPIO green number to use for example. + + config EXAMPLE_GPIO_BLUE_NUM + int "GPIO blue number" + default 3 + help + GPIO blue number to use for example. + + config EXAMPLE_LEDC_RED_CHANNEL + int "LED RED channel" + default 0 + help + LED RGD channel to use for example. + + config EXAMPLE_LEDC_GREEN_CHANNEL + int "LED GREEN channel" + default 1 + help + LED GREEN channel to use for example. + + config EXAMPLE_LEDC_BLUE_CHANNEL + int "LED BLUE channel" + default 2 + help + LED BLUE channel to use for example. + + config EXAMPLE_GPIO_ACTIVE_LEVEL + bool "GPIO active level" + default y + help + GPIO active level. + + config EXAMPLE_ENABLE_CONSOLE_CONTROL + bool "Enable console control" + default n + +endmenu diff --git a/examples/lighting/indicator/rgb/main/idf_component.yml b/examples/lighting/indicator/rgb/main/idf_component.yml new file mode 100644 index 000000000..5f328acff --- /dev/null +++ b/examples/lighting/indicator/rgb/main/idf_component.yml @@ -0,0 +1,9 @@ +version: "0.0.1" +dependencies: + idf: ">=4.4" + cmd_led_indicator: + version: "*" + override_path: "../../components/cmd_led_indicator" + led_indicator: + version: "*" + override_path: "../../../../../components/led/led_indicator" diff --git a/examples/lighting/indicator/rgb/main/main.c b/examples/lighting/indicator/rgb/main/main.c new file mode 100644 index 000000000..d235aa599 --- /dev/null +++ b/examples/lighting/indicator/rgb/main/main.c @@ -0,0 +1,199 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "cmd_led_indicator.h" +#include "esp_log.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "led_indicator.h" +#include "inttypes.h" + +#define GPIO_LED_RED_PIN CONFIG_EXAMPLE_GPIO_RED_NUM +#define GPIO_LED_GREEN_PIN CONFIG_EXAMPLE_GPIO_GREEN_NUM +#define GPIO_LED_BLUE_PIN CONFIG_EXAMPLE_GPIO_BLUE_NUM +#define GPIO_ACTIVE_LEVEL CONFIG_EXAMPLE_GPIO_ACTIVE_LEVEL +#define LEDC_LED_RED_CHANNEL CONFIG_EXAMPLE_LEDC_RED_CHANNEL +#define LEDC_LED_GREEN_CHANNEL CONFIG_EXAMPLE_LEDC_GREEN_CHANNEL +#define LEDC_LED_BLUE_CHANNEL CONFIG_EXAMPLE_LEDC_BLUE_CHANNEL + +static const char *TAG = "led_rgb"; +static led_indicator_handle_t led_handle = NULL; + +/** + * @brief Define blinking type and priority. + * + */ +enum { + BLINK_DOUBLE_RED = 0, + BLINK_TRIPLE_GREEN, + BLINK_WHITE_BREATHE_SLOW, + BLINK_WHITE_BREATHE_FAST, + BLINK_BLUE_BREATH, + BLINK_COLOR_RING, + BLINK_MAX, +}; + +/** + * @brief Blinking twice times in red has a priority level of 0 (highest). + * + */ +static const blink_step_t double_red_blink[] = { + /*!< Set color to red by R:255 G:0 B:0 */ + {LED_BLINK_RGB, SET_RGB(255, 0, 0), 0}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Blinking three times in green with a priority level of 1. + * + */ +static const blink_step_t triple_green_blink[] = { + /*!< Set color to green by R:0 G:255 B:0 */ + {LED_BLINK_RGB, SET_RGB(0, 255, 0), 0}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Slow breathing in white with a priority level of 2. + * + */ +static const blink_step_t breath_white_slow_blink[] = { + /*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */ + {LED_BLINK_HSV, SET_HSV(0, 0, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 1000}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Fast breathing in white with a priority level of 3. + * + */ +static const blink_step_t breath_white_fast_blink[] = { + /*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */ + {LED_BLINK_HSV, SET_HSV(0, 0, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 500}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 500}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Breathing in green with a priority level of 4. + * + */ +static const blink_step_t breath_blue_blink[] = { + /*!< Set Color to blue and brightness to zero by H:240 S:255 V:0 */ + {LED_BLINK_HSV, SET_HSV(240, MAX_SATURATION, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 1000}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Color gradient with a priority level of 5(lowest). + * + */ +static const blink_step_t color_ring_blink[] = { + /*!< Set Color to RED */ + {LED_BLINK_HSV, SET_HSV(0, MAX_SATURATION, MAX_BRIGHTNESS), 0}, + {LED_BLINK_HSV_RING, SET_HSV(MAX_HUE, MAX_SATURATION, MAX_BRIGHTNESS), 2000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +blink_step_t const *led_mode[] = { + [BLINK_DOUBLE_RED] = double_red_blink, + [BLINK_TRIPLE_GREEN] = triple_green_blink, + [BLINK_WHITE_BREATHE_SLOW] = breath_white_slow_blink, + [BLINK_WHITE_BREATHE_FAST] = breath_white_fast_blink, + [BLINK_BLUE_BREATH] = breath_blue_blink, + [BLINK_COLOR_RING] = color_ring_blink, + [BLINK_MAX] = NULL, +}; + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL +static void led_cmd_cb(cmd_type_t cmd_type, uint32_t mode_index) +{ + switch (cmd_type) { + case START: + led_indicator_start(led_handle, mode_index); + ESP_LOGI(TAG, "start blink: %"PRIu32"", mode_index); + break; + case STOP: + led_indicator_stop(led_handle, mode_index); + ESP_LOGI(TAG, "stop blink: %"PRIu32"", mode_index); + break; + case PREEMPT_START: + led_indicator_preempt_start(led_handle, mode_index); + ESP_LOGI(TAG, "preempt start blink: %"PRIu32"", mode_index); + break; + case PREEMPT_STOP: + led_indicator_preempt_stop(led_handle, mode_index); + ESP_LOGI(TAG, "preempt stop blink: %"PRIu32"", mode_index); + break; + default: + ESP_LOGE(TAG, "unknown cmd type: %d", cmd_type); + break; + } +} +#endif + +void app_main(void) +{ + led_indicator_rgb_config_t rgb_config = { + .is_active_level_high = GPIO_ACTIVE_LEVEL, + .timer_inited = false, + .timer_num = LEDC_TIMER_0, + .red_gpio_num = GPIO_LED_RED_PIN, + .green_gpio_num = GPIO_LED_GREEN_PIN, + .blue_gpio_num = GPIO_LED_BLUE_PIN, + .red_channel = LEDC_LED_RED_CHANNEL, + .green_channel = LEDC_LED_GREEN_CHANNEL, + .blue_channel = LEDC_LED_BLUE_CHANNEL, + }; + + const led_indicator_config_t config = { + .mode = LED_RGB_MODE, + .led_indicator_rgb_config = &rgb_config, + .blink_lists = led_mode, + .blink_list_num = BLINK_MAX, + }; + + led_handle = led_indicator_create(&config); + assert(led_handle != NULL); + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL + cmd_led_indicator_t cmd_led_indicator = { + .cmd_cb = led_cmd_cb, + .mode_count = BLINK_MAX, + }; + + ESP_ERROR_CHECK(cmd_led_indicator_init(&cmd_led_indicator)); +#else + while (1) { + for (int i = 0; i < BLINK_MAX; i++) { + led_indicator_start(led_handle, i); + ESP_LOGI(TAG, "start blink: %d", i); + vTaskDelay(4000 / portTICK_PERIOD_MS); + led_indicator_stop(led_handle, i); + ESP_LOGI(TAG, "stop blink: %d", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +#endif +} diff --git a/examples/lighting/indicator/ws2812_strips/CMakeLists.txt b/examples/lighting/indicator/ws2812_strips/CMakeLists.txt new file mode 100644 index 000000000..bcfaf1ca8 --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(strips_led_indicator) diff --git a/examples/lighting/indicator/ws2812_strips/README.md b/examples/lighting/indicator/ws2812_strips/README.md new file mode 100644 index 000000000..db8df1805 --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/README.md @@ -0,0 +1,52 @@ +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | + +## LED Indicator WS2812 + +* Support ON/OFF +* Support set brightness +* Support breathe with brightness +* Support set hsv color +* Support set rgb color +* Support color ring with hsv +* Support color ring with rgb +* Support set by index + +### Hardware Required + +* WS2812 Strips +* ESP32 SOC Support RMT + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set `EXAMPLE_WS2812_GPIO_NUM` to set ws2812 gpio. +* Set `EXAMPLE_WS2812_STRIPS_NUM` to set ws2812 number. + +### How to USE + +If the macro `EXAMPLE_ENABLE_CONSOLE_CONTROL` is enabled, please use the following method for control; otherwise, the indicator lights will flash sequentially in order. + +* Help + ```shell + help + ``` + +* Immediate display mode, without considering priority. + ```shell + led -p 0 # Start + led -p 2 # Start + led -x 2 # Stop + ``` + +* Display mode based on priority. + ```shell + led -s 0 # Start 0 + led -s 2 # Start 2 + led -e 2 # Stop 2 + ``` + +![flowing leds](https://dl.espressif.com/ae/esp-iot-solution/led_indicator_ws2812.gif) \ No newline at end of file diff --git a/examples/lighting/indicator/ws2812_strips/main/CMakeLists.txt b/examples/lighting/indicator/ws2812_strips/main/CMakeLists.txt new file mode 100644 index 000000000..8a9d914e1 --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/lighting/indicator/ws2812_strips/main/Kconfig.projbuild b/examples/lighting/indicator/ws2812_strips/main/Kconfig.projbuild new file mode 100644 index 000000000..d17543707 --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/main/Kconfig.projbuild @@ -0,0 +1,24 @@ +menu "Example Configuration" + + config EXAMPLE_WS2812_GPIO_NUM + int "WS2812 GPIO number" + default 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32H2 + default 18 if IDF_TARGET_ESP32S2 + default 48 if IDF_TARGET_ESP32S3 + default 8 if IDF_TARGET_ESP32C6 + default 1 + help + 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. + + config EXAMPLE_WS2812_STRIPS_NUM + int "Number of strips" + default 1 + help + Number of strips to control. + + config EXAMPLE_ENABLE_CONSOLE_CONTROL + bool "Enable console control" + default n + +endmenu diff --git a/examples/lighting/indicator/ws2812_strips/main/idf_component.yml b/examples/lighting/indicator/ws2812_strips/main/idf_component.yml new file mode 100644 index 000000000..5f328acff --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/main/idf_component.yml @@ -0,0 +1,9 @@ +version: "0.0.1" +dependencies: + idf: ">=4.4" + cmd_led_indicator: + version: "*" + override_path: "../../components/cmd_led_indicator" + led_indicator: + version: "*" + override_path: "../../../../../components/led/led_indicator" diff --git a/examples/lighting/indicator/ws2812_strips/main/main.c b/examples/lighting/indicator/ws2812_strips/main/main.c new file mode 100644 index 000000000..f41c8358b --- /dev/null +++ b/examples/lighting/indicator/ws2812_strips/main/main.c @@ -0,0 +1,229 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "cmd_led_indicator.h" +#include "esp_log.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "led_indicator.h" +#include "inttypes.h" + +#define WS2812_GPIO_NUM CONFIG_EXAMPLE_WS2812_GPIO_NUM +#define WS2812_STRIPS_NUM CONFIG_EXAMPLE_WS2812_STRIPS_NUM + +#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) + +static const char *TAG = "led_strips"; +static led_indicator_handle_t led_handle = NULL; + +/** + * @brief Define blinking type and priority. + * + */ +enum { + BLINK_DOUBLE_RED = 0, + BLINK_TRIPLE_GREEN, + BLINK_WHITE_BREATHE_SLOW, + BLINK_WHITE_BREATHE_FAST, + BLINK_BLUE_BREATH, + BLINK_COLOR_RING, +#if WS2812_STRIPS_NUM > 1 + BLINK_FLOWING, +#endif + BLINK_MAX, +}; + +/** + * @brief Blinking twice times in red has a priority level of 0 (highest). + * + */ +static const blink_step_t double_red_blink[] = { + /*!< Set color to red by R:255 G:0 B:0 */ + {LED_BLINK_RGB, SET_RGB(255, 0, 0), 0}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Blinking three times in green with a priority level of 1. + * + */ +static const blink_step_t triple_green_blink[] = { + /*!< Set color to green by R:0 G:255 B:0 */ + {LED_BLINK_RGB, SET_RGB(0, 255, 0), 0}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_HOLD, LED_STATE_ON, 500}, + {LED_BLINK_HOLD, LED_STATE_OFF, 500}, + {LED_BLINK_STOP, 0, 0}, +}; + +/** + * @brief Slow breathing in white with a priority level of 2. + * + */ +static const blink_step_t breath_white_slow_blink[] = { + /*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */ + {LED_BLINK_HSV, SET_HSV(0, 0, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 1000}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Fast breathing in white with a priority level of 3. + * + */ +static const blink_step_t breath_white_fast_blink[] = { + /*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */ + {LED_BLINK_HSV, SET_HSV(0, 0, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 500}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 500}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Breathing in green with a priority level of 4. + * + */ +static const blink_step_t breath_blue_blink[] = { + /*!< Set Color to blue and brightness to zero by H:240 S:255 V:0 */ + {LED_BLINK_HSV, SET_HSV(240, MAX_SATURATION, 0), 0}, + {LED_BLINK_BREATHE, LED_STATE_ON, 1000}, + {LED_BLINK_BREATHE, LED_STATE_OFF, 1000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +/** + * @brief Color gradient with a priority level of 5. + * + */ +static const blink_step_t color_ring_blink[] = { + /*!< Set Color to RED */ + {LED_BLINK_HSV, SET_HSV(0, MAX_SATURATION, MAX_BRIGHTNESS), 0}, + {LED_BLINK_HSV_RING, SET_HSV(MAX_HUE, MAX_SATURATION, MAX_BRIGHTNESS), 2000}, + {LED_BLINK_LOOP, 0, 0}, +}; + +#if WS2812_STRIPS_NUM > 1 +/** + * @brief Flowing lights with a priority level of 6(lowest). + * Insert the index:MAX_INDEX to control all the strips + * + */ +static const blink_step_t flowing_blink[] = { + {LED_BLINK_HSV, SET_IHSV(MAX_INDEX, 0, MAX_SATURATION, MAX_BRIGHTNESS), 0}, + {LED_BLINK_HSV_RING, SET_IHSV(MAX_INDEX, MAX_HUE, MAX_SATURATION, MAX_BRIGHTNESS), 2000}, + {LED_BLINK_LOOP, 0, 0}, +}; +#endif + +blink_step_t const *led_mode[] = { + [BLINK_DOUBLE_RED] = double_red_blink, + [BLINK_TRIPLE_GREEN] = triple_green_blink, + [BLINK_WHITE_BREATHE_SLOW] = breath_white_slow_blink, + [BLINK_WHITE_BREATHE_FAST] = breath_white_fast_blink, + [BLINK_BLUE_BREATH] = breath_blue_blink, + [BLINK_COLOR_RING] = color_ring_blink, +#if WS2812_STRIPS_NUM > 1 + [BLINK_FLOWING] = flowing_blink, +#endif + [BLINK_MAX] = NULL, +}; + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL +static void led_cmd_cb(cmd_type_t cmd_type, uint32_t mode_index) +{ + switch (cmd_type) { + case START: + led_indicator_start(led_handle, mode_index); + ESP_LOGI(TAG, "start blink: %"PRIu32"", mode_index); + break; + case STOP: + led_indicator_stop(led_handle, mode_index); + ESP_LOGI(TAG, "stop blink: %"PRIu32"", mode_index); + break; + case PREEMPT_START: + led_indicator_preempt_start(led_handle, mode_index); + ESP_LOGI(TAG, "preempt start blink: %"PRIu32"", mode_index); + break; + case PREEMPT_STOP: + led_indicator_preempt_stop(led_handle, mode_index); + ESP_LOGI(TAG, "preempt stop blink: %"PRIu32"", mode_index); + break; + default: + ESP_LOGE(TAG, "unknown cmd type: %d", cmd_type); + break; + } +} +#endif + +void app_main(void) +{ + + led_strip_config_t strip_config = { + .strip_gpio_num = WS2812_GPIO_NUM, // The GPIO that connected to the LED strip's data line + .max_leds = WS2812_STRIPS_NUM, // The number of LEDs in the strip, + .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip + .led_model = LED_MODEL_WS2812, // LED strip model + .flags.invert_out = false, // whether to invert the output signal + }; + + // LED strip backend configuration: RMT + led_strip_rmt_config_t rmt_config = { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + .rmt_channel = 0, +#else + .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption + .resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency + .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3 +#endif + }; + + led_indicator_strips_config_t strips_config = { + .led_strip_cfg = strip_config, + .led_strip_driver = LED_STRIP_RMT, + .led_strip_rmt_cfg = rmt_config, + }; + + const led_indicator_config_t config = { + .mode = LED_STRIPS_MODE, + .led_indicator_strips_config = &strips_config, + .blink_lists = led_mode, + .blink_list_num = BLINK_MAX, + }; + + led_handle = led_indicator_create(&config); + assert(led_handle != NULL); + +#if CONFIG_EXAMPLE_ENABLE_CONSOLE_CONTROL + cmd_led_indicator_t cmd_led_indicator = { + .cmd_cb = led_cmd_cb, + .mode_count = BLINK_MAX, + }; + + ESP_ERROR_CHECK(cmd_led_indicator_init(&cmd_led_indicator)); +#else + while (1) { + for (int i = 0; i < BLINK_MAX; i++) { + led_indicator_start(led_handle, i); + ESP_LOGI(TAG, "start blink: %d", i); + vTaskDelay(4000 / portTICK_PERIOD_MS); + led_indicator_stop(led_handle, i); + ESP_LOGI(TAG, "stop blink: %d", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +#endif +}