Help on adapting software

Hi!

I am a total newbie regarding anything arduino or coding, but i'm learning.

I'm having a problem with this code that i found on Studiopieters site.
I followed the tutorial and everything works but it seems that the code is written in such a way that the receiver toggles the output on or off when the button on the transmitter is pressed.

I would need it to work momentarily - the output should be on only if the button is pressed and off when the button is released.
Can anyone advise what would need to be added or changed in the code?

I am using two arduino nano's with nRF24L01 modules

This is the code that is currently on the reciever and transmitter

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 (CE & CS)

RF24 radio(9, 10);

// sets the role of this unit in hardware.  Connect to GND to be the 'led' board receiver
// Don't connect to be the the 'remote' transmitter
const int role_pin = A4;

// Pins on the remote for buttons
const uint8_t button_pins[] = { 2, 3, 4, 5, 6, 7 };
const uint8_t num_button_pins = sizeof(button_pins);

// Pins on the LED board for LED's
const uint8_t led_pins[] = { 2, 3, 4, 5, 6, 7 };
const uint8_t num_led_pins = sizeof(led_pins);

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;

typedef enum { role_remote = 1, role_led } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Remote", "LED Board"};

role_e role;

uint8_t button_states[num_button_pins];
uint8_t led_states[num_led_pins];

void setup(void)
{
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin, HIGH);
  delay(20); // Just to get a solid reading on the role pin

  // read the address pin, establish our role
  if ( digitalRead(role_pin) )
    role = role_remote;
  else
    role = role_led;

  Serial.begin(115200);
  printf_begin();
  printf("\n\rRF24/examples/led_remote/\n\r");
  printf("ROLE: %s\n\r", role_friendly_name[role]);

  radio.begin();
  radio.setChannel(125);
  radio.setPALevel(RF24_PA_MAX);           // If you want to save power use "RF24_PA_MIN" but keep in mind that reduces the module's range
  radio.setDataRate(RF24_1MBPS);



  if ( role == role_remote )
  {
    radio.openWritingPipe(pipe);
  }
  else
  {
    radio.openReadingPipe(1, pipe);
  }

  if ( role == role_led )
    radio.startListening();

  radio.printDetails();

  if ( role == role_remote )
  {
    int i = num_button_pins;
    while (i--)
    {
      pinMode(button_pins[i], INPUT);
      digitalWrite(button_pins[i], HIGH);
    }
  }

  // Turn LED's ON until we start getting keys
  if ( role == role_led )
  {
    int i = num_led_pins;
    while (i--)
    {
      pinMode(led_pins[i], OUTPUT);
      led_states[i] = HIGH;
      digitalWrite(led_pins[i], led_states[i]);
    }
  }

}

void loop(void)
{

  if ( role == role_remote )
  {
    int i = num_button_pins;
    bool different = false;
    while (i--)
    {
      uint8_t state = ! digitalRead(button_pins[i]);
      if ( state != button_states[i] )
      {
        different = true;
        button_states[i] = state;
      }
    }

    if ( different )
    {
      printf("Now sending...");
      bool ok = radio.write( button_states, num_button_pins );
      if (ok)
        printf("ok\n\r");
      else
        printf("failed\n\r");
    }

    delay(20);
  }

  if ( role == role_led )
  {

    if ( radio.available() )
    {

      while (radio.available())
      {

        radio.read( button_states, num_button_pins );


        printf("Got buttons\n\r");

        int i = num_led_pins;
        while (i--)
        {
          if ( button_states[i] )
          {
            led_states[i] ^= HIGH;
            digitalWrite(led_pins[i], led_states[i]);
          }
        }
      }
    }
  }
}

The button presses at the moment toggle the leds. For example, a single press of button 1 switches led 1 on. The next press switches it off etc. Is that right ?

I suppose there will have to be some persistence to stop the led flashing while between cycles of the transmitter and receiver (say a few hundred milliseconds).

But you could try replacing this:

         if ( button_states[i] )
          {
            led_states[i] ^= HIGH;
            digitalWrite(led_pins[i], led_states[i]);
          }

with just this

          digitalWrite(led_pins[i],  button_states[i] );

to see if it gets you close to what you want.

Hi!

Thank you for your reply.

I have made the changes to the code you recommended and uploaded it to both arduinos, but now the led is constantly on and the button has no effect on the output (although the communication indicator on the receiver blinks when i push the button)

