Umbau Funksteckdose auf WLAN

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)