WLAN IR Brücke mit ESP32

Der letzte Blog-Eintrag Lernende Infrarot-Fernbedienung hat gezeigt, wie man mit dem ESP32 Infrarot-Fernbedienungssignale aufzeichnen und wiedergeben kann. Nachdem das gut funktioniert, ergibt sich die Frage, ob man die IR-Kommandos über eine WiFi-Verbindung (statt mit den Tastern an der Schaltung) steuern kann. In diesem Eintrag geht es darum, die angelernten IR-Kommandos über eine Web-Page abrufbar zu machen, eine WLAN-IR-Brücke.

Wofür braucht man so etwas? Es ist doch sehr komfortabel, ein elektronisches Gerät, z.B. eine Radio oder eine Stereo-Anlage, mit der zugehörigen Fernbedienung direkt zu steuern. Tatsächlich gibt es aber durchaus Fälle, in denen der Zugriff über eine Web-Page hilfreich sein kann, z.B., wenn das Gerät in einem anderen Raum steht und über IR nicht erreichbar ist, oder das Radio aus der Ferne an – oder ausgeschaltet werden soll.

Dieses Projekt hat zwei Komponenten. Erstens wurden die IR-Funktionen aus dem vorherigen Blog-Eintrag in eine eigene C++-Klasse IR_Module verpackt, wodurch sie einfacher zu verwenden sind. Zweitens kommt das WiFi-Modul des ESP32 zum Einsatz, um eine Web-Page mit Buttons zu erzeugen. Die Web-Page ist mit jedem normalen Browsers auf Computer, Tablett oder Handy aufrufbar, ohne dass weitere Installation auf dem Gerät notwendig sind. Aber der Reihe nach:

Die Hardware

Im Vergleich zum vorherigen Beispiel ist die Schaltung etwas einfacher geworden. IR-Empfänger und IR-Sender mit Transistor und IR-LED bleiben unverändert. Es gibt jetzt nur noch einen Taster, der zum Anlernen der IR-Fernbedienung benötigt wird. Die Tasten zum Abruf der IR-Signale sind nicht mehr nötig, weil der Abruf jetzt über die Buttons auf der Web-Page geschieht. Schließlich gibt es noch eine zweifarbige Leuchtiode zur Kommunikation mit dem Anwender.

Die Schaltung ist einfacher geworden. Die Hardware-Taster zum Auslösen der IR-Kommandos sind verschwunden. Sie werden durch Buttons auf der Web-Page ersetzt.
Aufbau der WLAN-IR-Bridge auf einem Breadboard

Klasse IR_Module

Die Vorgehensweise zum Lernen und Abspielen von IR-Signalen wurden im vorherigen Blog-Eintrag beschrieben. Um die Anwendung der zugehörigen Funktionen zu vereinfachen, haben ich Daten und Funktionen in einer Klasse zusammengefasst. Der Quellcode der Klasse besteht aus zwei Dateien, die Header-Datei ESP32_IR_module.h und die Methoden-Datei ESP32_IR_module.cpp.

In der Header-Datei werden die benötigten Daten bereit gestellt. Dreh- und Angelpunkt sind die Daten der IR-Signale. Sie werden in einem zweidimensionalen Array ir_data[][] abgelegt.

uint32_t ir_data[CHANNEL_MAX][IR_DATA_SIZE];     
int ir_data_len[CHANNEL_MAX];
int channel_cnt = 0;

Man kann sich das Array als Tabelle mit Zeilen und Spalten vorstellen. Jede Zeile bildet ein IR-Kommando und enthält als Spalten die Ein- und Ausschalt-Zeitpunkte des zugehörigen IR-Signals. Das Array verwendet 32-Bit-Integer Variablen, die die Zeitpunkte in Mikrosekunden relativ zum Anfang des Signals darstellen. Der ESP32 biete viel Speicherplatz. Hier werden maximal 10 (definiert in CHANNEL_MAX) angelernte Kommandos mit jeweils bis zu 250 (definiert in IR_DATA_SIZE) Umschaltzeitpunkten bereit gestellt. Es hat sich gezeigt, dass die Datenmenge ausreichend für die üblichen Anwendungen ist.

Das eindimensionale Array ir_data_len[] hält fest, wieviel Datenpunkte in jeder Zeile von ir_data[][] tatsächlich verwendet werden. Die Variable channel_cnt enthält die aktuelle genutzte Anzahl der IR-Signale, also die Zahl der verwendeten Zeilen.

Die Klasse stellt eine Reihe von Methoden bereit. load_ir_data(), save_ir_data() und clear_ir_data() dienen dem Speichermanagement. Die angelernten IR-Daten werden mit save_ir_data() in den permanenten “non-volatile” Speicher übertragen. Beim Systemstart können sie mit load_ir_data() aus dem permanenten Speicher in das RAM geladen und damit verfügbar gemacht werden. Mit clear_ir_data() werden die bestehenden Daten gelöscht, z.B. wenn eine neuen Fernbedienung angerlernt werden soll.

