Relais fernschalten mit nRF24L01

Nachdem Andreas Wolter meinen „Santa Detector“ um zwei nRF24L01 Transceiver ergänzt hatte, um die Sensorsignale in einem anderen Zimmer zu empfangen, lagen die beiden Module bei mir auf dem Tisch, bereit für ein neues Projekt. Wollte ich nicht schon seit längerem verschiedene Lichtkreise auf meiner Modelleisenbahnanlage mit Relais schalten? Der Micro Controller mit dem Funkempfänger und den Relais irgendwo versteckt unter der Platte, der Sender griffbereit neben den Fahrpulten.

In der ersten Option verwende ich Schalter, in der zweiten Option Taster bzw. ein kapazitives Touchpad zum Ein- und Ausschalten der Relais.

Verwendete Hardware

Anzahl Hardwarebauteil
1 Micro Controller mit ATMega 328
1 4-fach oder 8-fach Relais
2 2,4 MHz Transceiver nRF24L01 (optional Breadboard Adapter)
1 Micro Controller Nano V3.0
1 „Mäuseklavier“ (Dipschalter) oder 4-8 Schalter
alternativ 4-8 Taster
alternativ TTP229 16-Channel Digitaler Touch Kapazitiver Sensor Modul
Half-Breadboard und Jumperkabel

 

Vorüberlegungen zur Signalübermittlung

Für eine sichere Datenübertragung ist es sinnvoll, einen eindeutigen Code für die gewünschten Schaltzustände auszuwählen. Zu einem willkürlich gewählten Basiscode von 4000 addiere ich jeweils die Zweierpotenz des gewünschten Relais. Wie immer beim Programmieren beginnt das Zählen bei 0 und endet bei 3 für vier Relais bzw. bei 7 für acht Relais.

Beispiel: Relais 0, 2 und 7 sollen geschaltet werden, also 4000 + 2 hoch 0 + 2 hoch 2 + 2 hoch 7 ergibt einen Code von 4000 + 1 + 4 + 128 = 4133. Wenn das zweite Relais dann ausgeschaltet wird, ändert sich der Code auf 4129. Eine kleine Tabelle zur Wertigkeit der Relais (= Zweierpotenzen):

n

0

1

2

3

4

5

6

7

2 hoch n

1

2

4

8

16

32

64

128


Jedoch, in unserer Schaltung verwenden wir negative Logik, d.h. wegen der internen Pullup-Widerstände (s.u.) ist der ausgeschaltete Zustand 1, beim Einschalten verbinden wir den Pin mit GND und der Zustand wird 0. In diesem Fall subtrahieren wir die jeweilige Wertigkeit von 4015 (bei vier Schaltern, ansonsten 4255), also Code 4015 bedeutet: alle 4 Schalter aus, Code 4000 bedeutet alle Schalter an.

Für die Auswertung des Codes am Empfänger subtrahieren wir zunächst die willkürlich gewählten 4000; der verbleibende Wert liegt zwischen 0 (alles ON) und 15 (vier OFF) bzw. 255 (acht OFF). Bei meinem 4-fach-Relais hilft mir die negative Logik, denn die einzelnen Relais werden angezogen, wenn der jeweilige Eingang mit GND verbunden wird. Achten Sie bitte darauf, welche Art von Relais Sie verwenden wollen und bei welchem Zustand es anzieht. Die Thematik „negative Logik“ greife ich weiter unten noch einmal auf.

Für das weitere Vorgehen hilft eine kleine for-Schleife mit der Funktion bitRead().

zu Beginn des Sketches:

 int bitArray[4];         // resp. 8 for 8 relays

