From 9491deaeba11ae911c858c797a46734c8ec0914a Mon Sep 17 00:00:00 2001 From: Andrey Aleksandrov Date: Fri, 6 Feb 2026 17:35:50 +0200 Subject: [PATCH] Add brightness setting --- CHANGELOG.md | 8 ++- README.md | 71 ++++++++++++++++++++ led_manager.c | 180 +++++++++++++++++++++++++++++++++++++++++++++----- led_manager.h | 18 +++++ 4 files changed, 259 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8625ef8..a9f4f15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v1.0.0] - 2024-12-30 +## [v1.1.0] - 2026-02-06 + +### Added + +- Brightness and HSV settings + +## [v1.0.0] - 2025-12-30 ### Added diff --git a/README.md b/README.md index 272babb..b16de74 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,22 @@ void rgb_demo(void) { } ``` +### HSV + Global Brightness + +```c +#include "led_manager.h" + +void hsv_demo(void) { + led_manager_init(GPIO_NUM_8); + + // Set a teal color using HSV + led_manager_set_hsv(180, 255, 200); + + // Dim the LED globally without changing hue/saturation + led_manager_set_brightness(64); +} +``` + ## 📚 API Reference ### Data Types @@ -354,6 +370,61 @@ led_manager_set_rgb(255, 165, 0); // Orange variant led_manager_set_rgb(75, 0, 130); // Indigo ``` +##### `esp_err_t led_manager_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value)` + +Set LED color using HSV values. + +**Parameters:** + +- `hue`: Hue component (0-360) +- `saturation`: Saturation component (0-255) +- `value`: Value/brightness component (0-255) + +**Returns:** + +- `ESP_OK`: Color set successfully +- `ESP_ERR_INVALID_STATE`: LED manager not initialized +- Hardware error codes on failure + +**Technical Details:** + +- Stores HSV as the current color for blinking +- Global brightness scales the `value` component +- If blinking is active, color updates take effect on the next blink cycle + +**Example:** + +```c +// Teal-ish color +led_manager_set_hsv(180, 255, 200); +``` + +##### `esp_err_t led_manager_set_brightness(uint8_t brightness)` + +Set global brightness without changing the current hue/saturation. + +**Parameters:** + +- `brightness`: Brightness value (0-255) + +**Returns:** + +- `ESP_OK`: Brightness updated successfully +- `ESP_ERR_INVALID_STATE`: LED manager not initialized +- Hardware error codes on failure + +**Technical Details:** + +- Scales the current HSV value when pushing to the LED +- If blinking is active, brightness applies to subsequent blink updates + +**Example:** + +```c +// Dim to 25% +led_manager_set_brightness(64); +``` + #### Control Functions ##### `esp_err_t led_manager_clear(void)` diff --git a/led_manager.c b/led_manager.c index 35aaa5d..a49b84a 100644 --- a/led_manager.c +++ b/led_manager.c @@ -8,14 +8,18 @@ static bool is_initialized = false; // Blinking functionality static TaskHandle_t blink_task_handle = NULL; static bool is_blinking = false; -static uint8_t current_red = 0; -static uint8_t current_green = 0; -static uint8_t current_blue = 0; +static uint16_t current_hue = 0; +static uint8_t current_sat = 0; +static uint8_t current_val = 0; +static bool has_color = false; static uint32_t blink_rate_ms = 500; static bool blink_state = false; +static uint8_t global_brightness = 255; // Forward declaration for blink task static void led_blink_task(void *pvParameter); +static void rgb_to_hsv(uint8_t red, uint8_t green, uint8_t blue, uint16_t *hue, uint8_t *sat, uint8_t *val); +static uint8_t apply_brightness(uint8_t value); // RGB color definitions static const struct @@ -26,11 +30,11 @@ static const struct const char *name; led_color_t enum_val; } rgb_colors[] = { - {200, 0, 0, "Red", LED_COLOR_RED}, - {200, 40, 0, "Orange", LED_COLOR_ORANGE}, - {200, 160, 0, "Yellow", LED_COLOR_YELLOW}, - {0, 180, 0, "Green", LED_COLOR_GREEN}, - {0, 0, 160, "Blue", LED_COLOR_BLUE}, + {255, 0, 0, "Red", LED_COLOR_RED}, + {255, 100, 0, "Orange", LED_COLOR_ORANGE}, + {255, 200, 0, "Yellow", LED_COLOR_YELLOW}, + {0, 255, 0, "Green", LED_COLOR_GREEN}, + {0, 0, 255, "Blue", LED_COLOR_BLUE}, }; // LED blink task @@ -41,13 +45,13 @@ static void led_blink_task(void *pvParameter) if (blink_state) { // Turn on with current color - led_strip_set_pixel(led_strip, 0, current_red, current_green, current_blue); + led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, apply_brightness(current_val)); led_strip_refresh(led_strip); } else { // Turn off - led_strip_set_pixel(led_strip, 0, 0, 0, 0); + led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, 0); led_strip_refresh(led_strip); } @@ -56,7 +60,7 @@ static void led_blink_task(void *pvParameter) } // Clean exit - restore solid color - led_strip_set_pixel(led_strip, 0, current_red, current_green, current_blue); + led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, apply_brightness(current_val)); led_strip_refresh(led_strip); blink_task_handle = NULL; @@ -120,6 +124,11 @@ esp_err_t led_manager_init(int gpio_pin) } is_initialized = true; + global_brightness = 255; + current_hue = 0; + current_sat = 0; + current_val = 0; + has_color = false; ESP_LOGI(TAG, "LED manager initialized successfully"); return ESP_OK; } @@ -242,8 +251,10 @@ esp_err_t led_manager_set_rgb(uint8_t red, uint8_t green, uint8_t blue) ESP_LOGD(TAG, "Setting LED color: R=%d, G=%d, B=%d", red, green, blue); - // Set the LED pixel using RGB color - esp_err_t ret = led_strip_set_pixel(led_strip, 0, red, green, blue); + rgb_to_hsv(red, green, blue, ¤t_hue, ¤t_sat, ¤t_val); + has_color = true; + + esp_err_t ret = led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, apply_brightness(current_val)); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set LED pixel: %s", esp_err_to_name(ret)); @@ -258,10 +269,71 @@ esp_err_t led_manager_set_rgb(uint8_t red, uint8_t green, uint8_t blue) return ret; } - // Store current color for blinking - current_red = red; - current_green = green; - current_blue = blue; + return ESP_OK; +} + +esp_err_t led_manager_set_brightness(uint8_t brightness) +{ + global_brightness = brightness; + + if (!is_initialized || led_strip == NULL || !has_color || is_blinking) + { + return ESP_OK; + } + + esp_err_t ret = led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, apply_brightness(current_val)); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to set LED pixel: %s", esp_err_to_name(ret)); + return ret; + } + + ret = led_strip_refresh(led_strip); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to refresh LED strip: %s", esp_err_to_name(ret)); + return ret; + } + + return ESP_OK; +} + +esp_err_t led_manager_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value) +{ + if (!is_initialized || led_strip == NULL) + { + ESP_LOGE(TAG, "LED manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + if (hue > 360) + { + hue = (uint16_t)(hue % 360); + } + + current_hue = hue; + current_sat = saturation; + current_val = value; + has_color = true; + + if (is_blinking) + { + return ESP_OK; + } + + esp_err_t ret = led_strip_set_pixel_hsv(led_strip, 0, current_hue, current_sat, apply_brightness(current_val)); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to set LED pixel: %s", esp_err_to_name(ret)); + return ret; + } + + ret = led_strip_refresh(led_strip); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to refresh LED strip: %s", esp_err_to_name(ret)); + return ret; + } return ESP_OK; } @@ -306,6 +378,11 @@ esp_err_t led_manager_clear(void) return ret; } + has_color = false; + current_hue = 0; + current_sat = 0; + current_val = 0; + return ESP_OK; } @@ -343,6 +420,75 @@ esp_err_t led_manager_deinit(void) } is_initialized = false; + has_color = false; ESP_LOGI(TAG, "LED manager deinitialized"); return ESP_OK; +} + +static void rgb_to_hsv(uint8_t red, uint8_t green, uint8_t blue, uint16_t *hue, uint8_t *sat, uint8_t *val) +{ + uint8_t max = red; + uint8_t min = red; + + if (green > max) + { + max = green; + } + if (blue > max) + { + max = blue; + } + + if (green < min) + { + min = green; + } + if (blue < min) + { + min = blue; + } + + uint8_t delta = max - min; + + *val = max; + if (max == 0) + { + *sat = 0; + *hue = 0; + return; + } + + *sat = (uint8_t)((uint16_t)delta * 255 / max); + + if (delta == 0) + { + *hue = 0; + return; + } + + float h; + if (max == red) + { + h = 60.0f * ((float)(green - blue) / (float)delta); + } + else if (max == green) + { + h = 60.0f * (2.0f + (float)(blue - red) / (float)delta); + } + else + { + h = 60.0f * (4.0f + (float)(red - green) / (float)delta); + } + + if (h < 0.0f) + { + h += 360.0f; + } + + *hue = (uint16_t)(h + 0.5f); +} + +static uint8_t apply_brightness(uint8_t value) +{ + return (uint8_t)((uint16_t)value * global_brightness / 255); } \ No newline at end of file diff --git a/led_manager.h b/led_manager.h index b0f2927..c1c62cb 100644 --- a/led_manager.h +++ b/led_manager.h @@ -61,6 +61,24 @@ extern "C" */ esp_err_t led_manager_set_rgb(uint8_t red, uint8_t green, uint8_t blue); + /** + * @brief Set global brightness for the LED + * + * @param brightness Brightness value (0-255) + * @return esp_err_t ESP_OK on success, error code on failure + */ + esp_err_t led_manager_set_brightness(uint8_t brightness); + + /** + * @brief Set LED color using HSV values + * + * @param hue Hue component (0-360) + * @param saturation Saturation component (0-255) + * @param value Value/brightness component (0-255) + * @return esp_err_t ESP_OK on success, error code on failure + */ + esp_err_t led_manager_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value); + /** * @brief Clear/turn off the LED *