firmware: v5 — watchdog motores + fix stream buffering

- Watchdog FreeRTOS: si no llega comando F/B/L/R en 400ms envia S
  automaticamente. Evita que el coche siga recto cuando se pierde
  el comando de parada por latencia del proxy HTTPS.
- X-Accel-Buffering: no en stream_handler: desactiva buffering en
  nginx/Synology. Elimina los microcortes del video MJPEG.
- Cache-Control: no-cache en el stream.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Natxo1000
2026-06-02 12:44:33 +02:00
parent 3cded388b1
commit e634138924
4 changed files with 33 additions and 6 deletions

View File

@@ -10,7 +10,7 @@
// ================================================================
// OTA CONFIG
// ================================================================
#define FW_VERSION 4
#define FW_VERSION 5
#define GITEA_HOST "https://git.nacho.myds.me"
#define GITEA_OWNER "Natxo"
#define GITEA_REPO "Arduino-Car"

View File

@@ -48,6 +48,22 @@ static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %
httpd_handle_t stream_httpd = NULL;
httpd_handle_t camera_httpd = NULL;
// ── Watchdog de motores ────────────────────────────────────────────
// Si no llega ningún comando de movimiento en 400ms → para automáticamente
static volatile bool motorMoving = false;
static volatile int64_t lastMoveCmdUs = 0;
#define WATCHDOG_US 400000LL
static void motorWatchdogTask(void *) {
while (1) {
if (motorMoving && (esp_timer_get_time() - lastMoveCmdUs) > WATCHDOG_US) {
Serial.print("S\n");
motorMoving = false;
}
vTaskDelay(pdMS_TO_TICKS(80));
}
}
typedef struct {
size_t size; //number of values used for filtering
size_t index; //current value index
@@ -226,6 +242,8 @@ static esp_err_t stream_handler(httpd_req_t *req) {
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_hdr(req, "X-Framerate", "60");
httpd_resp_set_hdr(req, "X-Accel-Buffering", "no"); // desactiva buffering en nginx/Synology
httpd_resp_set_hdr(req, "Cache-Control", "no-cache, no-store");
#if defined(LED_GPIO_NUM)
isStreaming = true;
@@ -350,14 +368,21 @@ static esp_err_t cmd_handler(httpd_req_t *req) {
}
else {
// Lo demás se manda al otro micro por UART
// si es número
if (isdigit(value[0])) {
Serial.printf("%d\n", val);
}
// si es texto
else {
} else {
Serial.printf("%s\n", value);
}
// Watchdog: registra comandos de movimiento
if (!strcmp(variable, "car")) {
char c = value[0];
if (c=='F' || c=='B' || c=='L' || c=='R') {
motorMoving = true;
lastMoveCmdUs = esp_timer_get_time();
} else if (c == 'S') {
motorMoving = false;
}
}
}
if (res < 0) {
@@ -785,6 +810,8 @@ void startCameraServer() {
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
}
xTaskCreate(motorWatchdogTask, "motorWD", 2048, NULL, 1, NULL);
}
void setupLedFlash() {

Binary file not shown.

View File

@@ -1 +1 @@
4
5