Yes currently this code worked so that when the button was pressed once the led turned on and stayed on untill the button was pressed again.

Before i used the code from Studiopieters i found another site with a different approach to this, code pasted below
Transmitter:

//communication 1 way
//firstly download library https://github.com/nRF24/RF24

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN         
const byte address[6] = "00001"; //Byte of array representing the address. This is the address where we will send the data. This should be same on the receiving side.
int button_pin = 2;
boolean button_state = 0;

void setup() {
pinMode(button_pin, INPUT);
radio.begin();                  //Starting the Wireless communication
radio.openWritingPipe(address); //Setting the address where we will send the data
radio.setPALevel(RF24_PA_MIN);  //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.
radio.stopListening();          //This sets the module as transmitter
}

void loop()
{
button_state = digitalRead(button_pin);
if(button_state == HIGH)
{
const char text[] = "Your Button State is HIGH";
radio.write(&text, sizeof(text));                  //Sending the message to receiver
}
else
{
const char text[] = "Your Button State is LOW";
radio.write(&text, sizeof(text));                  //Sending the message to receiver 
}
radio.write(&button_state, sizeof(button_state));  //Sending the message to receiver 
delay(10);
}

Receiver:

//communication 1 way
//firstly download library https://github.com/nRF24/RF24

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN
const byte address[6] = "00001";
int led_pin = 3;
boolean button_state = 0;

void setup() {
pinMode(led_pin, OUTPUT);
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);   //Setting the address at which we will receive the data
radio.setPALevel(RF24_PA_MIN);       //You can set this as minimum or maximum depending on the distance between the transmitter and receiver.
radio.startListening();              //This sets the module as receiver
}

void loop()
{
if (radio.available())              //Looking for the data.
{
char text[32] = "";                 //Saving the incoming data
radio.read(&text, sizeof(text));    //Reading the data
radio.read(&button_state, sizeof(button_state));    //Reading the data
if(button_state == HIGH)
{
digitalWrite(led_pin, HIGH);
Serial.println(text);
}
else
{
digitalWrite(led_pin, LOW);
Serial.println(text);}
}
delay(5);
}

This code worked exactly as i needed - the led turned on and remained on when i pressed and held the button, turned off when the button was released. But i had issues with false triggering and stability so i abandoned it.

Maybe some insight on my use case would help.
I have a robot arm that has a 360deg rotating head which holds a workpiece, on the head there's a dead man's switch which disconnects a contact if the head looses grip of the workpiece.
If that happens the robot must stop to avoid damage.
As the switch on the rotating head can't be physically connected to the body of the robot this was my idea to wirelessly transfer the dead man's switch to the robot's controller.
The transmitter will be mounted directly on the rotating head and powered with a lithium battery pack.
The receiver will be mounted on the robots body and powered from it.

Previously we used a cheap chinese remote and wireless relay on 433mhz but there was too much interference and the system was notoriusly unstable.

I see that with the code sample I supplied, I did not reset all the LEDs to off when the transmission came to an end. In setup(), all the LEDs are switched on initially.

Anyway, start by changing this message:

printf( "Got buttons\n\r") ;

so it is clear which button was changed and what value it had. Something like :

for ( int i = 0 ; i < num_button_pins ; i++ )  printf( "Got button: %d  value: %d \n\r",  i ,  button_states[i] ) ;

to see if it registers a change in state of the remote button.

You will also have to decide what persistence a button press should have. If there is a momentary break in transmission during the time the button is pressed, after how many milliseconds should the led go off ? If this is period is too short, you may get the problem of the led appearing to flash while other processing is happening. If it is too long, the application may appear unresponsive.

6v6gt:
But you could try replacing this:

         if ( button_states[i] )

{
           led_states[i] ^= HIGH;
           digitalWrite(led_pins[i], led_states[i]);
         }




with just this 



digitalWrite(led_pins[i],  button_states[i] );




to see if it gets you close to what you want.

There is no need to read the button_states into a separate list and then copy the list to led_states. Just read directly into led_states:

   if (role == role_led && radio.available() >= num_led_pins)
  {
    radio.read( led_states, num_led_pins );


    printf("Got led_states\n\r");


    for (int i = 0; i < num_led_pins; i++)
      digitalWrite(led_pins[i], led_states[i]);
  }

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.