in der loop()-Funktion:

 for (i = 0; i < 4; i++) {
         bitArray[i] = bitRead(var, i);            //Variable var steht für den korrigierten Code

Am Ende steht in bitArray[i] jeweils der Schaltzustand 0 oder 1 für jedes Relais.

Einbindung der Transceiver in beide Sketche

Zunächst werden zu Beginn des Sketches die benötigten Programm-Bibliotheken eingebunden:

 /* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
 RF24 radio(9, 10);                                   // CE, CSN, MOSI=11, MISO=12, SCK=13
 const byte address[6] = "Code8";       // frei wählbare Adresse der Transceiver

In der Funktion void setup() folgt dann die Initialisierung:

    radio.begin();
    radio.openWritingPipe(address);
    radio.setPALevel(RF24_PA_MIN);
    radio.stopListening();                        // beim Sender

bzw.:

  radio.startListening();                       // beim Empfänger

Im Sketch des Senders definiere ich eine Funktion sendcode:

 void sendcode()  {
   radio.write(&code, sizeof(code));
   delay(100);         // little delay for next button press
  }

Beim Empfänger beginnt die Funktion void loop() mit

    if (radio.available()) {
       radio.read(&code, sizeof(code));

Der leichteste Teil ist grundsätzlich die Abfrage der Schalter: Pin-Nummern festlegen, im Setup als Eingänge festlegen und in der Schleife (loop) die Zustände abfragen. Um unnötige Widerstände zu vermeiden, entscheide ich mich für die eingebauten Pullup-Widerstände; das bedeutet negative Logik (s.o.), der Pin wird gegen GND geschaltet. Und aufgrund der Vielzahl der Schalter entscheide ich mich für Arrays mit den Pin-Nummern und Schaltzuständen.

Die Schaltung für den Sender mit vier Schaltern

Anstelle von 4 bzw. 8 einzelnen Schaltern verwende ich ein „Mäuseklavier“. Was das ist, fragen die Jüngeren. Das sind acht Miniaturschalter in einer Reihe. Weit verbreitet auf den Computer-Mainboards der 1990-er Jahre, um die jeweilige Konfiguration des PCs festzulegen.

Bild und Schaltbild

Der Sketch für den Sender mit vier Schaltern (Download):

 /*
 * Arduino Wireless Communication
 * Transmitter Code for 4 Relais
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
 RF24 radio(9, 10); // CE, CSN
 const byte address[6] = "Code8";
 int code=4000;
 int inputPins[4]={2,3,4,5};
 
 void setup() {
   Serial.begin(9600);
   for (int i=0; i <= 3; i++){
     pinMode(inputPins[i],INPUT_PULLUP);
  }
   radio.begin();
   radio.openWritingPipe(address);
   radio.setPALevel(RF24_PA_MIN);
   radio.stopListening();
 }   // end setup
 
 void sendcode() {
   radio.write(&code, sizeof(code));
   delay(100);  // little delay for next button press
  }   // end sendcode
 
 void loop() {
   code = 4000;
   int n = 1;
   for (int i=0; i <= 3; i++){
     int digRead = digitalRead(inputPins[i]);
     Serial.print(" i = ");
     Serial.print(i);
     Serial.print(" digRead = ");
     Serial.println(digRead);
     code = code + n * digRead;
     n = n*2;
  }
   Serial.print(" Code = ");
   Serial.println(code);
   sendcode();
 }   // end loop

Die Schaltung für den Empfänger mit vier Relais

Bild und Schaltbild

Der Sketch für den Empfänger mit vier Relais (Download):

 /*
 * Arduino Wireless Communication
 * Receiver Code for 4 Relais
 *
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
 RF24 radio(9, 10);        // CE, CSN, MOSI=11, MISO=12, SCK=13
 const byte address[6] = "Code8";
 int code = 4000;
 int outputPins[4]={2,3,4,5};    // resp. 8 for 8 relays
 int bitArray[4];                // resp. 8 for 8 relays
 int var = 0;
 
 void setup() {
   Serial.begin(9600);
   for (int i=0; i <= 3; i++){
     pinMode(outputPins[i],OUTPUT);  
    }
   radio.begin();
   radio.openReadingPipe(0, address);
   radio.setPALevel(RF24_PA_MIN);
   radio.startListening();
  }   //end void setup
 
 void loop() {
   if (radio.available()) {
     radio.read(&code, sizeof(code));
     Serial.println(code);
     if (code>=4000 &&code<4256)   {
       Serial.print("Code ist ");
       Serial.println(code-4000);
       var = code-4000;
       Serial.println(var,BIN);
       int i = 0;
       for (i = 0; i < 4; i++) {
         bitArray[i] = bitRead(var, i);
         Serial.print("Schalter ");
         Serial.print(i+1);    
         Serial.print(" ist ");
         Serial.println(bitArray[i]);
         digitalWrite(outputPins[i],bitArray[i]);  
        }
      }
    }
  }   //end void loop

Und nun das Ganze noch einmal mit Buttons bzw. dem kapazitiven Touchpad:

Nicht jeder hat solch ein Mäuseklavier oder Schalter. Aber Taster (button) finden sich bei jedem Maker oder Hobby-Elektroniker. Bei der Verwendung von Tastern müssen wir jedoch die Sketche anpassen, um jeweils bei Tastendruck ein Relais ein- oder auszuschalten. (Wer möchte schon die ganze Zeit den Taster gedrückt halten?).

Wir benötigen für jeden Taster (jedes Relais am Ende der Funkstrecke) drei Variablen:

  1. den Status, den wir senden wollen
  2. den vorherigen Status
  3. den aktuellen Zustand unseres Tasters

Für alle Eingangssignale verwenden wir wieder Arrays:

 int StatusPins[4]={0,0,0,0};
 int lastStatusPins[4]={0,0,0,0};
 int buttonStatus[4]={0,0,0,0};

In der void loop() fragen wir in einer for-Schleife nacheinander alle Taster ab und vergleichen mit dem vorherigen Status. Wenn diese ungleich sind und der Taster erneut LOW ist, wird der gesendete Status invertiert. Zuletzt wird die Variable für den vorherigen Status aktualisiert.

   for (i=0; i <= 3; i++){
     buttonStatus[i] = digitalRead(inputPins[i]);
    }
   delay(100);    // avoid bouncing  
   for (i=0; i <= 3; i++){
     if (buttonStatus[i] != lastStatusPins[i])   {
       if (buttonStatus[i] == LOW)   {
         StatusPins[i] = !StatusPins[i];
      }
       lastStatusPins[i] = buttonStatus[i];    
    }

Hier der Sketch zum Download.

Wem nicht gefällt, dass beim ersten Einschalten alle Relais angezogen sind (wir erinnern uns – „negative Logik“), der kann im Sketch des Empfängers eine kleine Änderung vornehmen:

Wir ändern Zeile 35 in: 

 var = 15 - (code-4000);        // bei 8 Relais  255 – ( )

Dies gilt wieder für mein 4-fach-Relais, bei dem die Eingänge zum Einschalten „gegroundet“ werden müssen.

„Touch“ anstelle von „Push“:

Es gibt eine Sorte Taster, die mechanisch und elektrisch fast unverwüstlich sind: Berührungssensoren, die nach dem Prinzip Änderung der Kapazität arbeiten. 

Im Weiteren verwende ich das TTP229 16-Channel Digitaler Touch Kapazitiver Sensor Modul, das auf zwei verschiedene Weisen funktioniert: 1. Es gibt acht Ausgänge, die bei Berührung der Tasten 1 bis 8 jeweils auf HIGH geschaltet werden. 2. Und es gibt einen seriellen Ausgang mit zwei Leitungen SCL und SDO. 

Anmerkungen zu 1. Die „positive Logik“ (active HIGH) müssen wir in der Schaltung und im Sketch berücksichtigen (s.u.). Und wir können definitiv maximal acht Touchpads benutzen.

Anmerkungen zu 2. Es handelt sich bei den zwei Leitungen trotz der Namensähnlichkeit ausdrücklich nicht um eine I2C-Schnittstelle. Deshalb kann die im Bibliotheksverwalter der Arduino IDE angezeigte Bibliothek TTP229 von Alexander Kiryanenko nicht verwendet werden. Es gibt eine geeignete Bibliothek auf der Produktseite unter Downloads.

Allgemeine Anmerkungen: Mehrere Optionen sind mit Jumpern an weiteren - nicht mit Pins versehenen - Kontakten einstellbar. Die default-Werte für „single touch“ und Begrenzung auf die ersten acht Touchpads sind richtig für unser Projekt. Die Spannungsversorgung ist für alle Mikro Controller unkritisch, sowohl 3,3 Volt als auch 5V sind möglich. Mehr dazu weiter unten.

Wenn Sie wie ich nur maximal vier Relais schalten wollen, empfehle ich die Benutzung der digitalen Ausgänge OUT1 bis OUT4, also 2 Leitungen für die Spannungsversorgung und vier Leitungen zu digitalen Eingängen am Micro Controller, keine Jumper und keine Programm-Bibliothek.

Zusätzlich zur Verbindung mit OUT1 bis OUT4 müssen wir sogenannte Pulldown-Widerstände zwischen den Eingängen und GND schalten, damit wir stets einen definierten Zustand haben. Wenn das jeweilige Touchpad berührt wird, ist der Eingang HIGH, nach dem Loslassen wieder LOW. 

Im Sketch für die Taster müssen nur zwei Zeilen geändert werden:

In Zeile 21 wird der pinMode anstelle von INPUT_PULLUP wie folgt gesetzt:

 pinMode(inputPins[i],INPUT);

Und in Zeile 43 wird abgefragt, ob der Eingang HIGH geschaltet ist:

  if (buttonStatus[i] == HIGH)   {

Ich persönlich finde, dass die „positive Logik“ leichter verständlich ist. Leider kennen die Arduinos als pinMode nur OUTPUT, INPUT und INPUT_PULLUP (mit internen PULLUP-Widerständen). Deshalb sind dafür wie oben beschrieben externe Pulldown-Widerstände erforderlich. Es gibt aber auch den Micro Controller ESP32, der den pinMode INPUT_PULLDOWN versteht (also interne Pulldown-Widerstände hat).

Der Hersteller des Moduls hat jedoch auch die Möglichkeit der negativen Logik eingebaut, also OUT1 bis OUT8 bekommen bei Berührung GND-Potential. Dafür müssen wir jedoch zum Lötkolben greifen und die zusätzlichen Pin-Leisten (nicht im Lieferumfang) einlöten. Wenn wir schon mal dabei sind: hier die Beschreibung der wichtigsten Optionen:

TP0

8 output pins – CMOS output active LOW

Jumper gesetzt

TP0

1

8 output pins – CMOS output active HIGH

Default

TP2

0

16 channel mode (16 input keys)

Jumper gesetzt, nur 2-wire

TP2

1

8 channel mode (8 input keys)

Default, 2-wire oder OUT

TP3 und TP4

0, 0

All multi-keys

Beide Jumper gesetzt

TP3 und TP4

1, 1

All single-keys

Default


Also: Wer die negative Logik (active LOW) an den digitalen OUT-Pins haben möchte, muss den Jumper auf TP0, jedoch keinen Jumper bei TP2 setzen. Änderungen der Konfiguration benötigen einen Neustart des Moduls. 

Auch wenn ich mehrere Optionen getestet habe: Die Default-Werte (alle Verbindungen offen, kein Löten erforderlich) sind für unser Projekt mit vier oder acht Relais gut geeignet.

Nun wird es noch einmal schwieriger. Aber es lohnt sich! Nur zwei Datenleitungen (plus die Stromversorgung) für acht oder sogar sechzehn Touchpads. Wie oben beschrieben, handelt es sich nicht um eine I2C-Schnittstelle. Wir können also normale digitale Pins für SCL und SDO verwenden. Aber das Auslesen der Daten erfordert eine bestimmte Bibliothek.

Dazu laden wir von der Produktseite des TTP229 16-Channel Digitaler Touch Kapazitiver Sensor Modul in der Spalte „Wichtige Downloads & Links“ die Arduino Libraries herunter. 

Benötigt wird die Datei TTP229.zip mit folgendem Inhalt:

Diese zip-Datei wird in den Unterordner \Arduino\libraries verschoben und dann im Menü Sketch/Bibliothek einbinden/.ZIP-Bibliothek hinzufügen… eingebunden. Damit stehen auch zwei Beispielsketche zur Verfügung: Calculator und KeyToSerial. Der erste Sketch zeigt den „multi-keys mode“, also Möglichkeit zum Drücken mehrerer Touchpads gleichzeitig, der zweite Sketch zeigt den single-key mode, also nur ein Touchpad zur Zeit. Beide Sketche benutzen den Anschluss 2-wire, also SCL und SDO.

Zurück zu unserem Projekt mit Funkfernsteuerung von vier oder acht Relais, wir verbinden nun SCL mit Pin D2 und SDO mit Pin D3 (frei wählbar).

Bei meinem Sketch (Download) habe ich die switch – case -Verzweigung gewählt, weil ich mit der Exponential-Funktion pow() durch unterschiedliche Datentypen und Rundungsfehler absurde Ergebnisse erhalten hatte. Einzige Stolperfalle: Die Keypads haben die Bezeichnungen 1 bis 8, die Wertigkeiten liegen jedoch bei 2 hoch 0 bis 2 hoch 7, also immer eins niedriger als die Zahl auf dem Keypad. Der Sketch auf der Empfängerseite bleibt unverändert, es sei denn, Sie möchten acht Relais schalten.

Das war’s. Eigentlich nicht schwer, wenn wir uns nicht mit negativer Logik (active LOW) oder Pulldown-Widerständen hätten herumquälen müssen. Viel Spaß beim Nachbauen.

Voor arduinoProjecten voor beginners

1 Kommentar

 TOMMERAY

TOMMERAY

Merci, du matériel proposé avec explications en français et le sketch qui va avec. Un pas en avant, c’est parfait.

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert

Aanbevolen blog berichten

  1. Installeer ESP32 nu van de raad van bestuur
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP Programmeren via Wi-Fi