From 81b589df21589b6db7c7731e82390bb9cb7cc563 Mon Sep 17 00:00:00 2001 From: Drath Date: Thu, 19 Mar 2026 19:52:13 +0100 Subject: [PATCH] light driver thread implemented --- .idea/.name | 1 - README.md | 1 - dependencies.lock | 6 ++-- include/light_driver.h | 6 ++-- main/light_driver.c | 72 +++++++++++++++++++++++++++--------------- main/zigbee.c | 15 ++++----- 6 files changed, 60 insertions(+), 41 deletions(-) delete mode 100644 .idea/.name diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index d0cea86..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -st7290 \ No newline at end of file diff --git a/README.md b/README.md index 9a9a84a..77baa7d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ Generalnie co ma dzialac to juz dziala, thank fuck. Ja pierdole ale api do zigbe ### TODO - hardware - weird start up behavior - - wylaczanie lamp nie dziala po gammie - identyfikacja, niby opcjonalna ale fajny bajer - factory reset zigbee zeby bylo legitnie, dzwonisz po `esp_zb_factory_reset();` - status LED zeby bylo legitnie (pokazuje factory reset i OTA kiedys) diff --git a/dependencies.lock b/dependencies.lock index bb850b1..5d9e8ad 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -6,7 +6,8 @@ dependencies: type: local version: 1.6.8 espressif/cmake_utilities: - component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f + component_hash: + 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f dependencies: - name: idf require: private @@ -16,7 +17,8 @@ dependencies: type: service version: 0.5.3 espressif/esp-zboss-lib: - component_hash: 321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a + component_hash: + 321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a dependencies: - name: idf require: private diff --git a/include/light_driver.h b/include/light_driver.h index 3328726..770db95 100644 --- a/include/light_driver.h +++ b/include/light_driver.h @@ -8,8 +8,8 @@ #include "esp_err.h" #include "stdbool.h" -esp_err_t light_driver_init(bool default_state); -esp_err_t light_driver_set_level(uint8_t level, uint16_t transition_ms); -esp_err_t light_driver_set_power(bool power, uint16_t transition_ms); +void light_driver_task(void *pvParameter); +void light_driver_set_level(uint8_t level); +void light_driver_set_power(bool power); #endif //LIGHT_DRIVER_H \ No newline at end of file diff --git a/main/light_driver.c b/main/light_driver.c index b8840fa..264ab77 100644 --- a/main/light_driver.c +++ b/main/light_driver.c @@ -7,11 +7,12 @@ #include "esp_err.h" #include #include +#include static const char* TAG = "light_driver"; /* tweakable stuff */ -static const uint8_t light_gpio = 2; +static const uint8_t light_gpio = 15; static const uint16_t light_pwm_freq = 65000; static const ledc_timer_bit_t light_pwm_resolution = LEDC_TIMER_10_BIT; static const double light_lowest_duty_pct = 0.05; // lowest duty percentage where the LEDs still light up nice @@ -20,32 +21,27 @@ static const double light_lowest_duty_pct = 0.05; // lowest duty percentage wher static const ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0; static const ledc_mode_t light_ledc_speed_mode = LEDC_LOW_SPEED_MODE; static const uint32_t light_brightness_steps = (1 << light_pwm_resolution) - 1; +SemaphoreHandle_t light_sem = NULL; /* global vars */ -static bool light_init_done = false; -static uint8_t light_current_level = 0; +static uint8_t light_target_level = 0; static uint16_t gamma_lut[ZIGBEE_LIGHT_LEVELS + 1]; -esp_err_t light_driver_set_level(const uint8_t level, const uint16_t transition_ms) { - if (!light_init_done) { - ESP_LOGW(TAG, "light driver not ready!"); - return ESP_FAIL; - } - light_current_level = level; - const uint16_t duty = gamma_lut[light_current_level]; - ESP_ERROR_CHECK(ledc_fade_stop(light_ledc_speed_mode, light_ledc_channel)); - ESP_ERROR_CHECK(ledc_set_fade_with_time(light_ledc_speed_mode, light_ledc_channel, duty, transition_ms)); - ESP_ERROR_CHECK(ledc_fade_start(light_ledc_speed_mode, light_ledc_channel, LEDC_FADE_NO_WAIT)); - // ESP_LOGI(TAG, "led set to %d, max is %d", duty, light_brightness_steps); - return ESP_OK; +void light_driver_set_level(const uint8_t level) { + xSemaphoreTake(light_sem, portMAX_DELAY); + light_target_level = level; + xSemaphoreGive(light_sem); } -esp_err_t light_driver_set_power(const bool power, const uint16_t transition_ms) { - return light_driver_set_level(power ? light_current_level : 0, transition_ms); +uint16_t get_level(void) { + xSemaphoreTake(light_sem, portMAX_DELAY); + const uint16_t lvl = light_target_level; + xSemaphoreGive(light_sem); + return MIN(254, lvl); } -esp_err_t light_driver_init(const bool default_state) { +void light_driver_task(void *pvParameter) { const ledc_timer_config_t ledc_timer = { .speed_mode = light_ledc_speed_mode, .duty_resolution = light_pwm_resolution, @@ -60,9 +56,14 @@ esp_err_t light_driver_init(const bool default_state) { .intr_type = LEDC_INTR_DISABLE, .gpio_num = light_gpio, .duty = 0, // Set duty to 0% - .hpoint = 0 + .hpoint = (int)light_brightness_steps }; + ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); + ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); + static uint8_t prev_level = 0; + + // pre-compute gamma table for (uint8_t i = 0; i <= ZIGBEE_LIGHT_LEVELS; i++) { const double brightness_pct = (double)i / (double)ZIGBEE_LIGHT_LEVELS; const double gamma_corrected = pow(brightness_pct, 2.2); @@ -73,11 +74,32 @@ esp_err_t light_driver_init(const bool default_state) { if (gamma_lut[ZIGBEE_LIGHT_LEVELS] > light_brightness_steps) gamma_lut[ZIGBEE_LIGHT_LEVELS] = light_brightness_steps; ESP_LOGI(TAG, "pre-computed brightness lookup table"); - ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); - ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); - ESP_ERROR_CHECK(ledc_fade_func_install(0)); + // semaphore init + light_sem = xSemaphoreCreateMutex(); + xSemaphoreGive(light_sem); + ESP_LOGI(TAG, "ledc driver initialized, f=%d Hz, %d step resolution", light_pwm_freq, light_brightness_steps); - light_init_done = true; - light_driver_set_power(default_state, 100); - return ESP_OK; + light_driver_set_level(0); + + while (true) { + const uint16_t tgt = get_level(); + if (tgt != prev_level) { + const int diff = tgt - prev_level; + const int abs_diff = abs(diff); + const int step = MIN(abs_diff / 8 + 1, 20); + + if (diff > 0) + prev_level += step; + else + prev_level -= step; + + ESP_LOGI(TAG, "setting light level to %d, tgt is %d, step of %d", prev_level, tgt, step); + ledc_set_duty_and_update(light_ledc_speed_mode, light_ledc_channel, gamma_lut[prev_level], light_brightness_steps); + } + vTaskDelay(pdMS_TO_TICKS(20)); + } +} + +void light_driver_set_power(const bool power) { + light_driver_set_level(power ? get_level() : 0); } \ No newline at end of file diff --git a/main/zigbee.c b/main/zigbee.c index af5fc76..04e521d 100644 --- a/main/zigbee.c +++ b/main/zigbee.c @@ -12,13 +12,10 @@ static char manufacturer[] = "\x05""Drath"; static char model[] = "\x15""Dimmable Zigbee Light"; static const uint8_t endpoint_no = 1; -static const uint16_t transition_on_off_ms = 500; -static const uint16_t transition_level_ms = 100; // looks like it gets lvl updates from HA every 100ms - static esp_err_t deferred_driver_init(void) { static bool is_inited = false; if (!is_inited) { - light_driver_init(LIGHT_DEFAULT_OFF); + xTaskCreate(light_driver_task, "light task", 4096, NULL, 6, NULL); is_inited = true; } return is_inited ? ESP_OK : ESP_FAIL; @@ -60,7 +57,7 @@ static esp_err_t zigbee_attribute_handler(const esp_zb_zcl_set_attr_value_messag bool light_state = false; light_state = message->attribute.data.value ? *(bool*)message->attribute.data.value : light_state; ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off"); - light_driver_set_power(light_state, transition_on_off_ms); + light_driver_set_power(light_state); } break; @@ -68,7 +65,7 @@ static esp_err_t zigbee_attribute_handler(const esp_zb_zcl_set_attr_value_messag if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { uint8_t light_level = 0; light_level = message->attribute.data.value ? *(uint8_t*)message->attribute.data.value : light_level; - light_driver_set_level(light_level, transition_level_ms); + light_driver_set_level(light_level); ESP_LOGI(TAG, "Light level changes to %d", light_level); } break; @@ -166,9 +163,9 @@ void zigbee_endpoint_init(esp_zb_ep_list_t *ep_list, esp_zb_cluster_list_t *clus } /* appearently you cant rename this? */ -void esp_zb_app_signal_handler(esp_zb_app_signal_t* signal_struct) { - uint32_t* p_sg_p = signal_struct->p_app_signal; - const esp_err_t err_status = signal_struct->esp_err_status; +void esp_zb_app_signal_handler(const esp_zb_app_signal_t* signal_s) { + uint32_t* p_sg_p = signal_s->p_app_signal; + const esp_err_t err_status = signal_s->esp_err_status; const esp_zb_app_signal_type_t sig_type = *p_sg_p; switch (sig_type) {