Erkennt AutoRecover das Plotter-Recover-Fenster, ruft es jetzt zuerst einen ESP auf (HTTP /trigger) und klickt danach „Recover". Der ESP schaltet einen MOSFET und aktiviert damit die Stromzufuhr. Konfiguration über config.json (esp_url/esp_path/esp_key/esp_timeout) bzw. Env-Vars; ohne esp_url unverändertes Verhalten. Neu: esp/skrift_mosfet.ino (ESP8266/ESP32-Firmware, WLAN + HTTP-Server, Endpunkte /trigger /on /off, getimter Puls oder Latch) + esp/README.md (Verdrahtung/Flashen) + config.example.json. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
137 lines
5.4 KiB
C++
137 lines
5.4 KiB
C++
/*
|
||
* Skrift – ESP MOSFET-Trigger („Stromzufuhr aktivieren")
|
||
* ===========================================================================
|
||
* Kleiner WLAN-Empfänger für einen N-Kanal-MOSFET (Low-Side-Schalter).
|
||
* AutoRecover ruft bei jedem Plotter-Recover-Fenster den Endpunkt /trigger auf;
|
||
* der ESP schaltet dann den MOSFET (GPIO) und aktiviert damit die Stromzufuhr.
|
||
*
|
||
* Läuft auf ESP8266 (NodeMCU/Wemos D1 mini) UND ESP32 – die passenden Bibliotheken
|
||
* werden über die Board-Auswahl in der Arduino IDE automatisch gewählt.
|
||
*
|
||
* Endpunkte (HTTP GET, Port 80):
|
||
* / Statusseite (Text) – Pin-Zustand, Uptime, IP
|
||
* /trigger MOSFET aktivieren (Puls von PULSE_MS ms; 0 = dauerhaft an)
|
||
* /on MOSFET dauerhaft AN
|
||
* /off MOSFET AUS
|
||
* Optionaler Schutz: ist AUTH_TOKEN gesetzt, muss jeder Aufruf ?key=<token>
|
||
* mitschicken (muss zu esp_key in der AutoRecover-config.json passen).
|
||
*
|
||
* Verdrahtung (Low-Side, N-Kanal-Logic-Level-MOSFET, z. B. IRLZ44N / AO3400-Modul):
|
||
* ESP GPIO (MOSFET_PIN) ─► Gate (ggf. 100–220 Ω in Reihe)
|
||
* Gate ─► 100 kΩ ─► GND (Pulldown, damit der MOSFET beim Booten sicher AUS ist)
|
||
* Last(+) an Versorgung+, Last(−) ─► Drain ; Source ─► GND (gemeinsame Masse!)
|
||
* GND von ESP und Last-Versorgung verbinden.
|
||
* ACTIVE_HIGH=true: GPIO HIGH = MOSFET leitet = „Strom an".
|
||
*/
|
||
|
||
#if defined(ESP32)
|
||
#include <WiFi.h>
|
||
#include <WebServer.h>
|
||
WebServer server(80);
|
||
#else
|
||
#include <ESP8266WiFi.h>
|
||
#include <ESP8266WebServer.h>
|
||
ESP8266WebServer server(80);
|
||
#endif
|
||
|
||
// ── Konfiguration ──────────────────────────────────────────────────────────
|
||
const char* WIFI_SSID = "DEIN_WLAN";
|
||
const char* WIFI_PASS = "DEIN_WLAN_PASSWORT";
|
||
|
||
// GPIO, an dem das MOSFET-Gate hängt. ESP8266: 5 = D1 (Wemos/NodeMCU). ESP32: z. B. 23.
|
||
const int MOSFET_PIN = 5;
|
||
const bool ACTIVE_HIGH = true; // true: HIGH = MOSFET an ("Strom an")
|
||
const unsigned long PULSE_MS = 3000; // /trigger: Dauer der Aktivierung (0 = latch, bleibt an)
|
||
|
||
// Optionaler Schutz. Leer = kein Schutz. Muss zu esp_key in der config.json passen.
|
||
const char* AUTH_TOKEN = "";
|
||
|
||
// Optionale feste IP (empfohlen, damit AutoRecover eine stabile Adresse hat).
|
||
// Auf true setzen und Werte anpassen; sonst DHCP.
|
||
const bool USE_STATIC_IP = false;
|
||
IPAddress IP_ADDR (192, 168, 2, 50);
|
||
IPAddress IP_GATE (192, 168, 2, 1);
|
||
IPAddress IP_MASK (255, 255, 255, 0);
|
||
IPAddress IP_DNS (192, 168, 2, 1);
|
||
|
||
// ── Zustand ────────────────────────────────────────────────────────────────
|
||
bool mosfetAn = false;
|
||
bool pulsAktiv = false;
|
||
unsigned long pulsBis = 0;
|
||
|
||
void mosfetSchreiben(bool an) {
|
||
mosfetAn = an;
|
||
digitalWrite(MOSFET_PIN, (an == ACTIVE_HIGH) ? HIGH : LOW);
|
||
}
|
||
|
||
bool autorisiert() {
|
||
if (strlen(AUTH_TOKEN) == 0) return true;
|
||
return server.hasArg("key") && server.arg("key") == AUTH_TOKEN;
|
||
}
|
||
|
||
void sendeStatus(const char* hinweis) {
|
||
String s = String(hinweis) + "\n";
|
||
s += "mosfet="; s += (mosfetAn ? "an" : "aus"); s += "\n";
|
||
s += "puls="; s += (pulsAktiv ? "aktiv" : "-"); s += "\n";
|
||
s += "ip="; s += WiFi.localIP().toString(); s += "\n";
|
||
s += "uptime_s="; s += String(millis() / 1000); s += "\n";
|
||
server.send(200, "text/plain; charset=utf-8", s);
|
||
}
|
||
|
||
void handleRoot() { sendeStatus("Skrift ESP MOSFET-Trigger"); }
|
||
|
||
void handleTrigger() {
|
||
if (!autorisiert()) { server.send(403, "text/plain", "verboten\n"); return; }
|
||
mosfetSchreiben(true);
|
||
if (PULSE_MS > 0) { // getimter Puls
|
||
pulsAktiv = true;
|
||
pulsBis = millis() + PULSE_MS;
|
||
sendeStatus("OK trigger (puls)");
|
||
} else { // dauerhaft an (latch)
|
||
pulsAktiv = false;
|
||
sendeStatus("OK trigger (latch)");
|
||
}
|
||
}
|
||
|
||
void handleOn() { if (!autorisiert()) { server.send(403, "text/plain", "verboten\n"); return; } pulsAktiv = false; mosfetSchreiben(true); sendeStatus("OK on"); }
|
||
void handleOff() { if (!autorisiert()) { server.send(403, "text/plain", "verboten\n"); return; } pulsAktiv = false; mosfetSchreiben(false); sendeStatus("OK off"); }
|
||
|
||
void setup() {
|
||
Serial.begin(115200);
|
||
pinMode(MOSFET_PIN, OUTPUT);
|
||
mosfetSchreiben(false); // sicher AUS beim Start
|
||
|
||
if (USE_STATIC_IP) WiFi.config(IP_ADDR, IP_GATE, IP_MASK, IP_DNS);
|
||
WiFi.mode(WIFI_STA);
|
||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||
Serial.print("Verbinde WLAN");
|
||
while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); }
|
||
Serial.println();
|
||
Serial.print("Verbunden. IP: "); Serial.println(WiFi.localIP());
|
||
|
||
server.on("/", handleRoot);
|
||
server.on("/trigger", handleTrigger);
|
||
server.on("/on", handleOn);
|
||
server.on("/off", handleOff);
|
||
server.onNotFound([]() { server.send(404, "text/plain", "nicht gefunden\n"); });
|
||
server.begin();
|
||
Serial.println("HTTP-Server auf Port 80 gestartet.");
|
||
}
|
||
|
||
void loop() {
|
||
server.handleClient();
|
||
|
||
// WLAN bei Bedarf neu verbinden (Plotter läuft lange).
|
||
static unsigned long letzteWlanPruefung = 0;
|
||
if (millis() - letzteWlanPruefung > 10000) {
|
||
letzteWlanPruefung = millis();
|
||
if (WiFi.status() != WL_CONNECTED) WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||
}
|
||
|
||
// Getimten Puls beenden.
|
||
if (pulsAktiv && (long)(millis() - pulsBis) >= 0) {
|
||
pulsAktiv = false;
|
||
mosfetSchreiben(false);
|
||
}
|
||
}
|