feat: Adiciona suporte para controle de LED RGB e animações de estado
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRC_DIRS "."
|
SRC_DIRS "."
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES nvs_flash esp_driver_gpio esp_driver_uart ieee802154
|
PRIV_REQUIRES nvs_flash esp_driver_gpio esp_driver_uart ieee802154 heap esp_driver_rmt
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "ha/esp_zigbee_ha_standard.h"
|
#include "ha/esp_zigbee_ha_standard.h"
|
||||||
#include "zcl_utility.h"
|
#include "zcl_utility.h"
|
||||||
#include "esp_zb_switch.h"
|
#include "esp_zb_switch.h"
|
||||||
|
#include "led_indicator.h"
|
||||||
|
|
||||||
typedef struct light_bulb_device_params_s {
|
typedef struct light_bulb_device_params_s {
|
||||||
esp_zb_ieee_addr_t ieee_addr;
|
esp_zb_ieee_addr_t ieee_addr;
|
||||||
@@ -58,6 +59,9 @@ static void zb_buttons_handler(switch_func_pair_t *button_func_pair)
|
|||||||
|
|
||||||
static esp_err_t deferred_driver_init(void)
|
static esp_err_t deferred_driver_init(void)
|
||||||
{
|
{
|
||||||
|
/* Inicializa o LED RGB */
|
||||||
|
led_indicator_init(GPIO_LED_RGB);
|
||||||
|
|
||||||
/* Inicializa o relay */
|
/* Inicializa o relay */
|
||||||
relay_driver_init();
|
relay_driver_init();
|
||||||
|
|
||||||
@@ -161,9 +165,11 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
|
|||||||
if (esp_zb_bdb_is_factory_new()) {
|
if (esp_zb_bdb_is_factory_new()) {
|
||||||
ESP_LOGI(TAG, "Start network steering (joining network)");
|
ESP_LOGI(TAG, "Start network steering (joining network)");
|
||||||
ESP_LOGI(TAG, "Scanning for available Zigbee networks on all channels...");
|
ESP_LOGI(TAG, "Scanning for available Zigbee networks on all channels...");
|
||||||
|
led_indicator_set_state(LED_PAIRING); /* LED azul piscando */
|
||||||
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
|
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "Device rebooted, rejoining network");
|
ESP_LOGI(TAG, "Device rebooted, rejoining network");
|
||||||
|
led_indicator_set_state(LED_PAIRING); /* LED azul piscando */
|
||||||
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
|
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -193,6 +199,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
|
|||||||
ESP_LOGI(TAG, " IEEE Address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
ESP_LOGI(TAG, " IEEE Address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
|
ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
|
||||||
ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);
|
ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);
|
||||||
|
led_indicator_set_state(LED_CONNECTED); /* LED verde fixo */
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "Network steering failed (status: %s)", esp_err_to_name(err_status));
|
ESP_LOGW(TAG, "Network steering failed (status: %s)", esp_err_to_name(err_status));
|
||||||
ESP_LOGI(TAG, "No networks found or unable to join. Retrying in 5 seconds...");
|
ESP_LOGI(TAG, "No networks found or unable to join. Retrying in 5 seconds...");
|
||||||
@@ -200,6 +207,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
|
|||||||
ESP_LOGI(TAG, " 1. Powered on and working");
|
ESP_LOGI(TAG, " 1. Powered on and working");
|
||||||
ESP_LOGI(TAG, " 2. In 'permit join' mode (network open)");
|
ESP_LOGI(TAG, " 2. In 'permit join' mode (network open)");
|
||||||
ESP_LOGI(TAG, " 3. Within range (< 10 meters recommended)");
|
ESP_LOGI(TAG, " 3. Within range (< 10 meters recommended)");
|
||||||
|
led_indicator_set_state(LED_DISCONNECTED); /* LED vermelho piscando */
|
||||||
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 5000);
|
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 5000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -266,7 +274,7 @@ static void esp_zb_task(void *pvParameters)
|
|||||||
|
|
||||||
esp_zb_core_action_handler_register(zb_action_handler);
|
esp_zb_core_action_handler_register(zb_action_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Setting channel mask: 0x%08lx (channel 20)", (unsigned long)ESP_ZB_PRIMARY_CHANNEL_MASK);
|
ESP_LOGI(TAG, "Setting channel mask: 0x%08lx (all channels)", (unsigned long)ESP_ZB_PRIMARY_CHANNEL_MASK);
|
||||||
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
|
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
|
||||||
ESP_ERROR_CHECK(esp_zb_start(false));
|
ESP_ERROR_CHECK(esp_zb_start(false));
|
||||||
esp_zb_stack_main_loop();
|
esp_zb_stack_main_loop();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#define MAX_CHILDREN 10 /* the max amount of connected devices */
|
#define MAX_CHILDREN 10 /* the max amount of connected devices */
|
||||||
#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */
|
#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */
|
||||||
#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */
|
#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */
|
||||||
#define ESP_ZB_PRIMARY_CHANNEL_MASK (1l << 20) /* Zigbee primary channel mask - Channel 20 for ZHA */
|
#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use all channels */
|
||||||
|
|
||||||
/* Basic manufacturer information */
|
/* Basic manufacturer information */
|
||||||
#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */
|
#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
#include "led_indicator.h"
|
||||||
|
#include "led_strip_encoder.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/rmt_tx.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static const char *TAG = "LED_INDICATOR";
|
||||||
|
|
||||||
|
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) // 10MHz resolution
|
||||||
|
|
||||||
|
static rmt_channel_handle_t led_channel = NULL;
|
||||||
|
static rmt_encoder_handle_t led_encoder = NULL;
|
||||||
|
static TaskHandle_t led_task_handle = NULL;
|
||||||
|
static led_state_t current_led_state = LED_OFF;
|
||||||
|
static gpio_num_t led_gpio = GPIO_NUM_NC;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t green;
|
||||||
|
uint8_t red;
|
||||||
|
uint8_t blue;
|
||||||
|
} grb_t;
|
||||||
|
|
||||||
|
static void led_write(grb_t color) {
|
||||||
|
uint8_t led_data[3];
|
||||||
|
led_data[0] = color.green;
|
||||||
|
led_data[1] = color.red;
|
||||||
|
led_data[2] = color.blue;
|
||||||
|
|
||||||
|
rmt_transmit_config_t tx_config = {
|
||||||
|
.loop_count = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_enable(led_channel));
|
||||||
|
ESP_ERROR_CHECK(rmt_transmit(led_channel, led_encoder, led_data, sizeof(led_data), &tx_config));
|
||||||
|
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_channel, portMAX_DELAY));
|
||||||
|
ESP_ERROR_CHECK(rmt_disable(led_channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void led_indicator_task(void *arg) {
|
||||||
|
grb_t color;
|
||||||
|
uint32_t tick = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
switch (current_led_state) {
|
||||||
|
case LED_OFF:
|
||||||
|
color = (grb_t){0, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_PAIRING:
|
||||||
|
// Azul piscando
|
||||||
|
color = (tick % 2 == 0) ? (grb_t){0, 0, 50} : (grb_t){0, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
tick++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_CONNECTED:
|
||||||
|
// Verde fixo
|
||||||
|
color = (grb_t){30, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_DISCONNECTED:
|
||||||
|
// Vermelho piscando
|
||||||
|
color = (tick % 2 == 0) ? (grb_t){0, 50, 0} : (grb_t){0, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(300));
|
||||||
|
tick++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_RELAY_ON:
|
||||||
|
// Verde brilhante
|
||||||
|
color = (grb_t){60, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_RELAY_OFF:
|
||||||
|
// Verde escuro
|
||||||
|
color = (grb_t){10, 0, 0};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_FACTORY_RESET:
|
||||||
|
// Arco-íris rotativo
|
||||||
|
{
|
||||||
|
float hue = (tick % 360) * 3.14159f / 180.0f;
|
||||||
|
color = (grb_t){
|
||||||
|
(uint8_t)(30 * (1 + sinf(hue))),
|
||||||
|
(uint8_t)(30 * (1 + sinf(hue + 2.0943f))),
|
||||||
|
(uint8_t)(30 * (1 + sinf(hue + 4.1888f)))
|
||||||
|
};
|
||||||
|
led_write(color);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(20));
|
||||||
|
tick++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t led_indicator_init(gpio_num_t gpio_num) {
|
||||||
|
esp_err_t ret;
|
||||||
|
led_gpio = gpio_num;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Inicializando LED RGB no GPIO %d", gpio_num);
|
||||||
|
|
||||||
|
// Configurar canal RMT TX
|
||||||
|
rmt_tx_channel_config_t tx_chan_config = {
|
||||||
|
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||||
|
.gpio_num = gpio_num,
|
||||||
|
.mem_block_symbols = 64,
|
||||||
|
.resolution_hz = LED_STRIP_RMT_RES_HZ,
|
||||||
|
.trans_queue_depth = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = rmt_new_tx_channel(&tx_chan_config, &led_channel);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Falha ao criar canal RMT TX: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Criar encoder customizado para LED strip
|
||||||
|
led_strip_encoder_config_t encoder_config = {
|
||||||
|
.resolution = LED_STRIP_RMT_RES_HZ,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = rmt_new_led_strip_encoder(&encoder_config, &led_encoder);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Falha ao criar encoder LED: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Criar task para controlar LED
|
||||||
|
xTaskCreate(led_indicator_task, "led_indicator", 2048, NULL, 5, &led_task_handle);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "LED RGB inicializado com sucesso");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_indicator_set_state(led_state_t state) {
|
||||||
|
current_led_state = state;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef LED_INDICATOR_H
|
||||||
|
#define LED_INDICATOR_H
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LED_OFF,
|
||||||
|
LED_PAIRING,
|
||||||
|
LED_CONNECTED,
|
||||||
|
LED_DISCONNECTED,
|
||||||
|
LED_RELAY_ON,
|
||||||
|
LED_RELAY_OFF,
|
||||||
|
LED_FACTORY_RESET
|
||||||
|
} led_state_t;
|
||||||
|
|
||||||
|
esp_err_t led_indicator_init(gpio_num_t gpio_num);
|
||||||
|
void led_indicator_set_state(led_state_t state);
|
||||||
|
|
||||||
|
#endif // LED_INDICATOR_H
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "led_strip_encoder.h"
|
||||||
|
|
||||||
|
static const char *TAG = "led_encoder";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rmt_encoder_t base;
|
||||||
|
rmt_encoder_t *bytes_encoder;
|
||||||
|
rmt_encoder_t *copy_encoder;
|
||||||
|
int state;
|
||||||
|
rmt_symbol_word_t reset_code;
|
||||||
|
} rmt_led_strip_encoder_t;
|
||||||
|
|
||||||
|
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
||||||
|
{
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||||
|
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||||
|
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||||
|
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||||
|
size_t encoded_symbols = 0;
|
||||||
|
|
||||||
|
switch (led_encoder->state) {
|
||||||
|
case 0: // send RGB data
|
||||||
|
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state |= RMT_ENCODING_MEM_FULL;
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
case 1: // send reset code
|
||||||
|
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||||
|
sizeof(led_encoder->reset_code), &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||||
|
state |= RMT_ENCODING_COMPLETE;
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state |= RMT_ENCODING_MEM_FULL;
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
*ret_state = state;
|
||||||
|
return encoded_symbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
|
||||||
|
{
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
free(led_encoder);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
|
||||||
|
{
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||||
|
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||||
|
led_encoder->state = RMT_ENCODING_RESET;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||||
|
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
|
led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t));
|
||||||
|
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||||
|
led_encoder->base.encode = rmt_encode_led_strip;
|
||||||
|
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||||
|
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||||
|
|
||||||
|
// WS2812 timing: 0: 0.4us/0.85us, 1: 0.8us/0.45us
|
||||||
|
rmt_bytes_encoder_config_t bytes_encoder_config = {
|
||||||
|
.bit0 = {
|
||||||
|
.level0 = 1,
|
||||||
|
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
|
||||||
|
},
|
||||||
|
.bit1 = {
|
||||||
|
.level0 = 1,
|
||||||
|
.duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
|
||||||
|
},
|
||||||
|
.flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
|
||||||
|
};
|
||||||
|
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
|
||||||
|
|
||||||
|
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||||
|
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
|
||||||
|
|
||||||
|
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
|
||||||
|
led_encoder->reset_code = (rmt_symbol_word_t) {
|
||||||
|
.level0 = 0,
|
||||||
|
.duration0 = reset_ticks,
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = reset_ticks,
|
||||||
|
};
|
||||||
|
*ret_encoder = &led_encoder->base;
|
||||||
|
return ESP_OK;
|
||||||
|
err:
|
||||||
|
if (led_encoder) {
|
||||||
|
if (led_encoder->bytes_encoder) {
|
||||||
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
|
}
|
||||||
|
if (led_encoder->copy_encoder) {
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
}
|
||||||
|
free(led_encoder);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "driver/rmt_encoder.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of led strip encoder configuration
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t resolution; /*!< Encoder resolution, in Hz */
|
||||||
|
} led_strip_encoder_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create RMT encoder for encoding LED strip pixels into RMT symbols
|
||||||
|
*
|
||||||
|
* @param[in] config Encoder configuration
|
||||||
|
* @param[out] ret_encoder Returned encoder handle
|
||||||
|
* @return
|
||||||
|
* - ESP_ERR_INVALID_ARG for any invalid arguments
|
||||||
|
* - ESP_ERR_NO_MEM out of memory when creating led strip encoder
|
||||||
|
* - ESP_OK if creating encoder successfully
|
||||||
|
*/
|
||||||
|
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "esp_zigbee_core.h"
|
#include "esp_zigbee_core.h"
|
||||||
#include "switch_driver.h"
|
#include "switch_driver.h"
|
||||||
|
#include "led_indicator.h"
|
||||||
|
|
||||||
/* Estado atual do relay */
|
/* Estado atual do relay */
|
||||||
static bool relay_state = false;
|
static bool relay_state = false;
|
||||||
@@ -123,13 +124,9 @@ static void switch_driver_button_detected(void *arg)
|
|||||||
if ((current_time - press_start_time) >= LONG_PRESS_DURATION_MS) {
|
if ((current_time - press_start_time) >= LONG_PRESS_DURATION_MS) {
|
||||||
ESP_LOGI(TAG, "Botão pressionado por 5 segundos - Iniciando factory reset...");
|
ESP_LOGI(TAG, "Botão pressionado por 5 segundos - Iniciando factory reset...");
|
||||||
ESP_LOGI(TAG, "Dispositivo entrará em modo de pareamento após reiniciar");
|
ESP_LOGI(TAG, "Dispositivo entrará em modo de pareamento após reiniciar");
|
||||||
/* Piscar relay para feedback visual */
|
/* Animação arco-íris no LED para feedback visual */
|
||||||
for (int i = 0; i < 5; i++) {
|
led_indicator_set_state(LED_FACTORY_RESET);
|
||||||
relay_set_state(true);
|
vTaskDelay(pdMS_TO_TICKS(2000)); /* 2 segundos de animação */
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
relay_set_state(false);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
/* Factory reset - limpa NVS e reinicia */
|
/* Factory reset - limpa NVS e reinicia */
|
||||||
esp_zb_factory_reset();
|
esp_zb_factory_reset();
|
||||||
switch_state = SWITCH_IDLE;
|
switch_state = SWITCH_IDLE;
|
||||||
@@ -229,6 +226,10 @@ void relay_set_state(bool state)
|
|||||||
{
|
{
|
||||||
relay_state = state;
|
relay_state = state;
|
||||||
gpio_set_level(GPIO_OUTPUT_RELAY, state ? 1 : 0);
|
gpio_set_level(GPIO_OUTPUT_RELAY, state ? 1 : 0);
|
||||||
|
|
||||||
|
/* Atualiza LED para refletir estado do relay */
|
||||||
|
led_indicator_set_state(state ? LED_RELAY_ON : LED_RELAY_OFF);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Relay %s", state ? "LIGADO" : "DESLIGADO");
|
ESP_LOGI(TAG, "Relay %s", state ? "LIGADO" : "DESLIGADO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ extern "C" {
|
|||||||
#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9
|
#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9
|
||||||
|
|
||||||
/* GPIO para controlar o relay */
|
/* GPIO para controlar o relay */
|
||||||
#define GPIO_OUTPUT_RELAY GPIO_NUM_8
|
#define GPIO_OUTPUT_RELAY GPIO_NUM_4
|
||||||
|
|
||||||
|
/* GPIO para o LED RGB (WS2812) */
|
||||||
|
#define GPIO_LED_RGB GPIO_NUM_8
|
||||||
|
|
||||||
/* config button level depends on the pull up/down setting
|
/* config button level depends on the pull up/down setting
|
||||||
push button level is on level = 1 when pull-down enable
|
push button level is on level = 1 when pull-down enable
|
||||||
|
|||||||
Reference in New Issue
Block a user