day/night cycle on LED 1 from CSV file

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-09-26 23:01:26 +02:00
parent f2e2fe4078
commit 845fdd306e
15 changed files with 340 additions and 80 deletions

View File

@@ -1,12 +0,0 @@
idf_component_register(SRCS "bootloader.c"
REQUIRES bootloader bootloader_support)
idf_build_get_property(target IDF_TARGET)
set(target_folder "${target}")
# Use the linker script files from the actual bootloader
set(scripts "${IDF_PATH}/components/bootloader/subproject/main/ld/${target_folder}/bootloader.ld"
"${IDF_PATH}/components/bootloader/subproject/main/ld/${target_folder}/bootloader.rom.ld")
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")

View File

@@ -1,65 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "bootloader_init.h"
#include "bootloader_utility.h"
#include "bootloader_common.h"
static const char* TAG = "boot";
static int select_partition_number(bootloader_state_t* bs);
/*
* We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
* The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
* We do have a stack, so we can do the initialization in C.
*/
void __attribute__((noreturn)) call_start_cpu0(void) {
// 1. Hardware initialization
if(bootloader_init() != ESP_OK) {
bootloader_reset();
}
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
// If this boot is a wake up from the deep sleep then go to the short way,
// try to load the application which worked before deep sleep.
// It skips a lot of checks due to it was done before (while first boot).
bootloader_utility_load_boot_image_from_deep_sleep();
// If it is not successful try to load an application as usual.
#endif
// 2. Select the number of boot partition
bootloader_state_t bs = {0};
int boot_index = select_partition_number(&bs);
if(boot_index == INVALID_INDEX) {
bootloader_reset();
}
// 2.1 Print a custom message!
ESP_LOGI(TAG, "Custom bootloader completed");
// 3. Load the app image for booting
bootloader_utility_load_boot_image(&bs, boot_index);
}
// Select the number of boot partition
static int select_partition_number(bootloader_state_t* bs) {
// 1. Load partition table
if(!bootloader_utility_load_partition_table(bs)) {
ESP_LOGE(TAG, "load partition table error!");
return INVALID_INDEX;
}
// 2. Select the number of boot partition
return bootloader_utility_get_selected_boot_partition(bs);
}
// Return global reent struct if any newlib functions are linked to bootloader
struct _reent* __getreent(void) {
return _GLOBAL_REENT;
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include "driver/rmt_tx.h"
#include "esp_check.h"
#include <stdint.h>
// Number of LEDs to be controlled

View File

@@ -72,7 +72,8 @@ void event_handler(void *arg, esp_event_base_t base, int32_t id, void *event_dat
}
led_strip_refresh(led_strip);
led_behavior_t led2_behavior = {.mode = LED_MODE_SOLID, .color = {.r = red, .g = green, .b = blue}};
led_behavior_t led2_behavior = {
.mode = LED_MODE_SOLID, .color = {.r = red, .g = green, .b = blue}, .on_time_ms = 0, .off_time_ms = 0};
led_status_set_behavior(2, led2_behavior);
}

View File

@@ -0,0 +1,8 @@
idf_component_register(SRCS
"simulator.c"
"storage.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES
led-manager
spiffs
)

View File

