Relais fernschalten mit nRF24L01

After Andreas Wolter "Santa Detector" having added two nRF24L01 transceivers to receive the sensor signals in another room, the two modules were on my table, ready for a new project. Haven't I wanted to switch different light circuits on my model railway system with relays for a long time? The micro controller with the radio receiver and the relays hidden somewhere under the plate, the transmitter at hand next to the control panels.

In the first option I use switches, in the second option buttons or a capacitive touchpad to turn on and off the relays.

Used hardware

Number Hardware components
1 Micro Controller with ATmega 328
1 4-speed or 8-speed relays
2 2.4MHz Transceiver nRF24L01 (optional Breadboard Adapter)
1 Micro Controller Nano V3.0
1 "Mouse piano" (dip switch) or 4-8 switches
alternative 4-8 Buttons
alternative TTP229 16-Channel Digital Touch Capacitive Sensor Module
Half-Breadboard and jumper cables

 

Preliminary considerations for signal transmission

For secure data transmission, it makes sense to select a unique code for the desired switching states. To an arbitrarily chosen base code of 4000, I add the power of two of the desired relay in each case. As always with programming, counting starts at 0 and ends at 3 for four relays or at 7 for eight relays.

Example: Relays 0, 2 and 7 are to be switched, so 4000 + 2 high 0 + 2 high 2 + 2 high 7 results in a code of 4000 + 1 + 4 + 128 = 4133. When the second relay is then switched off, the code changes to 4129. A small table on the valency of the relays (= powers of two):

n

0

1

2

3

4

5

6

7

2 high n

1

2

4

8

16

32

64

128


However, in our circuit we use negative logic, i.e. because of the internal pull-up resistors (see below), the switched-off state is 1, when turned on, we connect the pin to GND and the state becomes 0. In this case, we subtract the respective value from 4015 (for four switches, otherwise 4255), so code 4015 means: all 4 switches off, code 4000 means all switches on.

To evaluate the code at the receiver, we first subtract the arbitrarily selected 4000; the remaining value is between 0 (all ON) and 15 (four OFF) or 255 (eight OFF). With my 4-way relay, the negative logic helps me, because the individual relays are energized when the respective input is connected to GND. Please pay attention to what kind of relay you want to use and in what condition it is energized. The topic of "negative logic" I pick up below open up again.

For the further procedure, a small for-loop with the function will help bitRead().

at the beginning of the sketch:

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

