diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da45c34 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/DinnerRecv/build/ diff --git a/DinnerRecv/CLAUDE.md b/DinnerRecv/CLAUDE.md deleted file mode 100644 index c6e982f..0000000 --- a/DinnerRecv/CLAUDE.md +++ /dev/null @@ -1,42 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -DinnerRecv is an Arduino project for a FireBeetle 2 ESP32-E microcontroller that controls a WS2812B LED strip. The project creates a sequential white light animation across 8 LEDs. - -## Hardware Configuration - -- **Microcontroller**: FireBeetle 2 ESP32-E -- **LED Strip**: WS2812B (8 pixels) -- **Data Pin**: GPIO 16 -- **Power**: 5V from bottom of the board (under USB connector) -- **Resistor**: 470 Ohm between data line and LED strip - -## Development Environment - -This is an Arduino sketch (.ino file) that should be developed using: -- Arduino IDE -- PlatformIO -- Or other Arduino-compatible development environment - -## Key Dependencies - -- `Adafruit_NeoPixel` library for WS2812B LED control - -## Code Architecture - -The code follows standard Arduino structure: -- `setup()`: Initializes serial communication (115200 baud) and LED strip -- `loop()`: Continuously runs the LED animation sequence - -## Hardware Reference - -Implementation follows the tutorial at: https://esp32io.com/tutorials/esp32-ws2812b-led-strip - -## Configuration Constants - -- `PIN 16`: Data pin for LED strip -- `NUMPIXELS 8`: Number of LEDs in the strip -- `DELAYVAL 50`: Delay in milliseconds between LED updates \ No newline at end of file diff --git a/DinnerRecv/main/led_strip_encoder.c b/DinnerRecv/main/led_strip_encoder.c index 0f717bd..a6af5ea 100644 --- a/DinnerRecv/main/led_strip_encoder.c +++ b/DinnerRecv/main/led_strip_encoder.c @@ -1,121 +1,143 @@ -#include "esp_check.h" -#include "led_strip_encoder.h" +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ -static const char *TAG = "led_strip_encoder"; +#include "led_strip_encoder.h" +#include "esp_check.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_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 = 0; - rmt_encode_state_t state = 0; - 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 = 0; // 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 - } +RMT_ENCODER_FUNC_ATTR +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; + *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->copy_encoder); - rmt_del_encoder(led_encoder->bytes_encoder); - free(led_encoder); - return ESP_OK; +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 = 0; - return ESP_OK; +RMT_ENCODER_FUNC_ATTR +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; - - // different led strip might have its own timing requirements, following parameter is for WS2812 - 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; +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 = rmt_alloc_encoder_mem(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; + // different led strip might have its own timing requirements, following + // parameter is for WS2812 + 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); + if (led_encoder) { + if (led_encoder->bytes_encoder) { + rmt_del_encoder(led_encoder->bytes_encoder); } - return ret; -} \ No newline at end of file + if (led_encoder->copy_encoder) { + rmt_del_encoder(led_encoder->copy_encoder); + } + free(led_encoder); + } + return ret; +} diff --git a/DinnerRecv/main/led_strip_encoder.h b/DinnerRecv/main/led_strip_encoder.h index 085d715..c0155c3 100644 --- a/DinnerRecv/main/led_strip_encoder.h +++ b/DinnerRecv/main/led_strip_encoder.h @@ -1,6 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "driver/rmt_encoder.h" +#include #ifdef __cplusplus extern "C" { @@ -20,7 +26,7 @@ typedef struct { * @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 encoder + * - 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, diff --git a/DinnerRecv/main/main.c b/DinnerRecv/main/main.c index 3fd4a55..fa7629c 100644 --- a/DinnerRecv/main/main.c +++ b/DinnerRecv/main/main.c @@ -1,3 +1,4 @@ +#include "driver/gpio.h" #include "driver/rmt_tx.h" #include "esp_log.h" #include "esp_now.h" @@ -13,14 +14,18 @@ #include #define LED_STRIP_GPIO_NUM 8 -#define LED_STRIP_LED_NUMBERS 4 +#define LED_STRIP_LED_NUMBERS 8 #define LED_STRIP_RMT_RES_HZ \ (10 * 1000 * 1000) // 10MHz resolution, 1 tick = 0.1us +#define BUTTON_GPIO_NUM 7 + #define ESPNOW_WIFI_CHANNEL 6 static const char *TAG = "DinnerRecv"; +static const uint8_t dinner_send_mac[6] = {0x08, 0x3A, 0xF2, 0x3E, 0x6D, 0x34}; + // Global variables static bool dinner_alert = false; static uint64_t dinner_start_time = 0; @@ -28,6 +33,8 @@ static uint64_t last_blink_time = 0; static bool led_state = false; static uint8_t breath = 0; static uint64_t last_breath_time = 0; +static bool button_pressed = false; +static uint64_t last_button_time = 0; // RMT and LED strip handles static rmt_channel_handle_t led_chan = NULL; @@ -86,13 +93,13 @@ static void on_data_received(const esp_now_recv_info_t *mac_addr, } static void blink_all_leds(void) { - if (get_time_ms() - last_blink_time >= 2000) { + if (get_time_ms() - last_blink_time >= 500) { last_blink_time = get_time_ms(); led_state = !led_state; if (led_state) { for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) { - led_strip_set_pixel(i, 255, 0, 0); + led_strip_set_pixel(i, 0, 0, 255); // G R B } } else { led_strip_clear(); @@ -104,13 +111,13 @@ static void blink_all_leds(void) { static void breathe(void) { uint8_t val = breath > 128 ? 256 - breath : breath; for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) { - led_strip_set_pixel(i, 0, 0, val); + led_strip_set_pixel(i, val, val, val); } led_strip_show(); } static void dinner_animation(void) { - if (get_time_ms() - dinner_start_time > 15 * 1000) { + if (get_time_ms() - dinner_start_time > 20 * 1000) { dinner_alert = false; ESP_LOGI(TAG, "Dinner alert timeout - returning to normal mode"); led_strip_clear(); @@ -151,6 +158,19 @@ static esp_err_t init_wifi(void) { return ESP_OK; } +static esp_err_t send_dinner_ack(void) { + const char *message = "dinner-ack"; + esp_err_t ret = + esp_now_send(dinner_send_mac, (const uint8_t *)message, strlen(message)); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to send dinner-ack: %s", esp_err_to_name(ret)); + return ret; + } + + ESP_LOGI(TAG, "Sent dinner-ack message"); + return ESP_OK; +} + static esp_err_t init_espnow(void) { esp_err_t ret = esp_now_init(); if (ret != ESP_OK) { @@ -161,6 +181,19 @@ static esp_err_t init_espnow(void) { ESP_ERROR_CHECK(esp_now_register_recv_cb(on_data_received)); ESP_LOGI(TAG, "ESP-NOW initialized and ready to receive messages"); + ret = esp_now_add_peer(&(esp_now_peer_info_t){ + .peer_addr = {dinner_send_mac[0], dinner_send_mac[1], dinner_send_mac[2], + dinner_send_mac[3], dinner_send_mac[4], dinner_send_mac[5]}, + .channel = ESPNOW_WIFI_CHANNEL, + .encrypt = false, + }); + + if (ret != ESP_OK && ret != ESP_ERR_ESPNOW_EXIST) { + ESP_LOGE(TAG, "Failed to add peer: %s", esp_err_to_name(ret)); + return ret; + } + ESP_LOGI(TAG, "ESP-NOW sender registered"); + return ESP_OK; } @@ -191,16 +224,47 @@ static esp_err_t init_led_strip(void) { return ESP_OK; } +static esp_err_t init_button(void) { + gpio_config_t io_conf = { + .pin_bit_mask = (1ULL << BUTTON_GPIO_NUM), + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + ESP_ERROR_CHECK(gpio_config(&io_conf)); + ESP_LOGI(TAG, "Button initialized on GPIO %d", BUTTON_GPIO_NUM); + return ESP_OK; +} + +static void check_button(void) { + int button_level = gpio_get_level(BUTTON_GPIO_NUM); + uint64_t current_time = get_time_ms(); + + if (button_level == 0 && !button_pressed && + (current_time - last_button_time > 200)) { + button_pressed = true; + last_button_time = current_time; + ESP_LOGI(TAG, "Button pressed!"); + + if (dinner_alert) { + dinner_alert = false; + ESP_LOGI(TAG, "Dinner alert dismissed by button press"); + led_strip_clear(); + led_strip_show(); + send_dinner_ack(); + } + } else if (button_level == 1) { + button_pressed = false; + } +} + void app_main(void) { ESP_LOGI(TAG, "Dinner RECV"); - // Initialize LED strip ESP_ERROR_CHECK(init_led_strip()); - - // Initialize WiFi + ESP_ERROR_CHECK(init_button()); ESP_ERROR_CHECK(init_wifi()); - - // Initialize ESP-NOW ESP_ERROR_CHECK(init_espnow()); // Print WiFi parameters @@ -214,11 +278,14 @@ void app_main(void) { // Main loop while (1) { + check_button(); + if (dinner_alert) { dinner_animation(); } else { breath_animation(); } - vTaskDelay(pdMS_TO_TICKS(10)); // Small delay to prevent watchdog timeout + + vTaskDelay(pdMS_TO_TICKS(10)); // prevent watchdog timeout } } diff --git a/DinnerSend/DinnerSend.ino b/DinnerSend/DinnerSend.ino index facb383..54d3515 100644 --- a/DinnerSend/DinnerSend.ino +++ b/DinnerSend/DinnerSend.ino @@ -22,8 +22,10 @@ unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50; // Broadcast MAC address for ESP-NOW -uint8_t recvMAC[] = {0x08, 0x3A, 0xF2, 0x39, 0x0A, 0xA8}; -// 08:3A:F2:39:0A:A8 +//uint8_t recvMAC[] = {0x08, 0x3A, 0xF2, 0x39, 0x0A, 0xA8}; +uint8_t recvMAC[] = {0x7c, 0xdf, 0xa1, 0xb4, 0x48, 0x14}; +// 7c:df:a1:b4:48:14 - esp32-c3-32s +// 08:3A:F2:39:0A:A8 - other firebeetle #define DELAYVAL 250 diff --git a/esp32-c3-32s.txt b/esp32-c3-32s.txt new file mode 100644 index 0000000..7f72030 --- /dev/null +++ b/esp32-c3-32s.txt @@ -0,0 +1,69 @@ +this was retrieved from `idf.py monitor` from the esp-idf hello-world example using all esp-idf toolchain as described in + +https://www.embeddedrelated.com/showarticle/1434.php#ESP-IDF_Installation + + + +ESP-ROM:esp32c3-api1-20210207 +Build:Feb 7 2021 +rst:0xc (RTC_SW_CPU_RST),boot:0xc (SPI_FAST_FLASH_BOOT) +Saved PC:0x40382ffc +--- 0x40382ffc: esp_restart_noos at /home/alx/esp/esp-idf/components/esp_system/port/soc/esp32c3/system_internal.c:116 +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fcd5820,len:0x15c4 +load:0x403cbf10,len:0xc64 +--- 0x403cbf10: esp_bootloader_get_description at /home/alx/esp/esp-idf/components/esp_bootloader_format/esp_bootloader_desc.c:40 +load:0x403ce710,len:0x2fcc +--- 0x403ce710: esp_flash_encryption_enabled at /home/alx/esp/esp-idf/components/bootloader_support/src/flash_encrypt.c:89 +entry 0x403cbf1a +--- 0x403cbf1a: call_start_cpu0 at /home/alx/esp/esp-idf/components/bootloader/subproject/main/bootloader_start.c:25 +I (35) boot: ESP-IDF v6.0-dev-2039-g2044fba6e7 2nd stage bootloader +I (35) boot: compile time Sep 15 2025 11:08:39 +I (35) boot: chip revision: v0.3 +I (37) boot: efuse block revision: v1.1 +I (40) boot.esp32c3: SPI Speed : 80MHz +I (44) boot.esp32c3: SPI Mode : DIO +I (48) boot.esp32c3: SPI Flash Size : 2MB +I (52) boot: Enabling RNG early entropy source... +I (56) boot: Partition Table: +I (59) boot: ## Label Usage Type ST Offset Length +I (65) boot: 0 nvs WiFi data 01 02 00009000 00006000 +I (72) boot: 1 phy_init RF data 01 01 0000f000 00001000 +I (78) boot: 2 factory factory app 00 00 00010000 00100000 +I (85) boot: End of partition table +I (88) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=0638ch ( 25484) map +I (100) esp_image: segment 1: paddr=000163b4 vaddr=3fc89c00 size=013a8h ( 5032) load +I (104) esp_image: segment 2: paddr=00017764 vaddr=40380000 size=088b4h ( 34996) load +I (117) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=10308h ( 66312) map +I (128) esp_image: segment 4: paddr=00030330 vaddr=403888b4 size=012d4h ( 4820) load +I (130) esp_image: segment 5: paddr=0003160c vaddr=50000000 size=00020h ( 32) load +I (136) boot: Loaded app from partition at offset 0x10000 +I (138) boot: Disabling RNG early entropy source... +I (154) cpu_start: Unicore app +I (162) cpu_start: GPIO 20 and 21 are used as console UART I/O pins +I (163) cpu_start: Pro cpu start user code +I (163) cpu_start: cpu freq: 160000000 Hz +I (165) app_init: Application information: +I (168) app_init: Project name: hello_world +I (173) app_init: App version: 1 +I (176) app_init: Compile time: Sep 15 2025 11:08:37 +I (181) app_init: ELF file SHA256: a67f59997... +I (185) app_init: ESP-IDF: v6.0-dev-2039-g2044fba6e7 +I (191) efuse_init: Min chip rev: v0.3 +I (195) efuse_init: Max chip rev: v1.99 +I (199) efuse_init: Chip rev: v0.3 +I (203) heap_init: Initializing. RAM available for dynamic allocation: +I (209) heap_init: At 3FC8BDE0 len 00034220 (208 KiB): RAM +I (214) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM +I (220) heap_init: At 3FCDC710 len 00002950 (10 KiB): Retention RAM +I (226) heap_init: At 50000020 len 00001FC8 (7 KiB): RTCRAM +I (232) spi_flash: detected chip: generic +I (235) spi_flash: flash io: dio +I (238) sleep_gpio: Configure to isolate all GPIO pins in sleep state +I (244) sleep_gpio: Enable automatic switching of GPIO sleep configuration +I (251) main_task: Started on CPU0 +I (251) main_task: Calling app_main() +Hello world! +This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision v0.3, 2MB external flash +Minimum free heap size: 339008 bytes