Mit der Methode read_ir_data() werden IR-Daten angelernt. Dabei wartet die Schaltung auf IR-Signale von einer Fernbedienung und speichert neue Kommandos ab. Die Funktion führt auch eine einfache Plausibilitäts-Prüfungen durch und quittiert IR-Impulse, die offensichtloch kein sinnvolles IR-Fernbedienungssignal darstellen, mit einer Fehlermeldung.

Die Methode play_ir_data(int channel) spielt das angewählte IR-Signal aus dem Speicher ab, sendet also das gewünschte Signal aus.

Die Methode print_ir_data(int chnnel) gibt die Daten eines Kanals auf dem seriellen Monitor aus. Das ist nur für debugging-Zwecke gedacht.

Und schließlich gibt es noch die Methode get_channel_cnt(), die die Anzahl der gespeicherten IR-Kommandos zurück gibt.

Um die Klasse zu verwenden, muss das aufrufende Programm ein Objekt vom Typ IR_Module anlegen, üblicherweise als globale Variable, so dass alle Funktionen darauf zugreifen können. Der Konstruktor benötigt die Pin-Nummern, an denen der IR-Empfänger und der IR-Sender angeschlossen sind.

IR_Module ir(34, 33);    // receiver and transmitter pin number

Web-Server mit dem ESP32

Es wurde schon viel über das WiFi-Modul des ESP32 geschrieben, deshalb hier nur in Kürze. Ich verwende einen Web-Server, der sich mit einer festen (statischen) IP-Adresse (hier 192.168.1.222) in das Heimnetzwerk einklinkt. Der Vorteil der statischen IP-Adresse ist, dass die zugehörige Web-Page direkt über die IP-Adresse abrufbar ist. Natürlich muss sichergestellt werden, dass die IP-Adresse im Netzwerk frei und verfügbar ist. Gegebenenfalls lässt sich das im Router einstellen. Der zugehörige Programm-Code sieht so aus:

#include <WiFi.h>
#include <WebServer.h>

// Create webserver operating on port 80, set static IP address
WebServer server(80);
IPAddress local_IP(192, 168, 1, 222);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

In der Arduino-Setup-Funktion verbindet sich der Web-Server mit dem Netzwerk. Die Zugangsdaten mit SSID und Passwort sind der Einfachheit halber direkt in den Programm-Code eingebettet. Während des Verbindungsaufbaus blinkt die rote LED. Wenn alles geklappt hat, gibt es eine Sekunde lang ein grünes Signal.

// Connect to WiFi network
if (!WiFi.config(local_IP, gateway, subnet)) {
  Serial.println("Failed to configure static IP address");
}
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  digitalWrite(led_green, !digitalRead(led_green));
  Serial.print(".");
  delay(500);
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(led_green, HIGH);
delay(1000);
digitalWrite(led_green, LOW);

Wenn die Verbindung steht, kann der Web-Server gestartet werden. Die Web-Page ist dann über die http://192.168.1.222 erreichbar.

Die Tasten werden als eigene Seiten unter dieser Adresse, also über 192.168.1.222/0, …/1, …/2 usw. bereit gestellt. Wenn eine Taste auf der Web-Page gedrückt wird, erzeugt der Browser einen Aufruf der entsprechenden URL. Der Web-Server des ESP32 empfängt den Aufruf und leitet ihn auf die Funktion handle_channel(). Diese führt dann die gewünschte Aktion aus, als das Abspielen des jeweiligen IR-Signals.

Der Start des Web-Servers in der setup()-Funktion ist hier gezeigt:

 // prepare and start web server
  char url_str[4] = "/ ";
  server.on("/", handle_OnConnect);
  for (int button_channel = 0; button_channel < CHANNEL_MAX; ++button_channel) {
    url_str[1] = '0' + button_channel;
    server.on(url_str, handle_channel);
  }
  server.onNotFound(handle_NotFound);
  server.begin();

Schließlich fehlt noch der HTML-Code, der an den Browser gesendet wird, wenn dieser sich mit der Seite verbindet. Dazu dient die Funktion send_html(), die den HTML-Code generiert und an den Client sendet. Die Buttons sind als Cascading Style Sheets (CSS) in den HTML-Code integriert. Der CSS-Code definiert die Farbe, Größe und Text der Buttons. Außerdem sorgt der Code mit Hilfe des Strings href dafür, dass bei einem Tastendruck die entsprechende URL aufgerufen wird. Damit ist der Kreis zum Web-Server und der Funktion handle_channel() geschlossen.

