rf24 board buttons

Hello,

I'm trying to make a light switch based on the rf24 transceiver and I'm using an ethernet board to control the lights over ethernet, and everything 'till now works like a charm, but I would like to have a couple of buttons on the receiver board to have the posibility of controlling the lights from the light switch.

What I've done so far was using the led_board sketch from the iBoardRF24 and adding the debounce sketch for dealing with the buttons. The problem with this is that by changing the code I'm now controlling the lights only from the buttons and nothing else happens when I send the commands from the remote board.

The code used is as follows:

/*
 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
 Modified by Andy Karpov <andy.karpov@gmail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Example LED Remote
 *
 * This is an example of how to use the RF24 class to control a remote
 * bank of LED's using buttons on a remote control.
 *
 * On the 'remote', connect any number of buttons or switches from
 * an arduino pin to ground.  Update 'button_pins' to reflect the
 * pins used.
 *
 * On the 'led' board, connect the same number of LED's from an
 * arduino pin to a resistor to ground.  Update 'led_pins' to reflect
 * the pins used.  Also connect a separate pin to ground and change
 * the 'role_pin'.  This tells the sketch it's running on the LED board.
 *
 * Every time the buttons change on the remote, the entire state of
 * buttons is send to the led board, which displays the state.
 */

#include <SPI.h>
#include <digitalWriteFast.h>
#include "iBoardRF24.h"
#include "printf.h"

//
// Hardware configuration
//


// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin1 = 7;    // the number of the pushbutton pin
const int buttonPin2 = 8;    // the number of the pushbutton pin
const int ledPin1 = A3;      // the number of the LED pin
const int ledPin2 = A5;      // the number of the LED pin

// Variables will change:
int ledState1 = HIGH;         // the current state of the output pin
int buttonState1;             // the current reading from the input pin
int lastButtonState1 = LOW;   // the previous reading from the input pin
int ledState2 = HIGH;         // the current state of the output pin
int buttonState2;             // the current reading from the input pin
int lastButtonState2 = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers




// Set up nRF24L01 radio on iBoard
iBoardRF24 radio(9, 10, 11, 12, 13, 4);

// sets the role of this unit in hardware.  Connect to GND to be the 'led' board receiver
// Leave open to be the 'remote' transmitter
const int role_pin = A4; // (A0)

// Pins on the remote for buttons (A1 - A6)
const uint8_t button_pins[] = { A3,A5 };
const uint8_t num_button_pins = sizeof(button_pins);

// Pins on the LED board for LED's (A1 - A6)
const uint8_t led_pins[] = { A3,A5 };
const uint8_t num_led_pins = sizeof(led_pins);


//
// Topology
//

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

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes in this
// system.  Doing so greatly simplifies testing.  The hardware itself specifies
// which node it is.
//
// This is done through the role_pin
//

// The various roles supported by this sketch
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"};

// The role of the current running sketch
role_e role;

//
// Payload
//

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

//
// Setup
//

void setup(void)
{
 

  //
  // Role
  //

  // set up the role pin
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin,LOW);
  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;

  //
  // Print preamble
  //

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

  //
  // Setup and configure rf radio
  //

  radio.begin();

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens a single pipes for these two nodes to communicate
  // back and forth.  One listens on it, the other talks to it.

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

  //
  // Start listening
  //

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

  //
  // Dump the configuration of the rf unit for debugging
  //

  radio.printDetails();

  //
  // Set up buttons / LED's
  //

  // Set pull-up resistors for all buttons
  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(button_pins[i],OUTPUT);
      led_states[i] = HIGH;
      digitalWrite(led_pins[i],led_states[i]);
    }
  }

  pinMode(buttonPin1, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(ledPin2, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin1, ledState1);
  digitalWrite(ledPin2, ledState2);
  
  
}

//
// Loop
//

void loop(void)
{

  //
  // LED role.  Receive the state of all buttons, and reflect that in the LEDs
  //

  if ( role == role_led )
  {
    // if there is data ready
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( button_states, num_button_pins );

        // Spew it
        printf("Got buttons\n\r");

        // For each button, if the button now on, then toggle the LED
        int i = num_led_pins;
        while(i--)
        {
          if ( button_states[i] )
          {
            led_states[i] ^= HIGH;
            digitalWrite(led_pins[i],led_states[i]);
          }
        }
      }
    }
  }

	
// read the state of the switch into a local variable:
  int reading1 = digitalRead(buttonPin1);
  int reading2 = digitalRead(buttonPin2);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading1 != lastButtonState1) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if (reading2 != lastButtonState2) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading1 != buttonState1) {
      buttonState1 = reading1;

      // only toggle the LED if the new button state is HIGH
      if (buttonState1 == HIGH) {
        ledState1 = !ledState1;
      }
    }
  }
  
    if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading2 != buttonState2) {
      buttonState2 = reading2;

      // only toggle the LED if the new button state is HIGH
      if (buttonState2 == HIGH) {
        ledState2 = !ledState2;
      }
    }
  }
  
  // set the LED:
  digitalWrite(ledPin1, ledState1);
  digitalWrite(ledPin2, ledState2);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState1 = reading1;
  lastButtonState2 = reading2;

 
}

Can anyone help me with this issue?

Thank you!

The code at lines 211,212 sets output pins ledPin1 and ledPin2 to the values ledState1 and ledState2 which are changed to reflect switch inputs but do not seem to be updated to reflect radio commands. Even if the radio commands were actioned correctly, the code at lines 211,212 would immediately override them with the most recent states read from the switch inputs.

I suspect this would work properly if you eliminated ledPin1, ledPin2, ledState1 and ledState2 and used led_pins[] and led_states[] instead.

By the way, you are using the same variable lastDebounceTime to debounce both buttons, which doesn't seem right. If you really want to use a single timer for both buttons, the two checks at lines 277, 292 could be merged. If you want to use a separate debounce timer for each input (which would seem more sensible) then it would make sense to store these in an array for consistency with the way you're managing the other pin numbers and states. I would also replace the other numbered variables with arrays. Then you can get rid of the duplicated code and process all inputs and all outputs in a FOR loop.

Thx for the input!