Die vorhandenen Funksteckdosen (433Mhz) haben nicht an allen Standorten sicher funktioniert. Deshalb habe ich einen Umbau der Steckdosen auf WLAN vorgenommen.
Als WLAN-Modul wird der ESP8266-01 eingesetzt. Die ursprüngliche Stromversorgung erschien mir als die preiswerteste Lösung. MIt 33V an der Gleichrichterbrücke und einem Vorschaltkondensator von 220nF ergibt sich eine verfügbare Leistung von 3W für WLAN-Modul und Relais. Problem war dabei, daß das Relais ein 12V-Typ ist und bei 12V Rohspannung reicht die Leistung nicht für WLAN und gezogenes Relais. Lösung ist ein PWM-Betrieb des Relais. Zum Anzug wird das Tastverhältnis so geregelt, das 12V für 20ms anliegen und danach wird reduziert auf 6V. Damit ist genügend Energiereserve zum sicheren Betrieb des WLAN-Moduls vorhanden.
Leider konnte bei dieser Hardwarelösung nicht die TASMOTA-Software eingesetzt werden, weil die Befehlsabarbeitung der Scripte zu langsam war, um das Relais per PWM zu betreiben. Die Software ist in C++ geschrieben und stellt auch ein Firmware-Update über das Webinterface zur Verfügung.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <WiFiUdp.h>
//#include <string.h>
#include "index_html.h" // In dieser Datei befindet sich die Steuerung Webseite
const char* ssid = "ssid"; // WLAN-Name,
const char* password = "password"; // WLAN-Passwort
const char* WiFi_hostname = "ESP-Rel-0000";
//#define RelaisPin 0 // GPIO 0 Modulpin 3
/* GPIO 0 kann für Relais nicht verwendet werden, weil beim Start Signal auf L geht --> Relais zieht zuviel Strom
ist eventuell für Signalisierung mit LED verwendbar (WLAN nicht verbunden oder WLAN-Verbindung ok.)
*/
#define LedPin 0 // GPIO 0 Modulpin 3 // LED
#define RelaisPin 3 // GPIO 3 Modulpin 1 // Relais
#define TXD 1 // GPIO 1 Modulpin 8 // blaue LED
#define TasterPin 2 // GPIO 2 Modulpin 5 // Aktiv Low (Taster gegen GND)
#define RXD 3 // GPIO 3 Modulpin 1
// Modulpin 2 = VCC
// Modulpin 4 = /Reset
// Modulpin 6 = Enable (muss an VCC)
// Modulpin 7 = GND
#define USE_SERIAL Serial
#define U_Z_Diode 33
#define U_Relais_min 7 // bei 33V bekommt Relais 6,6V ab
#define prog_vt 1024 - round(1024 * U_Relais_min / U_Z_Diode)
#define U_Relais_nom 12 // bei 33V bekommt Relais 12V ab
#define prog_vt1 1024 - round(1024 * U_Relais_nom / U_Z_Diode)
int active_low = 1; // "0" Relais schaltet bei +5V , "1" Relais beim schaltet bei 0V
int val = 0; // Hier wird der Schaltzustand gespeichert
ESP8266WebServer server(80); // Serverport hier einstellen
ESP8266HTTPUpdateServer httpUpdater;
void set_relais()
{
if ((active_low ^ val)==0)
{
analogWrite(RelaisPin,prog_vt1);
delay(20); // 20ms full power (12V)
analogWrite(RelaisPin,prog_vt); // relay is on, power reduce to U_Relais_min
}
else
{digitalWrite(RelaisPin, 1);}
}
char* dbgprint ( const char* format, ... )
{
static char sbuf[60] ; // For debug lines
va_list varArgs; // For variable number of params
va_start ( varArgs, format ) ; // Prepare parameters
vsnprintf ( sbuf, sizeof(sbuf), format, varArgs ) ; // Format the message
va_end ( varArgs ); // End of using parameters
return sbuf ; // Return stored string
}
void handleNotFound() { server.send(404, "text/plain", "404: Not found"); } // Send HTTP status 404 (Not Found)
void Index() { server.send(200, "text/html", indexHTML); } // Index-Webseite senden (sehe Datei "index_html.h")
void Command() // Wird ausgeführt wenn "http://<ip address>/cm/" aufgerufen wurde
{
if (server.args() > 0) // wenn Argumente im GET Anfrage vorhanden sind z.B http://<ip address>/?zustand=r
{
if (server.arg("cmnd") == "power 0") { val = 0; set_relais(); }
if (server.arg("cmnd") == "power 1") { val = 1; set_relais(); }
if (server.arg("cmnd") == "power 2") { val = !val; set_relais(); }
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
// wichtig! damit Daten nicht aus dem Browser-Cache kommen
server.sendHeader("pragma","no-cache");
server.sendHeader("Expires", "-1");
server.sendHeader("Access-Control-Allow-Origin","*");
server.send(200, "application/json", String(int(val)) ); // Antwort an Internet Browser senden nur eine Zahl ("0"/"1")
}
}
void HTTP_update()
{
t_httpUpdate_return ret = ESPhttpUpdate.update("http://ds215j/wlanSW/updater.php","WLAN_SD");
switch (ret) {
case HTTP_UPDATE_FAILED:
USE_SERIAL.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
USE_SERIAL.println("HTTP_UPDATE_NO_UPDATES");
break;
case HTTP_UPDATE_OK:
USE_SERIAL.println("HTTP_UPDATE_OK");
break;
}
}
void setup() {
pinMode(RelaisPin, OUTPUT);
pinMode(TasterPin, INPUT_PULLUP);
pinMode(LedPin, OUTPUT);
digitalWrite(RelaisPin, active_low);
digitalWrite(LedPin,val); // Led an
analogWriteFreq((uint32_t)15000); // PWM-Frequenz für Relais
WiFi_hostname = dbgprint("ESP-Rel-%04d",ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname
WiFi.hostname(WiFi_hostname);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(250);val = !val; // LED blinkt 2 x pro Sekunde
digitalWrite(LedPin,val); // Led toggeln
}
delay(250);val = 0;
digitalWrite(LedPin,active_low); // Led aus
// Behandlung der Ereignissen anschliessen
server.on("/", Index);
server.on("/cm", Command);
server.onNotFound ( handleNotFound );
httpUpdater.setup(&server);
server.begin();
}
void loop() {
server.handleClient();
if (!digitalRead(TasterPin)) // Wenn Taster betätigt "Signal 0"
{
val = !val; // Umschalten
set_relais(); delay(500); // Entprellung, Warten bis der Taster Kontakt sich beruhigt hat
while (!digitalRead(TasterPin)) server.handleClient(); // warten bis der Taster los gelassen wurde
}
}
Code-Sprache: C++ (cpp)