Die Hauptarbeit des Programms wird vom Web-Server und der Funktion handle-channel() übernommen. Entsprechend kurz fällt die Arduino loop()-Funktion au. Hier wird abgefragt, ob die Learn-Taste der Schaltung für mindestens 3 Sekunden gedrückt wurde. Wenn das der Fall ist, dann verzweigt das Programm in die Funktion learn_sequence(), die zum Anlernen einer neuen IR-Fernbedienung dient. Außerdem wird regelmäßig die Methode handleClient() des Web-Servers aufgerufen. Dadurch wird sichergestellt, dass der Web-Server auf die Verbindungsaufnahem durch einen Client reagiert.

void loop() {
  uint8_t learn_pressed_cnt = 0;

  // check whether the learn button is pressed for at least 3 seconds
  while (digitalRead(bt_learn) == LOW) {
    delay(200);
    ++learn_pressed_cnt;
    if (learn_pressed_cnt >= 15) {
      learn_sequence();
      ir.save_ir_data_set();
      learn_pressed_cnt = 0;
    }
  }

  // manage requests from web clients
  server.handleClient();
}

Inbetriebnahme

Hier eine kurze Beschreibung, wie die Schaltung und das Programm in Betrieb genommen werden.

Das Programm besteht aus 3 Dateien: ESP32_WLAN_IR_Bridge.ino, ESP32_IR_module.cpp und ESP32_IR_Module.h. Alle 3 Dateien müssen im entsprechenden Arduino-Folder liegen.

In der Datei ESP32_WLAN_IR_Bridge.ino gibt es einige Anpassungen am Anfang des Programms zu machen. Name und Zugangspasswort für das Heimnetz müssen bei SSID und Password eingetragen werden. Die globale Konstante char *bt_labels bietet die Möglichkeit, die Buttons auf der Web-Page mit sinnvollen kurzen Labels zu versehen, je nachdem, was die IR-Steuerung machen soll. Das Programm kann maximal 10 Buttons (Kanäle) bedienen. Im Zweifelsfall kann man einfach eine fortlaufende Nummer verwenden. Schließlich sollte die statische IP-Adresse entsprechende den eigenen Bedürfnissen angepasst werden

// network credentials - insert your data
const char ssid[] = "your network name";
const char password[] = "your network password";

// Labels for up to 10 buttons on the web page - customize for your needs.
const char *bt_label[] = {"On/Off", "Mode", "Vol +", "Vol -", "P +", "P -", "7", "8", "9", "10"};

// Create webserver operating on port 80, set static IP address
WebServer server(80);
IPAddress local_IP(192, 168, 1, 222);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

Wenn das Programm kompiliert und auf den ESP32 übertragen ist, ist das System einsatzbereit. Nach dem Einschalten verbindet sich der ESP32 mit dem Netzwerk. Das ist an der blinkenden Leuchtdiode erkennbar. Wenn die Verbindung erfolgreich ist, zeigt die LED eine Sekunde lang grün und geht dann aus. Die Web-Page ist jetzt über einen Browser über die IP-Adresse abrufbar.

Zum Anlernen einer IR-Fernbedienung muss die Lern-Taste für mindestens 3 Sekunden gedrückt werden. Achtung, dadurch werden alle bestehenden Daten gelöscht! Die blinkende LED zeigt jetzt an, dass die Schaltung bereit ist zum Lernen. Die gewünschten Fernbedienung wird auf den IR-Empfänger gerichtet und die erste Taste kurz (!) gedrückt. Wenn das Signal akzeptiert wurde, leuchtet die LED grün auf. Nach einer kurzen Pause ist die Schaltung bereit zum Lernen der nächsten Taste, was wieder durch Blinken angezeigt wird. Das Spiel geht solange, bis entweder für 20 Sekunden keine IR-Signal mehr kommt oder der Speicher mit 10 gelernten Tasten voll ist. Übrigens hat sich in der Praxis gezeigt, dass beim Anlernen direkte Beleuchtung mit manchen LED-Lampen etwas stören kann. Wenn es Probleme gibt, kann es helfen, z.B. das Schreibtischlicht auszuschalten.

Die WLAN-IR-Brücke wird mit den IR-Signalen einer Fernbedienung angelernt.

Nach dem erfolgreichen Lern-Prozess sind die IR-Kommandos über die Web-Page verfügbar. Die IR-Sende-Diode sollte in die Richtung des zu gewünschten Geräts gerichtet sein. Die IR-Kommandos stehen über die Web-Page via Computer oder Handy zur Verfügung, und das Zielgerät kann über das Web gesteuert werden.

So meldet sich der ESP32 beim Aufruf mit dem Browser.

Wie immer an dieser Stelle wünsche ich viel Spaß mit dem kleinen Projekt. Rückmeldung, Kommentare und Verbesserungsvorschläge sind willkommen.

Arduino-Software zur ESP32 WLAN-IR-Bridge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.