From 9c7156edbd08ab921841df80fa33c8bf77db84f6 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 25 Jun 2021 17:34:56 +0800 Subject: [PATCH] ESP32C3 Support: use onboard RGB-LED(WS2812) for status-LED in all-clusters-app add colorcontrol cluster for ESP32C3_DevkitM --- .../all-clusters-app/esp32/CMakeLists.txt | 11 +- examples/all-clusters-app/esp32/README.md | 5 +- .../esp32/main/CMakeLists.txt | 8 +- .../esp32/main/DeviceCallbacks.cpp | 36 +++++- .../esp32/main/Kconfig.projbuild | 3 +- .../all-clusters-app/esp32/main/LEDWidget.cpp | 104 +++++++++++++++++- .../esp32/main/include/DeviceCallbacks.h | 3 + .../esp32/main/include/LEDWidget.h | 8 ++ examples/all-clusters-app/esp32/main/main.cpp | 2 +- 9 files changed, 164 insertions(+), 16 deletions(-) diff --git a/examples/all-clusters-app/esp32/CMakeLists.txt b/examples/all-clusters-app/esp32/CMakeLists.txt index 930da3d1be2d3e..9d98e41df4be5c 100644 --- a/examples/all-clusters-app/esp32/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/CMakeLists.txt @@ -24,12 +24,11 @@ set(EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../common/QRCode" ) if(${IDF_TARGET} STREQUAL "esp32") -set(EXTRA_COMPONENT_DIRS - ${EXTRA_COMPONENT_DIRS} - "${CMAKE_CURRENT_LIST_DIR}/../../common/m5stack-tft/repo/components/tft" - "${CMAKE_CURRENT_LIST_DIR}/../../common/m5stack-tft/repo/components/spidriver" - "${CMAKE_CURRENT_LIST_DIR}/../../common/screen-framework" -) + list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../common/m5stack-tft/repo/components/tft" + "${CMAKE_CURRENT_LIST_DIR}/../../common/m5stack-tft/repo/components/spidriver" + "${CMAKE_CURRENT_LIST_DIR}/../../common/screen-framework") +elseif(${IDF_TARGET} STREQUAL "esp32c3") + list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/peripherals/rmt/led_strip/components") endif() project(chip-all-clusters-app) diff --git a/examples/all-clusters-app/esp32/README.md b/examples/all-clusters-app/esp32/README.md index a9cab13a1b2476..75810cdbf98caa 100644 --- a/examples/all-clusters-app/esp32/README.md +++ b/examples/all-clusters-app/esp32/README.md @@ -243,5 +243,6 @@ through the on/off/toggle commands from the `python-controller`. For `M5Stack`, a virtual Green LED on the display is used for the same. If you wish to see the actual effect of the commands on `ESP32-DevKitC`, -`ESP32-WROVER-KIT_V4.1` and `ESP32C3-DevKitM`, you will have to connect an -external LED to GPIO `STATUS_LED_GPIO_NUM`. +`ESP32-WROVER-KIT_V4.1`, you will have to connect an external LED to GPIO +`STATUS_LED_GPIO_NUM`. For `ESP32C3-DevKitM`, the on-board LED will show the +actual effect of the commands. diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 1124c7077833e1..06eb182bcf810d 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -69,13 +69,17 @@ set(SRC_DIRS_LIST ) if(("${CONFIG_DEVICE_TYPE_ESP32_DEVKITC}" STREQUAL "y") OR ("${CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM}" STREQUAL "y")) - set(PRIV_INCLUDE_DIRS_LIST ${PRIV_INCLUDE_DIRS_LIST} - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/screen-framework/include") + list(APPEND PRIV_INCLUDE_DIRS_LIST + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/screen-framework/include") set(PRIV_REQUIRES_LIST chip QRCode bt) elseif(("${CONFIG_DEVICE_TYPE_M5STACK}" STREQUAL "y") OR ("${CONFIG_DEVICE_TYPE_ESP32_WROVER_KIT}" STREQUAL "y")) set(PRIV_REQUIRES_LIST chip QRCode bt tft spidrier screen-framework) endif() +if("${CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM}" STREQUAL "y") + list(APPEND PRIV_REQUIRES_LIST led_strip) +endif() + idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST} PRIV_REQUIRES ${PRIV_REQUIRES_LIST}) diff --git a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp index 21be643045fb58..6dd69bd01c94df 100644 --- a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp @@ -95,7 +95,11 @@ void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, Cluster case ZCL_LEVEL_CONTROL_CLUSTER_ID: OnLevelControlAttributeChangeCallback(endpointId, attributeId, value); break; - +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + case ZCL_COLOR_CONTROL_CLUSTER_ID: + OnColorControlAttributeChangeCallback(endpointId, attributeId, value); + break; +#endif default: ESP_LOGI(TAG, "Unhandled cluster ID: %d", clusterId); break; @@ -164,6 +168,36 @@ void DeviceCallbacks::OnLevelControlAttributeChangeCallback(EndpointId endpointI return; } +// Current we only support ColorControl cluster for ESP32C3_DEVKITM which has an on-board RGB-LED +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM +void DeviceCallbacks::OnColorControlAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID || + attributeId == ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID, + ESP_LOGI(TAG, "Unhandled AttributeId ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, ESP_LOGE(TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + if(endpointId == 1) + { + uint8_t hue, saturation; + if(attributeId == ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID) + { + hue = *value; + emberAfReadServerAttribute(endpointId, ZCL_COLOR_CONTROL_CLUSTER_ID, ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID, + reinterpret_cast(&saturation), sizeof(uint8_t)); + } + else + { + saturation = *value; + emberAfReadServerAttribute(endpointId, ZCL_COLOR_CONTROL_CLUSTER_ID, ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID, + reinterpret_cast(&hue), sizeof(uint8_t)); + } + statusLED1.SetColor(hue,saturation); + } +exit: + return; +} +#endif + void IdentifyTimerHandler(Layer * systemLayer, void * appState, CHIP_ERROR error) { statusLED1.Animate(); diff --git a/examples/all-clusters-app/esp32/main/Kconfig.projbuild b/examples/all-clusters-app/esp32/main/Kconfig.projbuild index 487528fce73940..89911735fbf307 100644 --- a/examples/all-clusters-app/esp32/main/Kconfig.projbuild +++ b/examples/all-clusters-app/esp32/main/Kconfig.projbuild @@ -22,7 +22,8 @@ menu "Demo" choice prompt "Device Type" - default DEVICE_TYPE_ESP32_DEVKITC + default DEVICE_TYPE_ESP32_DEVKITC if IDF_TARGET_ESP32 + default DEVICE_TYPE_ESP32_C3_DEVKITM if IDF_TARGET_ESP32C3 help Specifies the type of ESP32 device. diff --git a/examples/all-clusters-app/esp32/main/LEDWidget.cpp b/examples/all-clusters-app/esp32/main/LEDWidget.cpp index c6a5a8c5986510..af4aef6f64af78 100644 --- a/examples/all-clusters-app/esp32/main/LEDWidget.cpp +++ b/examples/all-clusters-app/esp32/main/LEDWidget.cpp @@ -27,12 +27,19 @@ #include "ScreenManager.h" -#include "driver/ledc.h" #include "esp_log.h" #include "esp_system.h" #include "esp_timer.h" +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM +#include "driver/rmt.h" +#include "led_strip.h" +#define RMT_TX_DEFAULT_GPIO GPIO_NUM_8 +#define RMT_TX_DEFAULT_CHANNEL RMT_CHANNEL_0 +static led_strip_t *strip = NULL; +#else +#include "driver/ledc.h" #include "hal/ledc_types.h" - +#endif void LEDWidget::Init(gpio_num_t gpioNum) { mLastChangeTimeUS = 0; @@ -44,7 +51,20 @@ void LEDWidget::Init(gpio_num_t gpioNum) mState = false; mError = false; errorTimer = NULL; - +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + if (gpioNum == RMT_TX_DEFAULT_GPIO) + { + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(RMT_TX_DEFAULT_GPIO, RMT_TX_DEFAULT_CHANNEL); + config.clk_div = 2; + rmt_config(&config); + rmt_driver_install(config.channel, 0, 0); + led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1,(led_strip_dev_t)config.channel); + strip = led_strip_new_rmt_ws2812(&strip_config); + mDefaultOnBrightness = UINT8_MAX; + mHue = 0; + mSaturation = 0; + } +#else if (gpioNum < GPIO_NUM_MAX) { ledc_timer_config_t ledc_timer = { @@ -67,6 +87,7 @@ void LEDWidget::Init(gpio_num_t gpioNum) ledc_channel_config(&ledc_channel); mDefaultOnBrightness = UINT8_MAX; } +#endif } void LEDWidget::Set(bool state) @@ -77,11 +98,20 @@ void LEDWidget::Set(bool state) void LEDWidget::SetBrightness(uint8_t brightness) { +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + if(strip){ + uint8_t red, green, blue; + HSB2rgb(mHue, mSaturation, brightness, red, green, blue); + strip->set_pixel(strip, 0, red, green, blue); + strip->refresh(strip, 100); + } +#else if (mGPIONum < GPIO_NUM_MAX) { ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, brightness); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } +#endif if (brightness > 0) { mDefaultOnBrightness = brightness; @@ -155,11 +185,22 @@ void LEDWidget::DoSet(bool state) { bool stateChange = (mState != state); mState = state; +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + if(strip) + { + uint8_t red, green, blue; + uint8_t brightness = state ? mDefaultOnBrightness : 0; + HSB2rgb(mHue, mSaturation, brightness, red, green, blue); + strip->set_pixel(strip, 0, red, green, blue); + strip->refresh(strip, 100); + } +#else if (mGPIONum < GPIO_NUM_MAX) { ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, state ? mDefaultOnBrightness : 0); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } +#endif if (stateChange) { #if CONFIG_HAVE_DISPLAY @@ -186,3 +227,60 @@ void LEDWidget::SetVLED(int id1, int id2) } } #endif + + +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM +void LEDWidget::SetColor(uint8_t Hue, uint8_t Saturation) +{ + uint8_t red, green, blue; + uint8_t brightness = mState ? mDefaultOnBrightness : 0; + mHue = static_cast(Hue) * 360 / 254; //mHue [0, 360] + mSaturation = static_cast(Saturation) * 100 / 254; // mSaturation [0 , 100] + + HSB2rgb(mHue, mSaturation, brightness, red, green, blue); + strip->set_pixel(strip, 0, red, green, blue); + strip->refresh(strip, 100); +} + +void LEDWidget::HSB2rgb(uint16_t Hue, uint8_t Saturation, uint8_t brightness, uint8_t& red, uint8_t& green, uint8_t& blue) +{ + uint16_t i = Hue / 60; + uint16_t rgb_max = brightness; + uint16_t rgb_min = rgb_max * (100 - Saturation) / 100; + uint16_t diff = Hue % 60; + uint16_t rgb_adj = (rgb_max -rgb_min) * diff / 60; + + switch(i) { + case 0: + red = rgb_max; + green = rgb_min + rgb_adj; + blue = rgb_min; + break; + case 1: + red = rgb_max - rgb_adj; + green = rgb_max; + blue = rgb_min; + break; + case 2: + red = rgb_min; + green = rgb_max; + blue = rgb_min + rgb_adj; + break; + case 3: + red = rgb_min; + green = rgb_max - rgb_adj; + blue = rgb_max; + break; + case 4: + red = rgb_min + rgb_adj; + green = rgb_min; + blue = rgb_max; + break; + default: + red = rgb_max; + green = rgb_min; + blue = rgb_max - rgb_adj; + break; + } +} +#endif diff --git a/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h b/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h index e68b61a018d077..7917c79cc80308 100644 --- a/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h +++ b/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h @@ -42,6 +42,9 @@ class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); void OnLevelControlAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + void OnColorControlAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); +#endif void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); bool mEndpointOnOffState[2]; diff --git a/examples/all-clusters-app/esp32/main/include/LEDWidget.h b/examples/all-clusters-app/esp32/main/include/LEDWidget.h index a3f6f6c9c4ed08..ec4a19b30a696b 100644 --- a/examples/all-clusters-app/esp32/main/include/LEDWidget.h +++ b/examples/all-clusters-app/esp32/main/include/LEDWidget.h @@ -45,7 +45,11 @@ class LEDWidget void BlinkOnError(); void Animate(); +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + void SetColor(uint8_t Hue, uint8_t Saturation); + void HSB2rgb(uint16_t Hue, uint8_t Saturation, uint8_t brightness, uint8_t& red, uint8_t& green, uint8_t& blue); +#endif #if CONFIG_HAVE_DISPLAY void SetVLED(int id1, int id2); #endif @@ -55,6 +59,10 @@ class LEDWidget uint32_t mBlinkOnTimeMS; uint32_t mBlinkOffTimeMS; uint8_t mDefaultOnBrightness; +#if CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM + uint16_t mHue; // mHue [0, 360] + uint8_t mSaturation; // mSaturation [0, 100] +#endif gpio_num_t mGPIONum; int mVLED1; int mVLED2; diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 6de0390eaa204b..dbe0a53e8028b2 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -87,7 +87,7 @@ using namespace ::chip::DeviceLayer; #elif CONFIG_DEVICE_TYPE_ESP32_C3_DEVKITM -#define STATUS_LED_GPIO_NUM GPIO_NUM_2 +#define STATUS_LED_GPIO_NUM GPIO_NUM_8 #else // !CONFIG_DEVICE_TYPE_ESP32_DEVKITC