in the loop() function:

 for (i = 0; i < 4; i++) {
         BitArray[i] = bitRead(var, i);            //Variable var stands for the corrected code

At the end, BitArray[i] shows the switching state 0 or 1 for each relay.

Integration of the transceivers in both sketches

First, the required program libraries are integrated at the beginning of the sketch:

 /* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include
 #include
 #include
 RF24 radio(9, 10);                                   // CE, CSN, MOSI=11, MISO=12, SCK=13
 const byte address[6] = "Code8";       // freely selectable address of the transceivers

The function void setup() then initializes:

    radio.begin();
    radio.openWritingPipe(address);
    radio.setPALevel(RF24_PA_MIN);
    radio.stopListening();                        // at the transmitter

or.:

  radio.startListening();                       // the recipient

In the sketch of the sender I define a function sendcode:

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

For the receiver, the void loop() function starts with

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

The easiest part is basically the query of the switches: set pin numbers, set them as inputs in the setup and query the states in the loop (loop). In order to avoid unnecessary resistors, I opt for the built-in pull-up resistors; this means negative logic (see above), the pin is switched to GND. And due to the large number of switches, I opt for arrays with the pin numbers and switching states.

The circuit for the transmitter with four switches

Instead of 4 or 8 individual switches, I use a "mouse piano". What is this, the younger ones ask. That's eight miniature switches in a row. Widely used on the computer motherboards of the 1990s to determine the respective configuration of the PC.

Picture and schematic

The sketch for the transmitter with four switches (Download):

 /*
 * Arduino Wireless Communication
 * Transmitter Code for 4 relays
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include
 #include
 #include
 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

The circuit for the receiver with four relays

Picture and schematic

The sketch for the receiver with four relays (Download):

 /*
 * Arduino Wireless Communication
 * Receiver Code for 4 relays
 *
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
 #include
 #include
 #include
 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("The code is ");
       Serial.println(code-4000);
       var = code-4000;
       Serial.println(var,AM);
       int i = 0;
       for (i = 0; i < 4; i++) {
         BitArray[i] = bitRead(var, i);
         Serial.print("Switch ");
         Serial.print(i+1);    
         Serial.print(" shall ");
         Serial.println(BitArray[i]);
         digitalWrite(outputPins[i],BitArray[i]);  
        }
      }
    }
  }   //end void loop

And now the whole thing again with buttons or the capacitive touchpad:

Not everyone has such a mouse piano or switch. But buttons (button) can be found at every maker or amateur electronics technician. However, when using pushbuttons, we need to adjust the skits in order to turn on or off a relay at the touch of a button in each case. (Who wants to hold down the button all the time?).

We need three variables for each button (each relay at the end of the radio link):

  1. the status we want to send
  2. the previous status
  3. the current state of our pushbutton

For all input signals we use arrays again:

 int StatusPins[4]={0,0,0,0};
 int Load Status Pins[4]={0,0,0,0};
 int buttonStatus[4]={0,0,0,0};

In the void loop(), we query all buttons one by one in a for loop and compare them with the previous state. If these are unequal and the button is LOW again, the sent status is inverted. Finally, the variable is updated for the previous state.

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

Here is the sketch for Download.

If you do not like the fact that when you first turn on all the relays are turned on (we remember - "negative logic"), you can make a small change in the sketch of the receiver:

We change line 35 to:

 var = 15 - (code-4000);        // for 8 relays 255 - ( )

This again applies to my 4-way relay, in which the inputs must be "grounded" for switching on.

"Touch" instead of "push":

There is a variety of buttons that are mechanically and electrically almost indestructible: touch sensors that work on the principle of changing capacitance.

In the following I use the TTP229 16-Channel Digital Touch Capacitive Sensor Module, which works in two different ways: 1. There are eight outputs, which are switched to HIGH when the buttons 1 to 8 are touched. 2. And there is a serial output with two lines SCL and SDO.

Notes on 1. We have to take the "positive logic" (active HIGH) into account in the circuit and in the sketch (see below). And we can definitely use a maximum of eight touchpads.

Comments on 2. Despite the similarity of names, the two lines are expressly not an I2C interface. Therefore, the TTP229 library of Alexander Kiryanenko, displayed in the library manager of the Arduino IDE, can be not be used. There is a suitable library on the product page under Downloads.

General remarks: Several options can be adjusted with jumpers at further contacts-not with pins. The default values for "single touch" and the limit on the first eight touchpads are correct for our project. The voltage supply is not critical for all micro-controllers, both 3.3 volts and 5V are possible. More about this further down.

If you want to switch only a maximum of four relays, I recommend the use of the digital outputs OUT1 to OUT4, i.e. 2 lines for the power supply and four lines to digital inputs on the micro controller, no jumper and no program library.

In addition to the connection with OUT1 to OUT4, we have to switch so-called pull-down resistors between the inputs and GND, so that we always have a defined state. When the respective touchpad is touched, the HIGH input, after releasing, is again LOW.

Only two lines have to be changed in the button sketch:

In line 21, the pinMode instead of INPUT_PULLUP is set as follows:

 pinMode(inputPins[I],INPUT);

And in line 43, it is queried whether the HIGH input is switched:

  if (buttonStatus[I] == HIGH)   {

I personally find that the "positive logic" is easier to understand. Unfortunately, the Arduinos know as pinMode only OUTPUT, INPUT and INPUT_PULLUP (with internal PULLUP resistances). Therefore, external pull-down resistors are required as described above. However, there is also the micro controller ESP32, which understands the pinMode INPUT_PULLDOWN (i.e. has internal pull-down resistors).

However, the manufacturer of the module has also incorporated the possibility of negative logic, that is, OUT1 to OUT8 get GND potential when touched. For this, however, we have to reach the soldering iron and solder the additional pin strips (not included in the scope of delivery). If we are already here, here is the description of the most important options:

TP0

8 output pins-CMOS output active LOW

Jumper set

TP0

1

8 output pins-CMOS output active HIGH

Default

TP2

0

16 channel mode (16 input keys)

Jumper set, only 2-wire

TP2

1

8 channel mode (8 input keys)

Default, 2-wire or OUT

TP3 and TP4

0, 0

All multi-keys

Both Jumpers set

TP3 and TP4

1, 1

All single-keys

Default


So, if you want to have the negative logic (active LOW) on the digital OUT-pins, you have to put the jumper on TP0, but not a jumper on TP2. Changes to the configuration require a restart of the module.

Even though I have tested several options: The default values (all connections open, no soldering required) are well suited for our project with four or eight relays.

Now it will be more difficult. But it's worth it! Only two data lines (plus the power supply) for eight or even sixteen touchpads. As described above, it is not to an I2C interface. So we can use normal digital pins for SCL and SDO. But reading out the data requires a specific library.

For this, we invite you from the product page of the TTP229 16-Channel Digital Touch Capacitive Sensor Module in the column "Important Downloads & Links" Arduino Libraries .

The TTP229.zip file is required with the following content:

This zip file will be placed in the subfolder \Arduino\libraries moved and then in the menu Federate sketch/library/.Add ZIP Library ... involved. There are also two sample scetches available: Calculator and KeyToSerial. The first sketch shows the "multi-keys mode", that is, the possibility to push several touchpads simultaneously, the second sketch shows the single-key mode, that is, only a touchpad at the moment. Both sketches use the connector 2-wire, that is, SCL and SDO.

Back to our project with radio remote control of four or eight relays, we now connect SCL with pin D2 and SDO with pin D3 (freely selectable).

On my sketch (Download) I chose the switch-case branch because with the exponential function pow () I had obtained absurd results due to different data types and rounding errors. Only Stolperfalle: The Keypads have the designations 1 to 8, but the weights are 2 high 0 to 2 high 7, so always one lower than the number on the Keypad. The sketch on the receiver side will remain unchanged unless you want to switch eight relays.

That's it. Not really hard if we didn't have to have to torment ourselves with negative logic (active LOW) or pull-down resistances. Have fun with rebuilding.

For arduinoProjects for beginners

1 comment

 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.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN