Modbus über WLAN Teil 1: Hardware und Programmierung
Das Modbus®-Protokoll ist ein in der Industrie weit verbreitetes Verfahren, mit dem Anlagen und Steuerungen untereinander kommunizieren. Üblicherweise geschieht das über die gute alte RS485-Schnittstelle und traditionelle Kupferadern. In diesem Artikel stellen wir ein Modul vor, mit dem man das Modbus-Protokoll drahtlos über WLAN verwenden kann. Kern des Moduls ist ein NodeMCU-Board mit dem Mikrocontroller ESP8266. Eine zusätzliche Modbus-Basis-Platine sorgt vor allem dafür, dass man mit der in der Industrie üblichen Spannung von 24 V arbeiten kann. Zur anschaulichen Demonstration bauen wir eine einfache Garagentorsteuerung.
Das NodeMCU-Modul und die Arduino-IDE dürften den meisten Elektor-Lesern ja wohlbekannt sein. Wenn Sie dazu gehören, können Sie diesen Abschnitt auslassen und direkt zur Beschreibung der Modbus-TCP-Platine springen. Für alle anderen nun ein Crashkurs!
Der Kern dieses Projektes ist ein NodeMCU-Modul, das auch bei Elektor erhältlich ist. Auf dem Modul ist ein ESP8266-Mikrocontroller verbaut, der kaum größer ist als eine Briefmarke und über eine WLAN-Schnittstelle verfügt. Die Rechenleistung ist auch nicht zu verachten. In Tabelle 1 sind die wichtigsten technischen Daten des ESP8266-Mikrocontrollers zusammengefasst.
Das NodeMCU-Board erzeugt die Betriebsspannung für den ESP8266 und kümmert sich um die Ansteuerung der Programmierschnittstelle des ESP8266. Eine Übersicht der Anschlüsse des NodeMCU-Boards, wie sie in unserer Modbus-Schaltung verwendet werden, sehen Sie in Bild 1.
Zur Programmierung des NodeMCU-Boards eignet sich hervorragend die Arduino-IDE, die frei von der Arduino-Homepage [2] passend für das Betriebssystem Ihres Rechners heruntergeladen und gemäß der Anweisungen auf der Webseite installiert werden kann. Nach dem ersten Start präsentiert sich die IDE wie in Bild 2 zu sehen: Im Bereich für den Programmcode sind schon zwei Funktionen vordefiniert, die setup()-Funktion, die nur einmal beim Start des Programms ausgeführt wird und die beispielsweise der Initialisierung der Mikrocontroller-Schnittstellen dient, und unterhalb davon die loop()-Funktion, die normalerweise den Sourcecode Ihres Programms beherbergt.
Die loop()-Funktion wird aufgerufen, sobald die setup()-Funktion beendet ist. Ist die loop()-Funktion an ihr Ende gelangt, startet sie immer wieder neu. Zwischen dem Beenden und dem Neustarten der loop()-Funktion verwaltet der ESP8266 die WLAN-Schnittstelle. Daher müssen Sie darauf achten, dass sich in der loop()-Funktion keine Endlosschleife befindet, denn dies würde den ESP8266 unweigerlich zum Absturz bringen. Der Code in der loop()-Funktion muss vielmehr so beschaffen sein, dass er zyklisch abgearbeitet werden kann.
Ein Großteil aller schwer nachvollziehbaren Abstürze des ESP8266 haben ihre Ursache darin, dass der ESP8266 nicht die notwendige CPU-Zeit zur Verwaltung der WLAN-Schnittstelle erhält. Wenn Ihr Programmcode potentiell länger läuft, zum Beispiel in großen Schleifen, können Sie dem ESP8266 mit der yield()- oder der delay()-Funktion die Zeit zur WLAN-Verwaltung geben.
Das NodeMCU-Modul wird (noch nicht auf die Modbus-Platine gesteckt, sondern direkt) an den USB Ihres Computers angeschlossen, aber eines muss noch geschehen, bevor Sie loslegen können. Der ESP8266 wird standardmäßig nicht von der Arduino-IDE unterstützt, sondern muss nachgerüstet werden. Dazu gibt man unter Datei -> Voreinstellungen im Feld Zusätzliche Bordverwalter-URLs die URL:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
an, öffnet nach dem OK den Boardverwalter unter Werkzeuge -> Board: “...” -> Boardverwalter…, sucht und findet ESP8266 und installiert die Boards der ESP8266 Community.
Nach der Installation wird unter Werkzeuge -> Board das Board NodeMCU 1.0 (ESP-E12 Module) und unter Werkzeuge -> Port der Port eingestellt, an dem das NodeMCU-Board angeschlossen ist (Linux: /dev/ttyUSBx, Windows COMx).
Jetzt können wir mit einem ersten kleinen Test des NodeMCU-Moduls beginnen. Öffnen Sie dazu bitte das Blink-Beispielprogramm (Datei -> Beispiele -> ESP8266 -> Blink).
Das Programm in Listing 1 lässt die auf dem ESP8266-Board verbaute LED blinken. Der Code, der die LED ein- und ausschaltet, befindet sich in der loop()-Funktion. In der setup()-Funktion wird der GPIO-Pin der LED als Ausgang gesetzt.
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
delay(2000);
}
Um das Programm auf das NodeMCU-Board zu laden, klicken Sie nun auf das Hochladen-Icon (Pfeil nach rechts). Nach einigen Sekunden ist das Programm übertragen und die LED beginnt zu blinken. Mit diesem Test ist die Installation der IDE abgeschlossen.
Die Modbus-TCP-Platine
Wie im Titelbild zu sehen ist, befindet sich das NodeMCU-Modul auf der Modbus-TCP-Platine, auf der es recht „industriell“ zugeht. Alle Ein- und Ausgänge sind mit steckbaren Schraubklemmen versehen. Das erleichtert die Montage und die Schraubverbinder können leicht getauscht werden, wenn mal einer kaputtgeht. Hauptsächliche Aufgabe der Modbus-TCP-Platine ist es, die 3,3 V der Mikrocontroller-Ein- und Ausgänge in industriekompatible 24 V umzuwandeln. Das Schaltbild 3 zeigt, dass die vier Eingänge durch PC814-Optokoppler galvanisch vom Controller getrennt sind. Die Eingänge sind nicht einzeln am Controllerboard angeschlossen, sondern über einen Multiplexer 74HC151. Mit diesem kleinen Trick spart man einen GPIO-Anschluss, an den man einen DHT11-Sensor zur Messung von Temperatur und Luftfeuchte in die Schaltung aufzunehmen kann. Damit ist es möglich, die Modbus-Platine für einfache Klimaregelungen zu verwenden.
In den Ausgangsstufen sind BSP76 von HITFET verbaut (Bild 4). Dabei handelt es sich nicht um simple Power-MOSFETs, sondern um ICs, die den elektronischen Leistungsschalter mit verschiedenen Schutzmechanismen wie Überspannungsschutz, Strombegrenzung und Übertemperaturschutz ausstatten. So kann man ohne Bedenken ohmsche, induktive und kapazitive Lasten schalten.
Neben den digitalen Ein- und Ausgängen verfügt die Modbus-TCP-Platine über einen analogen Eingang und einen analogen Ausgang. Beide Analoganschlüsse arbeiten mit dem in der Industrie üblichen Spannungsbereich von 0...10 V. Beim analogen Eingang reduziert der Spannungsteiler R14/R17 die Eingangsspannung auf maximal 3,3 V. Der Eingang ist nicht galvanisch getrennt, aber C7, D10 und D11 sorgen für einen gewissen Schutz gegen Spikes und Überspannungen. Die Reihenwiderstände R14 und R19 begrenzen den Eingangsstrom, so dass die Dioden im Falle eines Falles nicht in Rauch aufgehen können.
Beim analogen Ausgang hebt IC3, ein Universal-Operationsverstärker LM7301 (Rail-to-Rail an Ein- und Ausgängen) die Ausgangsspannung des DAC des NodeMCU-Moduls an. Die Verstärkung ist durch R15 und R16 auf den Faktor 3 eingestellt. Der Opamp wird hier mit 24 V versorgt.
Besonderes Augenmerk sollten wir auf den DC/DC-Wandler von Recom richten. Er wandelt die 24-V-Versorgungsspannung in die 5 V, die für die Spannungsversorgung des NodeMCU-Moduls benötigt werden. Der DC/DC-Wandler weist einen Wirkungsgrad von weit über 90% auf und kann sehr flexibel eingesetzt werden. Es ist zum Beispiel auch möglich, mit dem Wandler eine negative Betriebsspannung für Operationsverstärker zu erzeugen. Ein Blick in das Datenblatt [4] des Wandlers lohnt sich auf jeden Fall. Direkt am 24-V-Eingang befindet sich eine 1N4007-Diode als Verpolungsschutz für die Schaltung.
Die Gerber-Dateien für die Platinenproduktion können von der Projektseite [8] heruntergeladen werden. Die Platine ist im unbestückten Zustand oder auch betriebsfertig bestückt beim Autor erhältlich [7].
Holzmodell zur Demonstration
Um zu zeigen, wie das Modbus-Modul mit in der Industrie üblichen Aufgaben fertig wird, habe ich ein Garagentor-Modell frisch aus dem chinesischen Supermarkt [5] verwendet (Bild 5). Das Tor wird über zwei Drucktaster geöffnet und geschlossen. Die Endpositionen des Tores werden über zwei kapazitive Näherungsschalter erkannt. Der Motor, der das Tor öffnet und schließt, wird mit Hilfe einer H–Brücke angesteuert, die aus zwei Leistungsrelais aufgebaut ist.
In Listing 2 ist das Programm zur Ansteuerung zu sehen. Das Programm definiert zunächst Klartext-Namen für die Ein- und Ausgänge der Schaltung. In der setup()-Funktion werden die einzelnen I/Os als Ein- und Ausgänge initialisiert. Danach folgen die Funktionen input() und output(), die uns einen etwas einfacheren Zugriff auf die I/Os ermöglichen. Das eigentliche Programm befindet sich in der loop()-Funktion. Hier werden die Ausgänge zur Ansteuerung des Motors abhängig von den Tastern und Endschaltern an- oder ausgeschaltet. Das Programm in der loop()-Funktion kann zyklisch ausgeführt werden. Falls Sie die Garagentürsteuerung in Aktion sehen wollen, schauen Sie doch einfach einmal bei YouTube [6] vorbei.
#define A1 16
#define A2 5
#define A3 19
#define A4 0
#define MUXA 12
#define MUXB 13
#define MUXY 14
#define E1 0
#define E2 1
#define E3 2
#define E4 3
void setup() {
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A4, OUTPUT);
pinMode(MUXA, OUTPUT);
pinMode(MUXB, OUTPUT);
pinMode(MUXY, INPUT);
}
bool input(int i){
digitalWrite(MUXA,(i&1));
digitalWrite(MUXB,(i&2)>>1);
delay(1);
return digitalRead(MUXY);
}
void output(int i, int v){
digitalWrite(i,v);
}
void loop() {
if(input(E4)& !input(E1)){output(A1,HIGH);}
if(input(E3)& !input(E2)){output(A2,HIGH);}
if(input(E1)){output(A1,LOW);}
if(input(E2)){output(A2,LOW);}
}
Ausblick
Ihnen dürfte trotz der Freude über die funktionierende Garagentor-Steuerung nicht entgangen sein, dass unser WLAN-Modul noch gar nicht zum Zuge gekommen ist. Dies wird der Inhalt des zweiten Teils des Artikels sein! Wir beschäftigen uns dann auch mit dem Modbus-Protokoll und welche Software man einsetzen kann, um über den Bus zu kommunizieren. Weiterhin zeigen wir, wie das Modbus-Modul eingerichtet werden kann.
Die Autoren
Josef Bernhardt hat sich schon früh mit Elektronik beschäftigt. Mit zwölf Jahren baute er seinen ersten Detektorempfänger, weitere Schaltungen folgten. Die ersten Programmiererfahrungen sammelte er in den 80er-Jahren mit dem Commodore VC20. Auch Assemblerprogrammierung auf dem 8088 Prozessor ist ihm nicht fremd. Er kann auf über 30 Jahre Elektronikentwicklung an der Uni Regensburg zurückblicken. Dort war er im Bereich Elektronik- und Softwareentwicklung tätig. Mit der eigenen SMD-Fertigung setzt er auch Elektronikprojekte von Kunden um.
Martin Mohr erblickte im Zeitalter der Magnet-Ringkernspeicher und Hebdrehwähler das Licht der Welt und hat somit die komplette Entwicklung der modernen Computertechnik miterleben dürfen. Die Vorliebe für alles, was blinkt, hat sich schon in seiner frühen Jugend entwickelt und wurde durch eine Ausbildung zum Elektroniker noch verstärkt. Nach dem Informatikstudium lag sein Beschäftigungsfeld überwiegend in der Entwicklung von Java-Applikationen. Mit dem Raspberry Pi ist aber die alte Liebe zur Elektronik wiedererwacht.