#include #include #include #include #include #include // Wifi credentials const char* ssid = "ReflowOven"; const char* password = "12345678"; AsyncWebServer server(80); AsyncWebSocket ws("/ws"); // SSR relay pin const int SSR_PIN = 5; // D1 (GPIO5) par exemple // PID variables double setpoint = 150, input = 0, output = 0; const int PWM_PERIOD = 2000; double Kp = 2, Ki = 5, Kd = 1; PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT); // Broches MAX6675 (exemple : SCK=14, CS=12, SO=13) const int thermoSO = 13; const int thermoCS = 12; const int thermoSCK = 14; MAX6675 thermocouple(thermoSCK, thermoCS, thermoSO); float lastTemp = NAN; unsigned long lastSend = 0; unsigned long pwmStart = 0; void setup() { // Action chauffe manuelle server.on("/action/preheat", HTTP_POST, [](AsyncWebServerRequest *request){ if (!request->hasArg("temp")) { request->send(400, "text/plain", "Paramètre 'temp' manquant"); return; } setpoint = request->arg("temp").toDouble(); Serial.printf("Chauffe manuelle demandée : %.1f°C (setpoint PID fixé)\n", setpoint); request->send(200, "text/plain", "OK"); }); // Action chauffe profil server.on("/action/profile", HTTP_POST, [](AsyncWebServerRequest *request){ if (!request->hasArg("profile") || !request->hasArg("preheatTemp") || !request->hasArg("preheatTime") || !request->hasArg("soakTemp") || !request->hasArg("soakTime") || !request->hasArg("reflowTemp") || !request->hasArg("reflowTime")) { request->send(400, "text/plain", "Paramètres manquants"); return; } String profile = request->arg("profile"); int preheatTemp = request->arg("preheatTemp").toInt(); int preheatTime = request->arg("preheatTime").toInt(); int soakTemp = request->arg("soakTemp").toInt(); int soakTime = request->arg("soakTime").toInt(); int reflowTemp = request->arg("reflowTemp").toInt(); int reflowTime = request->arg("reflowTime").toInt(); Serial.printf("Profil %s lancé : Preheat %d°C/%ds, Soak %d°C/%ds, Reflow %d°C/%ds\n", profile.c_str(), preheatTemp, preheatTime, soakTemp, soakTime, reflowTemp, reflowTime); request->send(200, "text/plain", "OK"); }); pinMode(SSR_PIN, OUTPUT); digitalWrite(SSR_PIN, LOW); myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, PWM_PERIOD); // output = ms ON sur 2s Serial.begin(115200); delay(100); // Configure ESP8266 as Access Point WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); Serial.print("AP IP address: "); Serial.println(WiFi.softAPIP()); // Initialisation LittleFS if (!LittleFS.begin()) { Serial.println("Erreur LittleFS"); return; } Serial.println("LittleFS monté"); // Route pour servir les fichiers statiques (html, js, css) server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html"); // WebSocket server.addHandler(&ws); // Démarrer le serveur web server.begin(); Serial.println("Serveur web démarré sur port 80"); } void loop() { ws.cleanupClients(); unsigned long now = millis(); // PID myPID.Compute(); // PWM logiciel SSR (2s) if (now - pwmStart >= PWM_PERIOD) { pwmStart = now; } if ((now - pwmStart) < (unsigned long)output) { digitalWrite(SSR_PIN, HIGH); } else { digitalWrite(SSR_PIN, LOW); } // WebSocket température (1Hz) if (now - lastSend > 1000) { lastSend = now; // Lecture température float t = thermocouple.readCelsius(); if (!isnan(t)) { input = t; } String msg = String(input, 1); Serial.println("Température: " + msg + " °C"+" | Output PID: "+ String(output)); ws.textAll(msg); } }