diff --git a/ESP8266/ESP8266.ino b/ESP8266/ESP8266.ino index 01a22ed..64d199e 100644 --- a/ESP8266/ESP8266.ino +++ b/ESP8266/ESP8266.ino @@ -1,22 +1,6 @@ +// FW_VERSION solo informativo — este ESP8266 no hace OTA +#define FW_VERSION 19 #include -#include -#include -#include -#include - -// ================================================================ -// OTA CONFIG -// ================================================================ -#define FW_VERSION 19 -#define GITEA_HOST "https://git.nacho.myds.me" -#define GITEA_OWNER "Natxo" -#define GITEA_REPO "Arduino-Car" -#define GITEA_BRANCH "main" -#define GITEA_TOKEN "d3b0b32eb0311c9b4ef569f22c8392c373ff3f9f" -// WiFi — mismas credenciales que usa el ESP32-CAM -#define WIFI_SSID "Natxo" -#define WIFI_PASS "Suprak1llm1ndS23S" -// ================================================================ // ==== Pines motores ==== const int ENA = D1; @@ -30,7 +14,7 @@ const int IN4 = D0; const int SERVO_X_PIN = D3; const int SERVO_Y_PIN = D4; -// ==== Pines buzzer ==== +// ==== Pin buzzer ==== const int buzzerPin = D8; Servo servoX; @@ -40,81 +24,14 @@ int currentSpeed = 150; int posX = 90; int posY = 90; -// ── OTA: comprueba si hay firmware nuevo y actualiza si hace falta ── -static void checkOTA() { - WiFi.mode(WIFI_STA); - WiFi.begin(WIFI_SSID, WIFI_PASS); - - int tries = 0; - while (WiFi.status() != WL_CONNECTED && tries < 20) { - delay(500); - tries++; - } - - if (WiFi.status() != WL_CONNECTED) { - WiFi.disconnect(); - WiFi.mode(WIFI_OFF); - return; // sin WiFi, arranque normal - } - - String base = String(GITEA_HOST) + "/" + GITEA_OWNER + "/" + GITEA_REPO - + "/raw/branch/" + GITEA_BRANCH + "/firmware/esp8266/"; - String token = "?token=" + String(GITEA_TOKEN); - - // ── Bloque de scope: libera el cliente BearSSL antes de la descarga ── - // BearSSL ocupa ~20KB de heap. Si los dos clientes coexisten el heap - // se agota y ESPhttpUpdate falla silenciosamente. - // Scope block: destruye el cliente BearSSL antes de crear el de descarga - // Libera ~20KB de heap (BearSSL con buffers por defecto) para la descarga - int remoteVer = 0; - { - BearSSL::WiFiClientSecure client; - client.setInsecure(); - HTTPClient http; - http.begin(client, base + "version.txt" + token); - http.setTimeout(10000); - int code = http.GET(); - if (code == HTTP_CODE_OK) { - String body = http.getString(); - body.trim(); - remoteVer = body.toInt(); - } - http.end(); - } // client destruido aquí — heap recuperado - - if (remoteVer > FW_VERSION) { - // 4 pitidos = ESP8266 actualizando - pinMode(buzzerPin, OUTPUT); - for (int i = 0; i < 4; i++) { - digitalWrite(buzzerPin, HIGH); - delay(150); - digitalWrite(buzzerPin, LOW); - delay(150); - } - delay(300); - - // Fuerza pines de motor a LOW antes del flash para minimizar glitch de GPIO - analogWrite(ENA, 0); analogWrite(ENB, 0); - digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); - digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); - - BearSSL::WiFiClientSecure updateClient; - updateClient.setInsecure(); - ESPhttpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - ESPhttpUpdate.rebootOnUpdate(true); - ESPhttpUpdate.update(updateClient, base + "firmware.bin" + token); - // Si llega aquí, el update falló — continúa arranque normal - } - - WiFi.disconnect(); - WiFi.mode(WIFI_OFF); // apaga radio para ahorrar energía -} - +// ── Handshake: espera "GO\n" del ESP32-CAM antes de procesar comandos ── +// Descarta la basura del bootloader ROM del ESP32 (115200 baud a 9600). bool espReady = false; void waitForReady() { delay(300); - while (Serial.available()) Serial.read(); + while (Serial.available()) Serial.read(); // descarta basura del bootloader + unsigned long timeout = millis() + 90000UL; String buf = ""; while (millis() < timeout) { @@ -127,7 +44,7 @@ void waitForReady() { delay(50); while (Serial.available()) Serial.read(); espReady = true; - // 2 pitidos: conexión entre placas lista + // 2 pitidos: conexión entre placas establecida for (int i = 0; i < 2; i++) { digitalWrite(buzzerPin, HIGH); delay(180); digitalWrite(buzzerPin, LOW); delay(180); @@ -145,19 +62,16 @@ void waitForReady() { } void setup() { - // 1. Pines y parada inmediata + // 1. Pines de motor y parada inmediata pinMode(ENA, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); stopMotors(); - // 2. Serial temprano (el ESP32 puede mandar el pitido de OTA) + // 2. Serial Serial.begin(9600); - // 3. OTA via WiFi - checkOTA(); - - // 4. Resto de periféricos + // 3. Periféricos analogWriteRange(255); analogWriteFreq(1000); servoX.attach(SERVO_X_PIN); @@ -166,85 +80,71 @@ void setup() { servoX.write(posX); servoY.write(posY); - // 5. Esperar "GO\n" del ESP32-CAM antes de procesar comandos + // 4. Esperar señal del ESP32-CAM waitForReady(); } -// Watchdog ligero en ESP8266: si no llega comando de movimiento en 1.5s → para -// Evita que el coche siga moviéndose si el ESP32 se cuelga o reinicia +// Watchdog: si no llega comando de movimiento en 1.5s → para motores unsigned long lastMoveMs = 0; bool motorRunning = false; void loop() { - // Watchdog: sin comandos durante 1.5s → para motores if (motorRunning && (millis() - lastMoveMs > 1500)) { stopMotors(); motorRunning = false; } - if (Serial.available()) { - char c = Serial.read(); + if (!Serial.available()) return; + char c = Serial.read(); - // Ignorar todo hasta que el handshake esté completo - if (!espReady) return; + if (!espReady) return; - if (c == 'F') { forward(); lastMoveMs = millis(); motorRunning = true; } - else if (c == 'B') { backward(); lastMoveMs = millis(); motorRunning = true; } - else if (c == 'L') { left(); lastMoveMs = millis(); motorRunning = true; } - else if (c == 'R') { right(); lastMoveMs = millis(); motorRunning = true; } - else if (c == 'S') { stopMotors(); motorRunning = false; } - - else if (c == 'V') { - int val = Serial.parseInt(); - if (val >= 0 && val <= 255) currentSpeed = val; - } - else if (c == 'X') { - int val = Serial.parseInt(); - if (val >= 0 && val <= 180) { posX = val; servoX.write(posX); } - } - else if (c == 'Y') { - int val = Serial.parseInt(); - if (val >= 0 && val <= 180) { posY = val; servoY.write(posY); } - } - else if (c == 'H') { - int val = Serial.parseInt(); - digitalWrite(buzzerPin, val > 0 ? HIGH : LOW); - } + if (c == 'F') { forward(); lastMoveMs = millis(); motorRunning = true; } + else if (c == 'B') { backward(); lastMoveMs = millis(); motorRunning = true; } + else if (c == 'L') { left(); lastMoveMs = millis(); motorRunning = true; } + else if (c == 'R') { right(); lastMoveMs = millis(); motorRunning = true; } + else if (c == 'S') { stopMotors(); motorRunning = false; } + else if (c == 'V') { + int val = Serial.parseInt(); + if (val >= 0 && val <= 255) currentSpeed = val; + } + else if (c == 'X') { + int val = Serial.parseInt(); + if (val >= 0 && val <= 180) { posX = val; servoX.write(posX); } + } + else if (c == 'Y') { + int val = Serial.parseInt(); + if (val >= 0 && val <= 180) { posY = val; servoY.write(posY); } + } + else if (c == 'H') { + int val = Serial.parseInt(); + digitalWrite(buzzerPin, val > 0 ? HIGH : LOW); } } // ==== Funciones de movimiento ==== void forward() { - analogWrite(ENA, currentSpeed); - analogWrite(ENB, currentSpeed); + analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed); digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); } - void backward() { - analogWrite(ENA, currentSpeed); - analogWrite(ENB, currentSpeed); + analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed); digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); } - void left() { - analogWrite(ENA, currentSpeed); - analogWrite(ENB, currentSpeed); + analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed); digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); } - void right() { - analogWrite(ENA, currentSpeed); - analogWrite(ENB, currentSpeed); + analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed); digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); } - void stopMotors() { - analogWrite(ENA, 0); - analogWrite(ENB, 0); + analogWrite(ENA, 0); analogWrite(ENB, 0); digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); } diff --git a/Esp32Cam/Esp32Cam.ino b/Esp32Cam/Esp32Cam.ino index 246d750..1b22558 100644 --- a/Esp32Cam/Esp32Cam.ino +++ b/Esp32Cam/Esp32Cam.ino @@ -10,7 +10,7 @@ // ================================================================ // OTA CONFIG // ================================================================ -#define FW_VERSION 19 +#define FW_VERSION 20 #define GITEA_HOST "https://git.nacho.myds.me" #define GITEA_OWNER "Natxo" #define GITEA_REPO "Arduino-Car" @@ -71,12 +71,11 @@ static void checkOTA() { int remoteVer = body.toInt(); if (remoteVer <= FW_VERSION) return; // ya tenemos la última versión - // 3 pitidos = ESP32-CAM actualizando (via Serial al ESP8266) + // 3 flashes LED = ESP32-CAM actualizando + // (ESP8266 en waitForReady(), no puede recibir Serial en este momento) for (int i = 0; i < 3; i++) { - Serial.print("H1"); - delay(150); - Serial.print("H0"); - delay(150); + ledcWrite(LED_GPIO_NUM, 255); delay(150); + ledcWrite(LED_GPIO_NUM, 0); delay(150); } delay(300); diff --git a/firmware/esp32cam/firmware.bin b/firmware/esp32cam/firmware.bin index adc8253..5b94b3f 100644 Binary files a/firmware/esp32cam/firmware.bin and b/firmware/esp32cam/firmware.bin differ diff --git a/firmware/esp32cam/version.txt b/firmware/esp32cam/version.txt index dec2bf5..2edeafb 100644 --- a/firmware/esp32cam/version.txt +++ b/firmware/esp32cam/version.txt @@ -1 +1 @@ -19 \ No newline at end of file +20 \ No newline at end of file