move nvs init around, more graceful bt/wifi bringup/down, led indicatorrs
This commit is contained in:
@@ -60,7 +60,8 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define TAG "BT_HID"
|
||||
#define BT_HID_SCAN_DURATION_S 3 /* ceiling only — scan stops early on first HID hit */
|
||||
#define BT_HID_SCAN_DURATION_S 3
|
||||
#define BT_HID_MIN_RSSI (-70) /* dBm — ignore devices weaker than this */
|
||||
#define BT_HID_RECONNECT_MS 2000
|
||||
#define BT_HID_BOND_TIMEOUT_MS 5000 /* wait for saved device before scanning */
|
||||
#define BT_HID_CONNECT_WAIT_MS 5000 /* wait after open() before next loop */
|
||||
@@ -245,6 +246,9 @@ static void hidh_callback(void *handler_args,
|
||||
nvs_save_bda(bda, s_connect_addr_type);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "OPEN failed, status=%d", p->open.status);
|
||||
/* Free the failed device handle — not doing so leaks a BT
|
||||
* resource and can block future connection attempts. */
|
||||
esp_hidh_dev_free(p->open.dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -342,6 +346,15 @@ static void ble_gap_event_handler(esp_gap_ble_cb_event_t event,
|
||||
memcpy(name, name_d, copy);
|
||||
}
|
||||
|
||||
if (param->scan_rst.rssi < BT_HID_MIN_RSSI) {
|
||||
ESP_LOGD(TAG, "SCAN %02x:%02x:%02x:%02x:%02x:%02x RSSI:%d '%s' (too weak, skipping)",
|
||||
param->scan_rst.bda[0], param->scan_rst.bda[1],
|
||||
param->scan_rst.bda[2], param->scan_rst.bda[3],
|
||||
param->scan_rst.bda[4], param->scan_rst.bda[5],
|
||||
param->scan_rst.rssi, name);
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "SCAN %02x:%02x:%02x:%02x:%02x:%02x RSSI:%d '%s' <<< HID",
|
||||
param->scan_rst.bda[0], param->scan_rst.bda[1],
|
||||
param->scan_rst.bda[2], param->scan_rst.bda[3],
|
||||
@@ -352,9 +365,6 @@ static void ble_gap_event_handler(esp_gap_ble_cb_event_t event,
|
||||
param->scan_rst.ble_addr_type,
|
||||
name,
|
||||
param->scan_rst.rssi);
|
||||
|
||||
/* Stop scanning immediately — we have what we need. */
|
||||
esp_ble_gap_stop_scanning();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
42
main/main.c
42
main/main.c
@@ -229,6 +229,28 @@ void app_main(void) {esp_task_wdt_add(NULL);
|
||||
while(true) {
|
||||
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
||||
|
||||
/* In soft idle: slow poll (5s) via direct GPIO, no I2C. */
|
||||
if (soft_idle_is_active()) {
|
||||
//vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
if (soft_idle_button_raw()) {
|
||||
rtc_reset_shutdown_timer();
|
||||
soft_idle_exit();
|
||||
i2c_poll_buttons(); /* sync TCA9555 state after idle */
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
}
|
||||
if (rtc_alarm_tripped()) {
|
||||
soft_idle_exit();
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
fsm_request(FSM_CMD_START);
|
||||
rtc_schedule_next_alarm();
|
||||
}
|
||||
solar_run_fsm();
|
||||
rtc_check_shutdown_timer();
|
||||
esp_task_wdt_reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
i2c_poll_buttons();
|
||||
|
||||
if (i2c_get_button_state(0)) {
|
||||
@@ -248,22 +270,22 @@ void app_main(void) {esp_task_wdt_add(NULL);
|
||||
} else if (i2c_get_button_ms(0) > 100){
|
||||
drive_leds(LED_STATE_START1);
|
||||
} else {
|
||||
/*if (
|
||||
if (
|
||||
rtc_is_set() &&
|
||||
!efuse_is_tripped(BRIDGE_JACK) &&
|
||||
!efuse_is_tripped(BRIDGE_AUX) &&
|
||||
!efuse_is_tripped(BRIDGE_DRIVE) &&
|
||||
efuse_get(BRIDGE_JACK)==EFUSE_OK &&
|
||||
efuse_get(BRIDGE_AUX)==EFUSE_OK &&
|
||||
efuse_get(BRIDGE_DRIVE)==EFUSE_OK &&
|
||||
fsm_get_error() == ESP_OK
|
||||
) {
|
||||
drive_leds(LED_STATE_AWAKE);
|
||||
} else {
|
||||
drive_leds(LED_STATE_ERROR);
|
||||
}*/
|
||||
}
|
||||
|
||||
int8_t state = 0b001;
|
||||
/*int8_t state = 0b001;
|
||||
if (get_is_safe()) state |= 0b010;
|
||||
if (get_sensor(SENSOR_SAFETY)) state |= 0b100;
|
||||
i2c_set_led1(state);
|
||||
i2c_set_led1(state);*/
|
||||
}
|
||||
|
||||
// when not actively moving we log at a low frequency (every 120s)
|
||||
@@ -321,12 +343,6 @@ void app_main(void) {esp_task_wdt_add(NULL);
|
||||
|
||||
|
||||
if (rtc_alarm_tripped()) {
|
||||
bool was_idle = soft_idle_is_active();
|
||||
soft_idle_exit();
|
||||
if (was_idle) {
|
||||
// Give WiFi softAP time to come up before movement begins
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
fsm_request(FSM_CMD_START);
|
||||
rtc_schedule_next_alarm();
|
||||
}
|
||||
|
||||
@@ -63,7 +63,11 @@ static void rf_433_receiver_task(void* param) {
|
||||
rmt_rx_done_event_data_t rx_data;
|
||||
|
||||
rmt_receive_config_t rx_config = {
|
||||
.signal_range_min_ns = 2000,
|
||||
/* Hardware filter max on ESP32 is ~3187 ns (8-bit APB counter).
|
||||
* Filters sub-3µs glitches; can't filter longer noise pulses in HW.
|
||||
* Buffer overflow from other 433 MHz devices is benign — the decoder
|
||||
* only reads the first 24 symbols regardless of total length. */
|
||||
.signal_range_min_ns = 3000,
|
||||
.signal_range_max_ns = 1250000,
|
||||
};
|
||||
|
||||
@@ -71,7 +75,7 @@ static void rf_433_receiver_task(void* param) {
|
||||
.gpio_num = (gpio_num_t)RF_PIN,
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = 1000000,
|
||||
.mem_block_symbols = 64,
|
||||
.mem_block_symbols = 64, /* ESP32 non-DMA RMT: 1 block = 64 symbols max */
|
||||
.flags = {
|
||||
.invert_in = false,
|
||||
.with_dma = false,
|
||||
|
||||
@@ -85,6 +85,7 @@ void soft_idle_enter(void)
|
||||
}
|
||||
|
||||
bool soft_idle_is_active(void) { return in_soft_idle; }
|
||||
bool soft_idle_button_raw(void) { return gpio_get_level(PIN_BTN_INTERRUPT) == 0; }
|
||||
|
||||
void soft_idle_exit(void)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ void rtc_reset_shutdown_timer(); // reset shutoff timer
|
||||
void soft_idle_enter(void);
|
||||
void soft_idle_exit(void);
|
||||
bool soft_idle_is_active(void);
|
||||
bool soft_idle_button_raw(void); /* direct GPIO read, no I2C */
|
||||
esp_sleep_wakeup_cause_t rtc_wakeup_cause();
|
||||
|
||||
/*void adjust_rtc_hour(char *key, int8_t dir);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "storage.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "version.h"
|
||||
|
||||
#define TAG "STORAGE"
|
||||
@@ -424,7 +425,17 @@ esp_err_t factory_reset(void) {
|
||||
esp_err_t storage_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing storage system...");
|
||||
|
||||
|
||||
// NVS must be initialized before WiFi and BT
|
||||
esp_err_t nvs_err = nvs_flash_init();
|
||||
if (nvs_err == ESP_ERR_NVS_NO_FREE_PAGES || nvs_err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_LOGW(TAG, "NVS partition needs erasing, performing erase...");
|
||||
nvs_err = nvs_flash_erase();
|
||||
if (nvs_err == ESP_OK) nvs_err = nvs_flash_init();
|
||||
}
|
||||
if (nvs_err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "nvs_flash_init failed: %s", esp_err_to_name(nvs_err));
|
||||
return nvs_err;
|
||||
}
|
||||
|
||||
log_mutex = xSemaphoreCreateMutex();
|
||||
if (log_mutex == NULL) {
|
||||
|
||||
@@ -432,6 +432,9 @@ static esp_err_t get_handler(httpd_req_t *req) {
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
static void soft_idle_enter_cb(void *arg) { soft_idle_enter(); }
|
||||
static void webserver_restart_wifi_cb(void *arg) { webserver_restart_wifi(); }
|
||||
|
||||
/**
|
||||
* Unified POST handler - handles commands, parameter updates, time updates
|
||||
*/
|
||||
@@ -523,15 +526,39 @@ static esp_err_t post_handler(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
if (should_restart_wifi) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500)); // Let the TCP response flush
|
||||
webserver_restart_wifi();
|
||||
/* Same deadlock risk as should_sleep — httpd_stop() inside
|
||||
* webserver_restart_wifi() cannot be called from within a handler. */
|
||||
static esp_timer_handle_t s_wifi_restart_timer = NULL;
|
||||
if (s_wifi_restart_timer == NULL) {
|
||||
esp_timer_create_args_t ta = {
|
||||
.callback = webserver_restart_wifi_cb,
|
||||
.name = "wifi_restart",
|
||||
};
|
||||
esp_timer_create(&ta, &s_wifi_restart_timer);
|
||||
}
|
||||
if (s_wifi_restart_timer != NULL) {
|
||||
esp_timer_start_once(s_wifi_restart_timer, 500 * 1000); /* 500 ms in µs */
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (should_sleep) {
|
||||
ESP_LOGI(TAG, "Entering soft idle in 2 seconds...");
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
soft_idle_enter();
|
||||
/* Cannot call soft_idle_enter() (→ httpd_stop()) from within an httpd
|
||||
* handler — httpd_stop() waits for all handlers to finish, causing a
|
||||
* deadlock. Schedule via a one-shot timer so this handler returns
|
||||
* first and the httpd task is free. */
|
||||
static esp_timer_handle_t s_sleep_timer = NULL;
|
||||
if (s_sleep_timer == NULL) {
|
||||
esp_timer_create_args_t ta = {
|
||||
.callback = soft_idle_enter_cb,
|
||||
.name = "soft_idle",
|
||||
};
|
||||
esp_timer_create(&ta, &s_sleep_timer);
|
||||
}
|
||||
if (s_sleep_timer != NULL) {
|
||||
esp_timer_start_once(s_sleep_timer, 2000 * 1000); /* 2 s in µs */
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -881,29 +908,8 @@ static esp_err_t launch_soft_ap(void) {
|
||||
|
||||
ESP_LOGI(TAG, "AP LAUNCHING");
|
||||
|
||||
err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
// NVS partition was truncated and needs to be erased
|
||||
ESP_LOGW(TAG, "NVS partition needs erasing, performing erase...");
|
||||
err = nvs_flash_erase();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase NVS: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
// Retry init after erase
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "AP LAUNCHING...");
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize NVS: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "HI THERE");
|
||||
|
||||
err = esp_netif_init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize netif: %s", esp_err_to_name(err));
|
||||
|
||||
Reference in New Issue
Block a user