DinnerRecv: working esp-idf version with ack
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/DinnerRecv/build/
|
||||||
@ -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
|
|
||||||
@ -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 {
|
typedef struct {
|
||||||
rmt_encoder_t base;
|
rmt_encoder_t base;
|
||||||
rmt_encoder_t *bytes_encoder;
|
rmt_encoder_t *bytes_encoder;
|
||||||
rmt_encoder_t *copy_encoder;
|
rmt_encoder_t *copy_encoder;
|
||||||
int state;
|
int state;
|
||||||
rmt_symbol_word_t reset_code;
|
rmt_symbol_word_t reset_code;
|
||||||
} rmt_led_strip_encoder_t;
|
} 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_ENCODER_FUNC_ATTR
|
||||||
{
|
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder,
|
||||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
rmt_channel_handle_t channel,
|
||||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
const void *primary_data, size_t data_size,
|
||||||
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
rmt_encode_state_t *ret_state) {
|
||||||
rmt_encode_state_t session_state = 0;
|
rmt_led_strip_encoder_t *led_encoder =
|
||||||
rmt_encode_state_t state = 0;
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
size_t encoded_symbols = 0;
|
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||||
|
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||||
switch (led_encoder->state) {
|
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||||
case 0: // send RGB data
|
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||||
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
size_t encoded_symbols = 0;
|
||||||
if (session_state & RMT_ENCODING_COMPLETE) {
|
switch (led_encoder->state) {
|
||||||
led_encoder->state = 1; // switch to next state when current encoding session finished
|
case 0: // send RGB data
|
||||||
}
|
encoded_symbols += bytes_encoder->encode(
|
||||||
if (session_state & RMT_ENCODING_MEM_FULL) {
|
bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||||
state |= RMT_ENCODING_MEM_FULL;
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
goto out; // yield if there's no free space for encoding artifacts
|
led_encoder->state =
|
||||||
}
|
1; // switch to next state when current encoding session finished
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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:
|
out:
|
||||||
*ret_state = state;
|
*ret_state = state;
|
||||||
return encoded_symbols;
|
return encoded_symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
|
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) {
|
||||||
{
|
rmt_led_strip_encoder_t *led_encoder =
|
||||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
rmt_del_encoder(led_encoder->copy_encoder);
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
free(led_encoder);
|
free(led_encoder);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
|
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_led_strip_encoder_t *led_encoder =
|
||||||
rmt_encoder_reset(led_encoder->bytes_encoder);
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
rmt_encoder_reset(led_encoder->copy_encoder);
|
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||||
led_encoder->state = 0;
|
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||||
return ESP_OK;
|
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 rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
||||||
{
|
rmt_encoder_handle_t *ret_encoder) {
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
rmt_led_strip_encoder_t *led_encoder = NULL;
|
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||||
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG,
|
||||||
led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t));
|
"invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
led_encoder = rmt_alloc_encoder_mem(sizeof(rmt_led_strip_encoder_t));
|
||||||
led_encoder->base.encode = rmt_encode_led_strip;
|
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG,
|
||||||
led_encoder->base.del = rmt_del_led_strip_encoder;
|
"no mem for led strip encoder");
|
||||||
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
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");
|
||||||
|
|
||||||
// different led strip might have its own timing requirements, following parameter is for WS2812
|
uint32_t reset_ticks = config->resolution / 1000000 * 50 /
|
||||||
rmt_bytes_encoder_config_t bytes_encoder_config = {
|
2; // reset code duration defaults to 50us
|
||||||
.bit0 = {
|
led_encoder->reset_code = (rmt_symbol_word_t){
|
||||||
.level0 = 1,
|
.level0 = 0,
|
||||||
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
|
.duration0 = reset_ticks,
|
||||||
.level1 = 0,
|
.level1 = 0,
|
||||||
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
|
.duration1 = reset_ticks,
|
||||||
},
|
};
|
||||||
.bit1 = {
|
*ret_encoder = &led_encoder->base;
|
||||||
.level0 = 1,
|
return ESP_OK;
|
||||||
.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:
|
err:
|
||||||
if (led_encoder) {
|
if (led_encoder) {
|
||||||
if (led_encoder->bytes_encoder) {
|
if (led_encoder->bytes_encoder) {
|
||||||
rmt_del_encoder(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);
|
|
||||||
}
|
}
|
||||||
return ret;
|
if (led_encoder->copy_encoder) {
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
}
|
||||||
|
free(led_encoder);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1,6 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "driver/rmt_encoder.h"
|
#include "driver/rmt_encoder.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -20,7 +26,7 @@ typedef struct {
|
|||||||
* @param[out] ret_encoder Returned encoder handle
|
* @param[out] ret_encoder Returned encoder handle
|
||||||
* @return
|
* @return
|
||||||
* - ESP_ERR_INVALID_ARG for any invalid arguments
|
* - 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_OK if creating encoder successfully
|
||||||
*/
|
*/
|
||||||
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "driver/gpio.h"
|
||||||
#include "driver/rmt_tx.h"
|
#include "driver/rmt_tx.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_now.h"
|
#include "esp_now.h"
|
||||||
@ -13,14 +14,18 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define LED_STRIP_GPIO_NUM 8
|
#define LED_STRIP_GPIO_NUM 8
|
||||||
#define LED_STRIP_LED_NUMBERS 4
|
#define LED_STRIP_LED_NUMBERS 8
|
||||||
#define LED_STRIP_RMT_RES_HZ \
|
#define LED_STRIP_RMT_RES_HZ \
|
||||||
(10 * 1000 * 1000) // 10MHz resolution, 1 tick = 0.1us
|
(10 * 1000 * 1000) // 10MHz resolution, 1 tick = 0.1us
|
||||||
|
|
||||||
|
#define BUTTON_GPIO_NUM 7
|
||||||
|
|
||||||
#define ESPNOW_WIFI_CHANNEL 6
|
#define ESPNOW_WIFI_CHANNEL 6
|
||||||
|
|
||||||
static const char *TAG = "DinnerRecv";
|
static const char *TAG = "DinnerRecv";
|
||||||
|
|
||||||
|
static const uint8_t dinner_send_mac[6] = {0x08, 0x3A, 0xF2, 0x3E, 0x6D, 0x34};
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
static bool dinner_alert = false;
|
static bool dinner_alert = false;
|
||||||
static uint64_t dinner_start_time = 0;
|
static uint64_t dinner_start_time = 0;
|
||||||
@ -28,6 +33,8 @@ static uint64_t last_blink_time = 0;
|
|||||||
static bool led_state = false;
|
static bool led_state = false;
|
||||||
static uint8_t breath = 0;
|
static uint8_t breath = 0;
|
||||||
static uint64_t last_breath_time = 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
|
// RMT and LED strip handles
|
||||||
static rmt_channel_handle_t led_chan = NULL;
|
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) {
|
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();
|
last_blink_time = get_time_ms();
|
||||||
led_state = !led_state;
|
led_state = !led_state;
|
||||||
|
|
||||||
if (led_state) {
|
if (led_state) {
|
||||||
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
|
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 {
|
} else {
|
||||||
led_strip_clear();
|
led_strip_clear();
|
||||||
@ -104,13 +111,13 @@ static void blink_all_leds(void) {
|
|||||||
static void breathe(void) {
|
static void breathe(void) {
|
||||||
uint8_t val = breath > 128 ? 256 - breath : breath;
|
uint8_t val = breath > 128 ? 256 - breath : breath;
|
||||||
for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) {
|
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();
|
led_strip_show();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dinner_animation(void) {
|
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;
|
dinner_alert = false;
|
||||||
ESP_LOGI(TAG, "Dinner alert timeout - returning to normal mode");
|
ESP_LOGI(TAG, "Dinner alert timeout - returning to normal mode");
|
||||||
led_strip_clear();
|
led_strip_clear();
|
||||||
@ -151,6 +158,19 @@ static esp_err_t init_wifi(void) {
|
|||||||
return ESP_OK;
|
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) {
|
static esp_err_t init_espnow(void) {
|
||||||
esp_err_t ret = esp_now_init();
|
esp_err_t ret = esp_now_init();
|
||||||
if (ret != ESP_OK) {
|
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_ERROR_CHECK(esp_now_register_recv_cb(on_data_received));
|
||||||
ESP_LOGI(TAG, "ESP-NOW initialized and ready to receive messages");
|
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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,16 +224,47 @@ static esp_err_t init_led_strip(void) {
|
|||||||
return ESP_OK;
|
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) {
|
void app_main(void) {
|
||||||
ESP_LOGI(TAG, "Dinner RECV");
|
ESP_LOGI(TAG, "Dinner RECV");
|
||||||
|
|
||||||
// Initialize LED strip
|
|
||||||
ESP_ERROR_CHECK(init_led_strip());
|
ESP_ERROR_CHECK(init_led_strip());
|
||||||
|
ESP_ERROR_CHECK(init_button());
|
||||||
// Initialize WiFi
|
|
||||||
ESP_ERROR_CHECK(init_wifi());
|
ESP_ERROR_CHECK(init_wifi());
|
||||||
|
|
||||||
// Initialize ESP-NOW
|
|
||||||
ESP_ERROR_CHECK(init_espnow());
|
ESP_ERROR_CHECK(init_espnow());
|
||||||
|
|
||||||
// Print WiFi parameters
|
// Print WiFi parameters
|
||||||
@ -214,11 +278,14 @@ void app_main(void) {
|
|||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while (1) {
|
while (1) {
|
||||||
|
check_button();
|
||||||
|
|
||||||
if (dinner_alert) {
|
if (dinner_alert) {
|
||||||
dinner_animation();
|
dinner_animation();
|
||||||
} else {
|
} else {
|
||||||
breath_animation();
|
breath_animation();
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(10)); // Small delay to prevent watchdog timeout
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // prevent watchdog timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,8 +22,10 @@ unsigned long lastDebounceTime = 0;
|
|||||||
unsigned long debounceDelay = 50;
|
unsigned long debounceDelay = 50;
|
||||||
|
|
||||||
// Broadcast MAC address for ESP-NOW
|
// Broadcast MAC address for ESP-NOW
|
||||||
uint8_t recvMAC[] = {0x08, 0x3A, 0xF2, 0x39, 0x0A, 0xA8};
|
//uint8_t recvMAC[] = {0x08, 0x3A, 0xF2, 0x39, 0x0A, 0xA8};
|
||||||
// 08:3A:F2:39:0A:A8
|
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
|
#define DELAYVAL 250
|
||||||
|
|
||||||
|
|||||||
69
esp32-c3-32s.txt
Normal file
69
esp32-c3-32s.txt
Normal file
@ -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
|
||||||
Reference in New Issue
Block a user