#include #include #include #include #include "FS.h" #include "SD.h" #include "SPI.h" ///////////////////////// // ==== WIFI =========== ///////////////////////// const char* ssid = "MLDEV"; const char* password = "Aysyw2ch?"; WebServer server(80); ///////////////////////// // ==== THERMOCOUPLE ==== ///////////////////////// Adafruit_MAX31856 maxthermo(D7, D9, D10, D8); const int heaterPin = D2; const int heaterPWMRes = 8; const int heaterPWMFreq = 1000; float targetTemp = 50.0; const float maxTemp = 70.0; float lastTemp = 0; float Kp = 5.0; float Ki = 0.1; float Kd = 1.0; float integral = 0; float lastError = 0; unsigned long lastPIDTime = 0; bool heaterEnabled = true; ///////////////////////// // ==== MOTOR ========== ///////////////////////// const int motorPWMPin = D0; const float maxMotorRPM = 1500.0; const int motorPWMMax = 255; float targetRPM = 0; ///////////////////////// // ==== SD ============ ///////////////////////// bool sd_ok = false; File logFile; unsigned long lastLogTime = 0; const unsigned long logInterval = 1000; void logCSV(unsigned long t, float temp, float tgtTemp, int pwm, float rpm) { if (!sd_ok) return; logFile = SD.open("/log.csv", FILE_APPEND); if (!logFile) return; logFile.printf("%lu,%.2f,%.2f,%d,%.0f\n", t, temp, tgtTemp, pwm, rpm); logFile.close(); } ///////////////////////// // ==== WEB UI ========= ///////////////////////// const char INDEX_HTML[] PROGMEM = R"rawliteral( ESP32 Control

ESP32-S3 Control Panel

Temperature: -- °C

Target Temp: -- °C

Motor RPM: --

Heater: --

Target Temp:

Target RPM:

)rawliteral"; void handleRoot() { server.send_P(200, "text/html", INDEX_HTML); } void handleStatus() { String json = "{"; json += "\"temp\":" + String(lastTemp,2) + ","; json += "\"targetTemp\":" + String(targetTemp,2) + ","; json += "\"rpm\":" + String(targetRPM,0) + ","; json += "\"heater\":" + String(heaterEnabled ? "true":"false"); json += "}"; server.send(200, "application/json", json); } void handleSet() { if (server.hasArg("temp")) { targetTemp = min(server.arg("temp").toFloat(), maxTemp); } if (server.hasArg("rpm")) { targetRPM = constrain(server.arg("rpm").toFloat(), 0, maxMotorRPM); analogWrite(motorPWMPin, (targetRPM / maxMotorRPM) * motorPWMMax); } if (server.hasArg("heater")) { heaterEnabled = server.arg("heater").toInt() == 1; if (!heaterEnabled) { analogWrite(heaterPin, 0); integral = 0; lastError = 0; } } server.send(200, "text/plain", "OK"); } ///////////////////////// // ==== SETUP ========== ///////////////////////// void setup() { Serial.begin(115200); pinMode(heaterPin, OUTPUT); analogWriteResolution(heaterPin, heaterPWMRes); analogWriteFrequency(heaterPin, heaterPWMFreq); pinMode(motorPWMPin, OUTPUT); analogWriteResolution(motorPWMPin, 8); analogWriteFrequency(motorPWMPin, 1000); if (!maxthermo.begin()) { Serial.println("Thermocouple init failed"); while (1); } maxthermo.setThermocoupleType(MAX31856_TCTYPE_K); maxthermo.setConversionMode(MAX31856_ONESHOT_NOWAIT); if (SD.begin(21)) { sd_ok = true; if (!SD.exists("/log.csv")) { logFile = SD.open("/log.csv", FILE_WRITE); logFile.println("time_ms,temp_C,targetTemp_C,heaterPWM,targetRPM"); logFile.close(); } } WiFi.begin(ssid, password); Serial.print("Connecting WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nConnected!"); Serial.print("IP: "); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.on("/status", handleStatus); server.on("/set", handleSet); server.begin(); lastPIDTime = millis(); } ///////////////////////// // ==== LOOP =========== ///////////////////////// void loop() { server.handleClient(); unsigned long now = millis(); float dt = (now - lastPIDTime) / 1000.0; lastPIDTime = now; maxthermo.triggerOneShot(); delay(100); if (maxthermo.conversionComplete()) { lastTemp = maxthermo.readThermocoupleTemperature(); int pwm = 0; if (heaterEnabled) { float error = targetTemp - lastTemp; integral += error * dt; pwm = constrain(Kp * error + Ki * integral + Kd * (error - lastError) / dt, 0, 255); lastError = error; analogWrite(heaterPin, pwm); } else { analogWrite(heaterPin, 0); } if (now - lastLogTime >= logInterval) { logCSV(now, lastTemp, targetTemp, pwm, targetRPM); lastLogTime = now; } } }