Send ESP-NOW accel only on deadzone change and harden BLE+WiFi OTA coex.

Quiet pods no longer spam 100 Hz samples; mute wifi logs and throttle BLE
notifies during slave distribution so the wifi task stack does not panic.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-02 00:55:50 +01:00
co-authored by Cursor
parent 141176a824
commit 8f90dfe82f
9 changed files with 112 additions and 14 deletions
+2 -2
View File
@@ -315,7 +315,7 @@ Alle Master-Sends laufen über `send_message()` / `send_message_ex()`:
| Nachricht | Task / Trigger | Master-Ziel | | Nachricht | Task / Trigger | Master-Ziel |
|-----------|----------------|-------------| |-----------|----------------|-------------|
| `ESPNOW_ACCEL_SAMPLE` | `slave_accel_stream_task` 10 ms, 1 ms slots via Discover `master_time_us` | `client_registry_update_accel()` | | `ESPNOW_ACCEL_SAMPLE` | `accel_stream_task` poll 10 ms + deadzone (nur bei Änderung), 1 ms slots via Discover `master_time_us` | `client_registry_update_accel()` |
| `ESPNOW_TAP_EVENT` | BMA456-IRQ → `on_bma456_tap` | `client_registry_update_tap()` | | `ESPNOW_TAP_EVENT` | BMA456-IRQ → `on_bma456_tap` | `client_registry_update_tap()` |
| `ESPNOW_BATTERY_REPORT` | Heartbeat + nach Join | `client_registry_update_battery()` | | `ESPNOW_BATTERY_REPORT` | Heartbeat + nach Join | `client_registry_update_battery()` |
| `ESPNOW_SLAVE_INFO` / `HEARTBEAT` | `slave_tx_task` / Heartbeat-Task | `client_registry_heartbeat()` | | `ESPNOW_SLAVE_INFO` / `HEARTBEAT` | `slave_tx_task` / Heartbeat-Task | `client_registry_heartbeat()` |
@@ -366,7 +366,7 @@ flowchart TB
| `espnow_mon` | Master | 1 s Timeout + Master-Battery | | `espnow_mon` | Master | 1 s Timeout + Master-Battery |
| `espnow_stx` | Slave | Queue: SLAVE_INFO, Battery nach Join | | `espnow_stx` | Slave | Queue: SLAVE_INFO, Battery nach Join |
| `espnow_hb` | Slave | 1 s Heartbeat + 30 s Battery | | `espnow_hb` | Slave | 1 s Heartbeat + 30 s Battery |
| `espnow_accel` | Slave | 10 ms Accel in ID-Slot (1 ms) wenn Stream an | | `espnow_accel` | Slave | Accel poll 10 ms / TX bei Deadzone-Änderung, ID-Slot 1 ms wenn Stream an |
| `bma456_poll` | Beide | 10 Hz (`bosch456.c`) | | `bma456_poll` | Beide | 10 Hz (`bosch456.c`) |
| `vTaskLedRing` | Beide | LED-Ring-Befehle | | `vTaskLedRing` | Beide | LED-Ring-Befehle |
+5 -4
View File
@@ -177,7 +177,7 @@ UART_CMD_REQ(&uart_msg, alox_UartMessage_accel_deadzone_request_tag, accel_deadz
| `ESPNOW_HEARTBEAT` | S→M | `heartbeat` | Keepalive 1 s | | `ESPNOW_HEARTBEAT` | S→M | `heartbeat` | Keepalive 1 s |
| `ESPNOW_SET_ACCEL_DEADZONE` | M→S | `accel_deadzone` | Deadzone LSB | | `ESPNOW_SET_ACCEL_DEADZONE` | M→S | `accel_deadzone` | Deadzone LSB |
| `ESPNOW_SET_TAP_CONFIG` | M→S | `tap_config` | Multitap-Parameter + NVS | | `ESPNOW_SET_TAP_CONFIG` | M→S | `tap_config` | Multitap-Parameter + NVS |
| `ESPNOW_SET_ACCEL_STREAM` | M→S | `accel_stream` | Stream ~10 ms (best-effort) | | `ESPNOW_SET_ACCEL_STREAM` | M→S | `accel_stream` | Stream poll ~10 ms, TX on deadzone change |
| `ESPNOW_ACCEL_SAMPLE` | S→M | `accel_sample` | x/y/z Roh-LSB | | `ESPNOW_ACCEL_SAMPLE` | S→M | `accel_sample` | x/y/z Roh-LSB |
| `ESPNOW_SET_TAP_NOTIFY` | M→S | `tap_notify` | Tap-Arten filtern | | `ESPNOW_SET_TAP_NOTIFY` | M→S | `tap_notify` | Tap-Arten filtern |
| `ESPNOW_TAP_EVENT` | S→M | `tap_event` | kind 1/2/3 | | `ESPNOW_TAP_EVENT` | S→M | `tap_event` | kind 1/2/3 |
@@ -199,7 +199,7 @@ UART_CMD_REQ(&uart_msg, alox_UartMessage_accel_deadzone_request_tag, accel_deadz
| Heartbeat | 1000 ms | | Heartbeat | 1000 ms |
| Client-Timeout (Master) | 3 × Heartbeat = 3 s → `available=false` | | Client-Timeout (Master) | 3 × Heartbeat = 3 s → `available=false` |
| Master-Verlust (Slave) | 5 s ohne Discover | | Master-Verlust (Slave) | 5 s ohne Discover |
| Accel-Stream | 10 ms (best-effort, kein ACK-Wait; = FreeRTOS-Tick) | | Accel-Stream | Poll 10 ms; TX nur bei Deadzone-Änderung (best-effort) |
| Batterie-Report | 30 s (+ einmal 150 ms nach Join) | | Batterie-Report | 30 s (+ einmal 150 ms nach Join) |
| Echo-Ping Timeout (Master) | 500 ms (`ESPNOW_ECHO_PING_TIMEOUT_MS`) | | Echo-Ping Timeout (Master) | 500 ms (`ESPNOW_ECHO_PING_TIMEOUT_MS`) |
@@ -262,7 +262,7 @@ Nur auf dem **Master** registriert (`powerpod.c`). IDs aus `MessageType` in `uar
- Optional `period_ms` (10–16): BLE-Host-Push-Intervall für `BLE_STREAM_TICK` (UART ignoriert; Default 10). - Optional `period_ms` (10–16): BLE-Host-Push-Intervall für `BLE_STREAM_TICK` (UART ignoriert; Default 10).
- Master setzt `client_registry_set_accel_stream` und sendet `ESPNOW_SET_ACCEL_STREAM`. - Master setzt `client_registry_set_accel_stream` und sendet `ESPNOW_SET_ACCEL_STREAM`.
- Slave-Task `slave_accel_stream_task` sendet `ESPNOW_ACCEL_SAMPLE` alle 10 ms (best-effort / `send_best_effort`). - Slave-Task `accel_stream_task` pollt alle 10 ms; sendet `ESPNOW_ACCEL_SAMPLE` nur wenn eine Achse die Accel-Deadzone seit dem letzten gesendeten Sample überschreitet (best-effort / `send_best_effort`; Baseline-Reset beim Stream-Enable).
### 7.5 TAP_NOTIFY (27) ### 7.5 TAP_NOTIFY (27)
@@ -371,6 +371,7 @@ Implementierung: `ota_uart.c`, Steuerung `cmd/cmd_ota.c`. Gleiches Protokoll üb
- Inaktive Partition: `esp_ota_get_next_update_partition()`. - Inaktive Partition: `esp_ota_get_next_update_partition()`.
- LED-Ring zeigt Fortschritt (blau Schreiben, grün Verteilung). - LED-Ring zeigt Fortschritt (blau Schreiben, grün Verteilung).
- BLE: ATT MTU ≥ ~219 (preferred 517); große Antworten werden über mehrere Notifies gestückelt; `BLE_STREAM_TICK` pausiert während `ota_session_busy()`. - BLE: ATT MTU ≥ ~219 (preferred 517); große Antworten werden über mehrere Notifies gestückelt; `BLE_STREAM_TICK` pausiert während `ota_session_busy()`.
- **BLE+ESP-NOW Coex:** Tag `wifi` auf `ESP_LOG_NONE` (WiFi-Task-Stack + Error-Logs → Overflow/Panic); während ESP-NOW-Dist `OTA_STATUS` DISTRIBUTING max. ~4/s und kürzere BLE-Notify-Retries.
- **App-Rollback** (`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`): neues Image bootet als `PENDING_VERIFY`. `ota_confirm` markiert nach ~8 s stabilem Lauf `mark_app_valid`; Crash/Reset davor → Bootloader rollt auf die vorherige App zurück. Während `PENDING_VERIFY` ist ein neues `OTA_START` blockiert. - **App-Rollback** (`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`): neues Image bootet als `PENDING_VERIFY`. `ota_confirm` markiert nach ~8 s stabilem Lauf `mark_app_valid`; Crash/Reset davor → Bootloader rollt auf die vorherige App zurück. Während `PENDING_VERIFY` ist ein neues `OTA_START` blockiert.
### 8.2 ESP-NOW-OTA (Master → Slaves) ### 8.2 ESP-NOW-OTA (Master → Slaves)
@@ -382,7 +383,7 @@ Implementierung: `ota_uart.c`, Steuerung `cmd/cmd_ota.c`. Gleiches Protokoll üb
3. `ESPNOW_OTA_END` → Boot-Partition setzen + automatischer Reboot 3. `ESPNOW_OTA_END` → Boot-Partition setzen + automatischer Reboot
4. Slave antwortet `ESPNOW_OTA_STATUS` (mit `send_message_ex` + Semaphore auf Master) 4. Slave antwortet `ESPNOW_OTA_STATUS` (mit `send_message_ex` + Semaphore auf Master)
Nach Erfolg: Master und Slaves starten automatisch neu (Rollback-Confirm siehe 8.1). Während Distribution: keine Client-Timeouts in der Registry (Heartbeats werden im recv_cb verworfen). Nach Erfolg: Master und Slaves starten automatisch neu (Rollback-Confirm siehe 8.1).
### 8.3 OTA_SLAVE_PROGRESS (21) ### 8.3 OTA_SLAVE_PROGRESS (21)
+12 -2
View File
@@ -3,6 +3,7 @@
#include "esp_timer.h" #include "esp_timer.h"
#include "host_transport.h" #include "host_transport.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "ota_espnow.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/task.h" #include "freertos/task.h"
@@ -26,9 +27,12 @@ static const char *DEVICE_NAME = "Powerpod";
/** Prefer large ATT MTU so CLIENT_INFO / BATTERY fit in fewer notify chunks. */ /** Prefer large ATT MTU so CLIENT_INFO / BATTERY fit in fewer notify chunks. */
#define BLE_PREFERRED_ATT_MTU 517 #define BLE_PREFERRED_ATT_MTU 517
#define BLE_NOTIFY_CHUNK_RETRIES 24 #define BLE_NOTIFY_CHUNK_RETRIES 24
/** During ESP-NOW OTA dist, fail notify sooner so WiFi/ESP-NOW keeps airtime. */
#define BLE_NOTIFY_CHUNK_RETRIES_OTA_DIST 4
#define BLE_NOTIFY_CHUNK_RETRY_MS 5 #define BLE_NOTIFY_CHUNK_RETRY_MS 5
/** Pace multi-chunk notifies so the central parser sees contiguous frame bytes. */ /** Pace multi-chunk notifies so the central parser sees contiguous frame bytes. */
#define BLE_NOTIFY_CHUNK_GAP_MS 8 #define BLE_NOTIFY_CHUNK_GAP_MS 8
#define BLE_NOTIFY_CHUNK_GAP_OTA_DIST_MS 2
/* /*
* Nordic UART style: * Nordic UART style:
@@ -73,7 +77,10 @@ uint16_t ble_host_max_payload(void) {
* One ATT notification (≤ MTU-3). Retries on transient NimBLE buffer pressure. * One ATT notification (≤ MTU-3). Retries on transient NimBLE buffer pressure.
*/ */
static esp_err_t ble_notify_chunk(const uint8_t *data, uint16_t len) { static esp_err_t ble_notify_chunk(const uint8_t *data, uint16_t len) {
for (int attempt = 0; attempt < BLE_NOTIFY_CHUNK_RETRIES; attempt++) { const int max_retries = ota_espnow_distribution_active()
? BLE_NOTIFY_CHUNK_RETRIES_OTA_DIST
: BLE_NOTIFY_CHUNK_RETRIES;
for (int attempt = 0; attempt < max_retries; attempt++) {
struct os_mbuf *om = ble_hs_mbuf_from_flat(data, len); struct os_mbuf *om = ble_hs_mbuf_from_flat(data, len);
if (om == NULL) { if (om == NULL) {
vTaskDelay(pdMS_TO_TICKS(BLE_NOTIFY_CHUNK_RETRY_MS)); vTaskDelay(pdMS_TO_TICKS(BLE_NOTIFY_CHUNK_RETRY_MS));
@@ -140,7 +147,10 @@ static esp_err_t ble_host_tx(const uint8_t *frame, size_t frame_len) {
} }
off += n; off += n;
if (off < frame_len) { if (off < frame_len) {
vTaskDelay(pdMS_TO_TICKS(BLE_NOTIFY_CHUNK_GAP_MS)); const uint32_t gap_ms = ota_espnow_distribution_active()
? BLE_NOTIFY_CHUNK_GAP_OTA_DIST_MS
: BLE_NOTIFY_CHUNK_GAP_MS;
vTaskDelay(pdMS_TO_TICKS(gap_ms));
} }
} }
+23 -1
View File
@@ -2,7 +2,7 @@
* BMA456H integration for Powerpod (ESP-IDF I2C master + Bosch SensorAPI). * BMA456H integration for Powerpod (ESP-IDF I2C master + Bosch SensorAPI).
* *
* Polls accelerometer at 10 Hz; tap events arrive on BMA456_INT_GPIO. * Polls accelerometer at 10 Hz; tap events arrive on BMA456_INT_GPIO.
* Accel logging is filtered in software (deadzone); slaves stream samples via ESP-NOW. * Accel log + ESP-NOW stream share a software deadzone filter (emit on change).
*/ */
#include "bosch456.h" #include "bosch456.h"
@@ -33,6 +33,10 @@ static int16_t s_last_x;
static int16_t s_last_y; static int16_t s_last_y;
static int16_t s_last_z; static int16_t s_last_z;
static bool s_have_last_sample; static bool s_have_last_sample;
static int16_t s_stream_last_x;
static int16_t s_stream_last_y;
static int16_t s_stream_last_z;
static bool s_stream_have_last;
static volatile bool s_int_pending; static volatile bool s_int_pending;
static SemaphoreHandle_t s_accel_mutex; static SemaphoreHandle_t s_accel_mutex;
@@ -119,6 +123,7 @@ bool bma456_is_ready(void) { return s_bma456_ready; }
void bma456_set_accel_deadzone(uint32_t deadzone_lsb) { void bma456_set_accel_deadzone(uint32_t deadzone_lsb) {
s_accel_deadzone = deadzone_lsb; s_accel_deadzone = deadzone_lsb;
s_have_last_sample = false; s_have_last_sample = false;
s_stream_have_last = false;
if (s_bma456_ready) { if (s_bma456_ready) {
ESP_LOGI(TAG, "accel deadzone %lu LSB", (unsigned long)deadzone_lsb); ESP_LOGI(TAG, "accel deadzone %lu LSB", (unsigned long)deadzone_lsb);
} }
@@ -126,6 +131,23 @@ void bma456_set_accel_deadzone(uint32_t deadzone_lsb) {
uint32_t bma456_get_accel_deadzone(void) { return s_accel_deadzone; } uint32_t bma456_get_accel_deadzone(void) { return s_accel_deadzone; }
void bma456_accel_stream_reset_baseline(void) { s_stream_have_last = false; }
bool bma456_accel_stream_take_if_changed(int16_t x, int16_t y, int16_t z) {
if (s_stream_have_last) {
if (axis_delta(x, s_stream_last_x) <= (int16_t)s_accel_deadzone &&
axis_delta(y, s_stream_last_y) <= (int16_t)s_accel_deadzone &&
axis_delta(z, s_stream_last_z) <= (int16_t)s_accel_deadzone) {
return false;
}
}
s_stream_last_x = x;
s_stream_last_y = y;
s_stream_last_z = z;
s_stream_have_last = true;
return true;
}
bool bma456_tap_config_valid(const bma456_tap_config_t *cfg) { bool bma456_tap_config_valid(const bma456_tap_config_t *cfg) {
if (cfg == NULL) { if (cfg == NULL) {
return false; return false;
+11 -1
View File
@@ -19,7 +19,7 @@
/** Sensor interrupt line → ESP32 GPIO (active high, rising edge). */ /** Sensor interrupt line → ESP32 GPIO (active high, rising edge). */
#define BMA456_INT_GPIO 10 #define BMA456_INT_GPIO 10
/** Software filter: log accel only when |axis - last| > deadzone (raw LSB). */ /** Software filter: emit accel only when |axis - last| > deadzone (raw LSB). */
#define BMA456_DEFAULT_ACCEL_DEADZONE 100u #define BMA456_DEFAULT_ACCEL_DEADZONE 100u
/** /**
@@ -81,6 +81,16 @@ bool bma456_is_ready(void);
void bma456_set_accel_deadzone(uint32_t deadzone_lsb); void bma456_set_accel_deadzone(uint32_t deadzone_lsb);
uint32_t bma456_get_accel_deadzone(void); uint32_t bma456_get_accel_deadzone(void);
/**
* ESP-NOW stream filter: true if sample exceeds deadzone vs last streamed
* sample (or no baseline yet). On true, commits (x,y,z) as stream baseline.
* Independent of the log filter baseline.
*/
bool bma456_accel_stream_take_if_changed(int16_t x, int16_t y, int16_t z);
/** Force next stream take to accept (call when accel stream is enabled). */
void bma456_accel_stream_reset_baseline(void);
/** Log accel when any axis moved more than deadzone since last reported sample. */ /** Log accel when any axis moved more than deadzone since last reported sample. */
void bma456_report_accel_if_changed(int16_t x, int16_t y, int16_t z); void bma456_report_accel_if_changed(int16_t x, int16_t y, int16_t z);
+36 -1
View File
@@ -5,8 +5,10 @@
#include "pod_reboot.h" #include "pod_reboot.h"
#include "uart_cmd.h" #include "uart_cmd.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h" #include "freertos/idf_additions.h"
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -32,6 +34,14 @@ typedef struct {
uint32_t written; uint32_t written;
int slot; int slot;
} ota_dist_job_t; } ota_dist_job_t;
/** Cap host DISTRIBUTING pushes (BLE notifies compete with ESP-NOW OTA TX). */
#define OTA_DIST_NOTIFY_MIN_US (250 * 1000ull)
static int64_t s_last_dist_agg_us;
static int64_t s_last_dist_slave_us;
static uint32_t s_last_dist_agg_bytes = UINT32_MAX;
static void send_ota_status(ota_uart_status_t status, uint32_t err_code) { static void send_ota_status(ota_uart_status_t status, uint32_t err_code) {
alox_UartMessage response; alox_UartMessage response;
uart_cmd_init_response(&response, alox_MessageType_OTA_STATUS, uart_cmd_init_response(&response, alox_MessageType_OTA_STATUS,
@@ -64,15 +74,33 @@ static void send_ota_distributing(uint32_t kind, uint32_t bytes_done,
static void ota_dist_aggregate(uint32_t bytes_done, uint32_t total_bytes, static void ota_dist_aggregate(uint32_t bytes_done, uint32_t total_bytes,
uint8_t slave_count) { uint8_t slave_count) {
(void)slave_count;
led_ring_show_ota_progress(bytes_done, total_bytes, OTA_LED_ESPNOW_TX_R, led_ring_show_ota_progress(bytes_done, total_bytes, OTA_LED_ESPNOW_TX_R,
OTA_LED_ESPNOW_TX_G, OTA_LED_ESPNOW_TX_B); OTA_LED_ESPNOW_TX_G, OTA_LED_ESPNOW_TX_B);
const int64_t now = esp_timer_get_time();
const bool first = (s_last_dist_agg_bytes == UINT32_MAX);
const bool boundary =
(bytes_done == 0) || (total_bytes > 0 && bytes_done >= total_bytes);
const bool paced =
(now - s_last_dist_agg_us) >= (int64_t)OTA_DIST_NOTIFY_MIN_US;
if (!first && !boundary && !paced) {
return;
}
s_last_dist_agg_us = now;
s_last_dist_agg_bytes = bytes_done;
send_ota_distributing(OTA_DIST_AGGREGATE, bytes_done, (uint32_t)slave_count); send_ota_distributing(OTA_DIST_AGGREGATE, bytes_done, (uint32_t)slave_count);
} }
static void ota_dist_per_slave(uint32_t slave_id, uint32_t bytes_done, static void ota_dist_per_slave(uint32_t slave_id, uint32_t bytes_done,
uint32_t total_bytes) { uint32_t total_bytes) {
(void)total_bytes; (void)total_bytes;
/* Host also polls OTA_SLAVE_PROGRESS; keep per-slave pushes rare on BLE. */
const int64_t now = esp_timer_get_time();
if ((now - s_last_dist_slave_us) < (int64_t)OTA_DIST_NOTIFY_MIN_US &&
bytes_done > 0) {
return;
}
s_last_dist_slave_us = now;
send_ota_distributing(OTA_DIST_PER_SLAVE, bytes_done, slave_id); send_ota_distributing(OTA_DIST_PER_SLAVE, bytes_done, slave_id);
} }
@@ -225,6 +253,9 @@ static void ota_distribute_task(void *param) {
led_ring_show_ota_progress(0, image_size, OTA_LED_ESPNOW_TX_R, OTA_LED_ESPNOW_TX_G, led_ring_show_ota_progress(0, image_size, OTA_LED_ESPNOW_TX_R, OTA_LED_ESPNOW_TX_G,
OTA_LED_ESPNOW_TX_B); OTA_LED_ESPNOW_TX_B);
s_last_dist_agg_us = 0;
s_last_dist_slave_us = 0;
s_last_dist_agg_bytes = UINT32_MAX;
send_ota_distributing(OTA_DIST_AGGREGATE, 0, 0); send_ota_distributing(OTA_DIST_AGGREGATE, 0, 0);
esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress); esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress);
@@ -315,6 +346,10 @@ static void ota_start_espnow_task(void *param) {
return; return;
} }
s_last_dist_agg_us = 0;
s_last_dist_slave_us = 0;
s_last_dist_agg_bytes = UINT32_MAX;
esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress); esp_err_t err = ota_espnow_distribute(part, image_size, &s_dist_progress);
if (err != ESP_OK) { if (err != ESP_OK) {
send_ota_failed(42); send_ota_failed(42);
+8
View File
@@ -280,6 +280,14 @@ esp_err_t esp_now_core_init_radio(uint8_t channel) {
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
ESP_ERROR_CHECK(esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE)); ESP_ERROR_CHECK(esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE));
/* WiFi task stack is tiny; ERROR logs from pp/coex (e.g. under BLE+ESP-NOW
* OTA) call esp_log_write on that stack and can overflow → panic reboot.
* Mute after esp_wifi_init (which resets the wifi tag to default level). */
esp_log_level_set("wifi", ESP_LOG_NONE);
esp_log_level_set("wifi_init", ESP_LOG_WARN);
esp_log_level_set("coex", ESP_LOG_WARN);
esp_log_level_set("NimBLE", ESP_LOG_WARN);
ESP_ERROR_CHECK(esp_read_mac(s_own_mac, ESP_MAC_WIFI_STA)); ESP_ERROR_CHECK(esp_read_mac(s_own_mac, ESP_MAC_WIFI_STA));
s_wifi_channel = channel; s_wifi_channel = channel;
return ESP_OK; return ESP_OK;
+5 -1
View File
@@ -780,7 +780,11 @@ static void monitor_task(void *param) {
while (1) { while (1) {
vTaskDelay(pdMS_TO_TICKS(ESPNOW_HEARTBEAT_INTERVAL_MS)); vTaskDelay(pdMS_TO_TICKS(ESPNOW_HEARTBEAT_INTERVAL_MS));
client_registry_check_timeouts(ESPNOW_CLIENT_TIMEOUT_MS); /* During ESP-NOW OTA dist the recv_cb drops heartbeats; do not wipe
* targets from the registry while they are still being updated. */
if (!ota_espnow_distribution_active()) {
client_registry_check_timeouts(ESPNOW_CLIENT_TIMEOUT_MS);
}
uint32_t t = esp_now_core_now_ms(); uint32_t t = esp_now_core_now_ms();
if (t - last_local_battery_ms >= ESPNOW_BATTERY_INTERVAL_MS) { if (t - last_local_battery_ms >= ESPNOW_BATTERY_INTERVAL_MS) {
+10 -2
View File
@@ -26,7 +26,8 @@
/** While master or slave OTA is in progress (discover may be sparse). */ /** While master or slave OTA is in progress (discover may be sparse). */
#define SLAVE_MASTER_OTA_GRACE_MS 300000u #define SLAVE_MASTER_OTA_GRACE_MS 300000u
/** /**
* Accel stream cadence (10 ms frame). TX path is selectable (INPUT_SEND_MODE). * Accel stream poll cadence (10 ms frame). TX only when sample exceeds the
* BMA456 deadzone vs last sent sample. TX path is selectable (INPUT_SEND_MODE).
* With master Discover.master_time_us, slaves phase into 1 ms slots: * With master Discover.master_time_us, slaves phase into 1 ms slots:
* offset_ms = (assigned_id - 1) % 8. Slot wait uses esp_timer (FreeRTOS tick * offset_ms = (assigned_id - 1) % 8. Slot wait uses esp_timer (FreeRTOS tick
* is 10 ms — too coarse for intra-frame offsets). * is 10 ms — too coarse for intra-frame offsets).
@@ -516,6 +517,9 @@ static void handle_accel_stream(const uint8_t *master_mac,
return; return;
} }
s_accel_stream_enabled = cfg->enable; s_accel_stream_enabled = cfg->enable;
if (cfg->enable) {
bma456_accel_stream_reset_baseline();
}
char mac_str[18]; char mac_str[18];
esp_now_core_mac_to_str(master_mac, mac_str, sizeof(mac_str)); esp_now_core_mac_to_str(master_mac, mac_str, sizeof(mac_str));
ESP_LOGI(TAG, "accel stream %s from master %s (id=%lu)", ESP_LOGI(TAG, "accel stream %s from master %s (id=%lu)",
@@ -743,7 +747,8 @@ static void accel_stream_task(void *param) {
(void)param; (void)param;
ESP_LOGI(TAG, ESP_LOGI(TAG,
"accel stream task (interval %u ms, %u×%llu us slots, mode selectable)", "accel stream task (poll %u ms, deadzone TX, %u×%llu us slots, "
"mode selectable)",
(unsigned)ESPNOW_ACCEL_INTERVAL_MS, (unsigned)ESPNOW_ACCEL_SLOT_COUNT, (unsigned)ESPNOW_ACCEL_INTERVAL_MS, (unsigned)ESPNOW_ACCEL_SLOT_COUNT,
(unsigned long long)ESPNOW_ACCEL_SLOT_US); (unsigned long long)ESPNOW_ACCEL_SLOT_US);
@@ -759,6 +764,9 @@ static void accel_stream_task(void *param) {
if (bma456_read_accel(&x, &y, &z) != ESP_OK) { if (bma456_read_accel(&x, &y, &z) != ESP_OK) {
continue; continue;
} }
if (!bma456_accel_stream_take_if_changed(x, y, z)) {
continue;
}
(void)send_accel_sample(s_master_mac, s_assigned_id, x, y, z); (void)send_accel_sample(s_master_mac, s_assigned_id, x, y, z);
} }
} }