starting status WLEDs behavior

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-08-23 16:02:21 +02:00
parent d8b1718069
commit 6e84d57b77
9 changed files with 252 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
# Definiere die Quelldateien in einer Variable
# Define the source files in a variable
set(SOURCE_FILES
src/common/InactivityTracker.cpp
src/common/Menu.cpp

View File

@@ -6,6 +6,7 @@ if (DEFINED ENV{IDF_PATH})
PRIV_REQUIRES
u8g2
esp_event
esp_timer
persistence-manager
)
return()

View File

@@ -1,3 +1,51 @@
#pragma once
void led_status_init();
#include "driver/rmt_tx.h"
#include <stdint.h>
// Number of LEDs to be controlled
#define STATUS_LED_COUNT 3
// Possible lighting modes
typedef enum
{
LED_MODE_OFF,
LED_MODE_SOLID,
LED_MODE_BLINK
} led_mode_t;
// Structure for an RGB color
typedef struct
{
uint8_t r;
uint8_t g;
uint8_t b;
} rgb_t;
// This is the structure you pass from the outside to define a behavior
typedef struct
{
led_mode_t mode;
rgb_t color;
uint32_t on_time_ms = 0; // Only relevant for BLINK
uint32_t off_time_ms = 0; // Only relevant for BLINK
} led_behavior_t;
/**
* @brief Initializes the status manager and the LED strip.
*
* @param gpio_num GPIO where the data line of the LEDs is connected.
* @return esp_err_t ESP_OK on success.
*/
esp_err_t led_status_init(int gpio_num);
/**
* @brief Sets the lighting behavior for a single LED.
*
* This function is thread-safe.
*
* @param index Index of the LED (0 to STATUS_LED_COUNT - 1).
* @param behavior The structure with the desired behavior.
* @return esp_err_t ESP_OK on success, ESP_ERR_INVALID_ARG on invalid index.
*/
esp_err_t led_status_set_behavior(uint8_t index, led_behavior_t behavior);

View File

@@ -18,20 +18,26 @@ const char *TAG = "LED";
uint64_t wled_init(void)
{
led_strip_config_t strip_config = {.strip_gpio_num = CONFIG_WLED_DIN_PIN,
.max_leds = 64,
.led_model = LED_MODEL_WS2812,
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,
.flags = {
.invert_out = false,
}};
led_strip_config_t strip_config = {
.strip_gpio_num = CONFIG_WLED_DIN_PIN,
.max_leds = 64,
.led_model = LED_MODEL_WS2812,
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,
.flags =
{
.invert_out = false,
},
};
led_strip_rmt_config_t rmt_config = {.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = 0,
.mem_block_symbols = 0,
.flags = {
.with_dma = true,
}};
led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = 0,
.mem_block_symbols = 0,
.flags =
{
.with_dma = true,
},
};
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
@@ -74,12 +80,12 @@ uint64_t send_event(uint32_t event, led_event_data_t *payload)
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = esp_event_post_to(loop_handle, // Event-Loop Handle
LED_EVENTS_BASE, // Event Base
esp_err_t err = esp_event_post_to(loop_handle, // Event loop handle
LED_EVENTS_BASE, // Event base
event, // Event ID (EVENT_LED_ON, EVENT_LED_OFF, etc.)
payload, // Daten-Pointer
sizeof(led_event_data_t), // Datengröße
portMAX_DELAY // Wartezeit
payload, // Data pointer
sizeof(led_event_data_t), // Data size
portMAX_DELAY // Wait time
);
if (err != ESP_OK)

View File

@@ -1,7 +1,145 @@
#include "led_status.h"
void led_status_init()
#include "esp_log.h"
#include "esp_timer.h" // For high-resolution timestamps
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "led_strip.h"
static const char *TAG = "LED_STATUS";
// Internal control structure for each LED
typedef struct
{
// This function is intentionally left empty for the native implementation.
// It serves as a placeholder to maintain compatibility with the HAL interface.
led_behavior_t behavior; // The desired behavior (target state)
uint64_t last_toggle_time_us; // Timestamp of the last toggle (in microseconds)
bool is_on_in_blink; // Current state in blink mode (actual state)
} led_control_t;
// --- Module variables ---
static led_strip_handle_t led_strip;
static led_control_t led_controls[STATUS_LED_COUNT];
static SemaphoreHandle_t mutex; // To protect the led_controls array
// The core: The task that controls the LEDs
static void led_status_task(void *pvParameters)
{
ESP_LOGI(TAG, "Led Status Task started.");
while (1)
{
uint64_t now_us = esp_timer_get_time();
// Take the mutex to safely access the control data
if (xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE)
{
for (int i = 0; i < STATUS_LED_COUNT; i++)
{
led_control_t *control = &led_controls[i];
switch (control->behavior.mode)
{
case LED_MODE_OFF:
led_strip_set_pixel(led_strip, i, 0, 0, 0);
break;
case LED_MODE_SOLID:
led_strip_set_pixel(led_strip, i, control->behavior.color.r, control->behavior.color.g,
control->behavior.color.b);
break;
case LED_MODE_BLINK: {
uint32_t duration_ms =
control->is_on_in_blink ? control->behavior.on_time_ms : control->behavior.off_time_ms;
if ((now_us - control->last_toggle_time_us) / 1000 >= duration_ms)
{
control->is_on_in_blink = !control->is_on_in_blink; // Toggle state
control->last_toggle_time_us = now_us; // Update timestamp
}
if (control->is_on_in_blink)
{
led_strip_set_pixel(led_strip, i, control->behavior.color.r, control->behavior.color.g,
control->behavior.color.b);
}
else
{
led_strip_set_pixel(led_strip, i, 0, 0, 0);
}
}
break;
}
}
// Release the mutex
xSemaphoreGive(mutex);
}
// Update the physical LED strip with the new values
led_strip_refresh(led_strip);
// Delay task for 20ms before the next iteration
vTaskDelay(pdMS_TO_TICKS(20));
}
}
// Initialization function
esp_err_t led_status_init(int gpio_num)
{
// LED strip configuration (e.g., for WS2812)
led_strip_config_t strip_config = {
.strip_gpio_num = gpio_num,
.max_leds = STATUS_LED_COUNT,
.led_model = LED_MODEL_WS2812,
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRBW,
.flags =
{
.invert_out = false,
},
};
led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = 10 * 1000 * 1000, // 10MHz
.mem_block_symbols = 0,
.flags =
{
.with_dma = false,
},
};
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
ESP_LOGI(TAG, "LED strip initialized.");
// Create mutex
mutex = xSemaphoreCreateMutex();
if (mutex == NULL)
{
ESP_LOGE(TAG, "Could not create mutex.");
return ESP_FAIL;
}
// Start task
xTaskCreate(led_status_task, "led_status_task", 2048, NULL, 5, NULL);
return ESP_OK;
}
// Function to set the behavior
esp_err_t led_status_set_behavior(uint8_t index, led_behavior_t behavior)
{
if (index >= STATUS_LED_COUNT)
{
return ESP_ERR_INVALID_ARG;
}
if (xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE)
{
led_controls[index].behavior = behavior;
// Reset internal state variables to start the new pattern cleanly
led_controls[index].is_on_in_blink = false;
led_controls[index].last_toggle_time_us = esp_timer_get_time();
xSemaphoreGive(mutex);
}
return ESP_OK;
}