@@ -0,0 +1,17 @@
#pragma once
#include "esp_check.h"
#include <stdint.h>
esp_err_t add_light_item(const char time[5], uint8_t red, uint8_t green, uint8_t blue);
void cleanup_light_items(void);
#ifdef __cplusplus
extern "C"
{
#endif
void simulate(void *args);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,5 @@
#pragma once
void initialize_storage();
void load_file(const char *filename);

View File

@@ -0,0 +1,120 @@
#include "simulator.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "led_status.h"
#include "storage.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
static const char *TAG = "simulator";
// The struct is extended with a 'next' pointer to form a linked list.
typedef struct light_item_node_t
{
char time[5];
uint8_t red;
uint8_t green;
uint8_t blue;
struct light_item_node_t *next;
} light_item_node_t;
// Global pointers for the head and tail of the list.
static light_item_node_t *head = NULL;
static light_item_node_t *tail = NULL;
esp_err_t add_light_item(const char time[5], uint8_t red, uint8_t green, uint8_t blue)
{
// Allocate memory for a new node in PSRAM.
light_item_node_t *new_node = (light_item_node_t *)heap_caps_malloc(sizeof(light_item_node_t), MALLOC_CAP_SPIRAM);
if (new_node == NULL)
{
ESP_LOGE(TAG, "Failed to allocate memory in PSRAM for new light_item_node_t.");
return ESP_FAIL;
}
// Initialize the data of the new node.
memcpy(new_node->time, time, sizeof(new_node->time));
new_node->red = red;
new_node->green = green;
new_node->blue = blue;
new_node->next = NULL;
// Append the new node to the end of the list.
if (head == NULL)
{
// If the list is empty, the new node becomes both head and tail.
head = new_node;
tail = new_node;
}
else
{
// Otherwise, append the new node to the end and update tail.
tail->next = new_node;
tail = new_node;
}
return ESP_OK;
}
void cleanup_light_items(void)
{
light_item_node_t *current = head;
light_item_node_t *next_node;
while (current != NULL)
{
next_node = current->next;
heap_caps_free(current);
current = next_node;
}
head = NULL;
tail = NULL;
ESP_LOGI(TAG, "Cleaned up all light items.");
}
void simulate(void *args)
{
ESP_LOGI(TAG, "Simulation task started with args: %p", args);
initialize_storage();
load_file("/spiffs/schema_02.csv");
if (head == NULL)
{
ESP_LOGW(TAG, "Light schedule is empty. Simulation will not run.");
vTaskDelete(NULL);
return;
}
ESP_LOGI(TAG, "Starting simulation loop.");
light_item_node_t *current_item = head;
while (1)
{
if (current_item == NULL)
{
current_item = head;
ESP_LOGI(TAG, "Reached end of schedule, restarting from head.");
}
ESP_LOGI(TAG, "Simulating time: %s -> R:%d, G:%d, B:%d", current_item->time, current_item->red,
current_item->green, current_item->blue);
led_behavior_t led1_behavior = {
.mode = LED_MODE_SOLID,
.color = {.r = current_item->red, .g = current_item->green, .b = current_item->blue},
.on_time_ms = 0,
.off_time_ms = 0};
led_status_set_behavior(1, led1_behavior);
current_item = current_item->next;
vTaskDelay(pdMS_TO_TICKS(1000));
}
cleanup_light_items();
}

View File

@@ -0,0 +1,77 @@
#include "storage.h"
#include "esp_check.h"
#include "esp_log.h"
#include "esp_spiffs.h"
#include "simulator.h"
#include <errno.h>
#include <stdio.h>
static const char *TAG = "storage";
void initialize_storage()
{
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs", // Der Basispfad, unter dem das Dateisystem gemountet wird
.partition_label = NULL, // NULL, um die erste gefundene SPIFFS-Partition zu verwenden
.max_files = 5, // Maximale Anzahl gleichzeitig geöffneter Dateien
.format_if_mount_failed = false // Partition formatieren, wenn das Mounten fehlschlägt
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount or format filesystem");
}
else if (ret == ESP_ERR_NOT_FOUND)
{
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
}
else
{
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return; // Oder entsprechende Fehlerbehandlung
}
}
void load_file(const char *filename)
{
ESP_LOGI(TAG, "Loading file: %s", filename);
FILE *f = fopen(filename, "r");
if (f == NULL)
{
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[128]; // Puffer für eine Zeile, vergrößert für mehr Sicherheit
while (fgets(line, sizeof(line), f))
{
// Entferne möglichen Zeilenumbruch am Ende
char *pos = strchr(line, '\n');
if (pos)
{
*pos = '\0';
}
char time[5] = {0}; // 4 Zeichen + Nullterminator
int red, green, blue;
// Parse die Zeile im Format "HHMM,R,G,B"
int items_scanned = sscanf(line, "%4[^,],%d,%d,%d", time, &red, &green, &blue);
if (items_scanned == 4)
{
add_light_item(time, (uint8_t)red, (uint8_t)green, (uint8_t)blue);
}
else
{
ESP_LOGW(TAG, "Could not parse line: %s", line);
}
}
fclose(f);
ESP_LOGI(TAG, "Finished loading file.");
}

View File

@@ -11,6 +11,7 @@ idf_component_register(SRCS
connectivity-manager
led-manager
persistence-manager
simulator
u8g2
nvs_flash
esp_timer
@@ -19,3 +20,5 @@ idf_component_register(SRCS
app_update
rmaker_common
)
spiffs_create_partition_image(storage ../spiffs_image FLASH_IN_PROJECT)

View File

@@ -10,6 +10,7 @@
#include "led_status.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "simulator.h"
#include "wifi_manager.h"
#ifdef __cplusplus
@@ -33,6 +34,7 @@ extern "C"
register_handler();
xTaskCreatePinnedToCore(app_task, "app_task", 4096, NULL, tskIDLE_PRIORITY + 1, NULL, portNUM_PROCESSORS - 1);
xTaskCreatePinnedToCore(simulate, "simulate", 4096, NULL, tskIDLE_PRIORITY + 1, NULL, portNUM_PROCESSORS - 1);
// xTaskCreatePinnedToCore(ble_manager_task, "ble_manager", 4096, NULL, tskIDLE_PRIORITY + 1, NULL,
// portNUM_PROCESSORS - 1);

View File

@@ -1,6 +1,7 @@
# Name , Type , SubType , Offset , Size , Flags
nvs , data , nvs , 0x9000 , 24k ,
phy_init , data , phy , , 4k ,
factory , app , factory , 0x10000 , 3072K ,
factory , app , factory , 0x10000 , 2048K ,
storage , data , spiffs , , 1024K ,
coredump , data , coredump , , 576k ,
fctry , data , nvs , , 24k ,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 24k
3 phy_init data phy 4k
4 factory app factory 0x10000 3072K 2048K
5 storage data spiffs 1024K
6 coredump data coredump 576k
7 fctry data nvs 24k

View File

@@ -35,3 +35,10 @@ CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM=64
CONFIG_ESP32_CORE_DUMP_STACK_SIZE=1024
CONFIG_ESP_RMAKER_DEF_TIMEZONE="Europe/Berlin"
# ESP PSRAM
CONFIG_SPIRAM=y
# SPI RAM config
CONFIG_SPIRAM_SPEED=80
CONFIG_SPIRAM_USE_CAPS_ALLOC=y

View File

@@ -0,0 +1,48 @@
0000,25,25,112
0030,25,25,112
0100,25,25,112
0130,25,25,112
0200,25,25,112
0230,25,25,112
0300,25,25,112
0330,25,25,112
0400,25,25,112
0430,140,25,112
0500,255,130,112
0530,255,155,112
0600,255,177,115
0630,255,200,135
0700,255,219,170
0730,255,234,205
0800,255,249,240
0830,255,249,250
0900,239,245,255
0930,224,240,255
1000,215,235,255
1030,212,234,255
1100,210,233,255
1130,208,232,255
1200,207,231,255
1230,205,230,255
1300,204,229,255
1330,204,229,255
1400,206,230,255
1430,208,231,255
1500,213,232,255
1530,219,234,255
1600,229,239,255
1630,236,246,255
1700,255,252,251
1730,255,243,236
1800,255,225,202
1830,255,203,174
1900,255,178,129
1930,255,146,85
2000,255,93,38
2030,140,55,70
2100,25,25,112
2130,25,25,112
2200,25,25,112
2230,25,25,112
2300,25,25,112
2330,25,25,112
1 0000 25 25 112
2 0030 25 25 112
3 0100 25 25 112
4 0130 25 25 112
5 0200 25 25 112
6 0230 25 25 112
7 0300 25 25 112
8 0330 25 25 112
9 0400 25 25 112
10 0430 140 25 112
11 0500 255 130 112
12 0530 255 155 112
13 0600 255 177 115
14 0630 255 200 135
15 0700 255 219 170
16 0730 255 234 205
17 0800 255 249 240
18 0830 255 249 250
19 0900 239 245 255
20 0930 224 240 255
21 1000 215 235 255
22 1030 212 234 255
23 1100 210 233 255
24 1130 208 232 255
25 1200 207 231 255
26 1230 205 230 255
27 1300 204 229 255
28 1330 204 229 255
29 1400 206 230 255
30 1430 208 231 255
31 1500 213 232 255
32 1530 219 234 255
33 1600 229 239 255
34 1630 236 246 255
35 1700 255 252 251
36 1730 255 243 236
37 1800 255 225 202
38 1830 255 203 174
39 1900 255 178 129
40 1930 255 146 85
41 2000 255 93 38
42 2030 140 55 70
43 2100 25 25 112
44 2130 25 25 112
45 2200 25 25 112
46 2230 25 25 112
47 2300 25 25 112
48 2330 25 25 112

View File

@@ -0,0 +1,48 @@
0000,25,25,112
0030,25,25,112
0100,25,25,112
0130,25,25,112
0200,25,25,112
0230,25,25,112
0300,25,25,112
0330,62,25,95
0400,102,60,78
0430,140,78,61
0500,178,95,44
0530,214,113,27
0600,255,130,10
0630,255,139,22
0700,255,147,34
0730,255,155,46
0800,255,163,58
0830,255,172,70
0900,255,180,82
0930,255,189,93
1000,255,197,105
1030,255,205,117
1100,255,213,129
1130,255,222,141
1200,255,230,153
1230,255,222,143
1300,255,214,133
1330,255,206,124
1400,255,198,114
1430,255,191,104
1500,255,183,94
1530,255,175,84
1600,255,167,74
1630,255,159,64
1700,255,151,55
1730,255,143,45
1800,255,135,35
1830,214,116,45
1900,178,98,61
1930,140,80,74
2000,102,62,86
2030,63,44,99
2100,25,25,112
2130,25,25,112
2200,25,25,112
2230,25,25,112
2300,25,25,112
2330,25,25,112
1 0000 25 25 112
2 0030 25 25 112
3 0100 25 25 112
4 0130 25 25 112
5 0200 25 25 112
6 0230 25 25 112
7 0300 25 25 112
8 0330 62 25 95
9 0400 102 60 78
10 0430 140 78 61
11 0500 178 95 44
12 0530 214 113 27
13 0600 255 130 10
14 0630 255 139 22
15 0700 255 147 34
16 0730 255 155 46
17 0800 255 163 58
18 0830 255 172 70
19 0900 255 180 82
20 0930 255 189 93
21 1000 255 197 105
22 1030 255 205 117
23 1100 255 213 129
24 1130 255 222 141
25 1200 255 230 153
26 1230 255 222 143
27 1300 255 214 133
28 1330 255 206 124
29 1400 255 198 114
30 1430 255 191 104
31 1500 255 183 94
32 1530 255 175 84
33 1600 255 167 74
34 1630 255 159 64
35 1700 255 151 55
36 1730 255 143 45
37 1800 255 135 35
38 1830 214 116 45
39 1900 178 98 61
40 1930 140 80 74
41 2000 102 62 86
42 2030 63 44 99
43 2100 25 25 112
44 2130 25 25 112
45 2200 25 25 112
46 2230 25 25 112
47 2300 25 25 112
48 2330 25 25 112