You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

128 lines
3.7 KiB

#include <PID_v1.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <LittleFS.h>
#include <ESPAsyncWebServer.h>
#include <max6675.h>
// 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);
}
}