wireless keypad with Nordic nRF24L01

Hi Guys,

I’m making a wireless scoreboard for my rugbyteam. I want to change the score wirelessly with an arduino, keypad and a nRF24L01 tranceiver. I’ve used virtual breadboard to test the circuit and the code, and that works, kindof. I only cannot test the wireless interface so i set the output to serial to test. That works.
I can enter 4 digits, and then press * or #, and the arduino sends it to the board encapsulated with exclamation marks (eg. !0230! )
Later on, i want the board to recognize it as 02-30 and feed it to some 7 segment display chips, but that is for later concern.

I’m trying to compile the code for the keypad, but it’s giving me an error when trying to send the data. I’ve picked the code from several places; the example whas sending sensor data over the nRF24L01. Now when i try to send the output i have from the keyboard, i get this error:

keypad.cpp: In function 'void keypadEvent(char)':
keypad:195: error: no matching function for call to 'transmit(String&)'
keypad.cpp:23: note: candidates are: void transmit(float)
keypad.cpp:39: note:                 void transmit(const char*)
keypad:208: error: no matching function for call to 'transmit(String)'
keypad.cpp:23: note: candidates are: void transmit(float)
keypad.cpp:39: note:                 void transmit(const char*)

I think because the function that handles the sending of the data only wants 1 character, but i can be wrong. ( transmit(1); works fine)

Does anyone have clue what i’ve done wrong, and pioint me in the right direction?
Also, if my code could have been written efficenter, i’d like to know, i’m still learning :))

Here is the complete code:

#include <Keypad.h>
#include <SPI.h>
#include <Mirf.h>

String numbers = "";
int i = 0;
int redLedpin = 7;
int greenLedpin = 8;
int power = 3300;

const byte rows = 4; //four rows
const byte cols = 3; //three columns

void transmit( float v)
{
  byte c; 
  char buf[10];

  dtostrf(v,9,3,buf);

  for( int i=0 ; i<8 ; i++ )
  { 
    c = buf[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// sends a string via the nRF24L01
void transmit(const char *string)
{
  byte c; 

  for( int i=0 ; string[i]!=0x00 ; i++ )
  { 
    c = string[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// send a CR/LF sequence via the nRF24L01
void transmitlf(void)
{
  byte c;

  c = '\r';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;

  c = '\n';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;
}



// pulse sequence of the leds: 1 = keypress, 2 != 4 chars, 3 = verzonden, 4 = stroom error, 5 = bijna op
int ledPulse(int x){

  if(x == 1){
    digitalWrite(greenLedpin, HIGH);
    delay(50);
    digitalWrite(greenLedpin, LOW);

  }
  if(x == 2){ // error sequence
    int y = 0;
    while(y < 5){
      digitalWrite(redLedpin, HIGH);
      delay(100);
      digitalWrite(redLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }
  if(x == 3){  //  verzonden
    int y = 0;
    while(y < 5){
      digitalWrite(greenLedpin, HIGH);
      delay(100);
      digitalWrite(greenLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }

  if(x == 4){  //  bijna op
    int y = 0;
    while(y < 4){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }
  if(x == 5){  //  geen stroom
    int y = 0;
    while(y < 1000){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }


  return 1;
}

//char [][] k2 = new char[5][6];  //useless?

char keys[rows][cols] = {  

  {
    '1','2','3'  } 
  ,
  {
    '4','5','6'  } 
  ,
  {
    '7','8','9'  } 
  ,
  {
    '*','0','#'  } 
  ,
};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these pins, 
// eg. ROW0 = Arduino pin2.
byte rowPins[rows] = { 
  0, 1, 2, 3 };

// Connect keypad COL0, COL1 and COL2 to these pins, 
// eg. COL0 = Arduino pin6.
byte colPins[cols] = { 
  6, 5, 4 };

//create a new Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

//#define 13 13 	 //sds	

void setup() {

  Mirf.csnPin = 10;
  Mirf.cePin = 9;
  // init the transceiver
  Mirf.init();

  // we transmit only a single byte each time
  Mirf.payload = 6;

  // selecting a channel which is not too noisy
  Mirf.channel = 2;
  Mirf.config();

  // Set 1MHz data rate
  Mirf.configRegister(RF_SETUP,0x06);

  // Set address - this one must match the 
  // address the receiver is using!
  Mirf.setTADDR((byte *)"TX_01");

  digitalWrite(greenLedpin, HIGH);   // sets the LED on
  Serial.begin(9600);
 keypad.addEventListener(keypadEvent); //add an event listener
}

void loop() 
{
  if(power < 3200 & power > 3100){
    ledPulse(4);
  }
  if(power < 3100){
    ledPulse(5);
  }
  keypad.getKey();


}

//take care of some special events
void keypadEvent(char eKey) {

  switch (eKey) {
  case '*': 
    if(i == 4){
      transmit(numbers);
      numbers = "";
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      numbers = "";
      i = 0;
    }
    break;
  case '#': 
    if(i == 4){
      transmit("!" + numbers + "!");
      numbers = "";
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      numbers = "";
      i = 0;
    }
    break;
  case KEY_RELEASED:
    break;
  default:
    if (eKey != NO_KEY ){
      i++;
      ledPulse(1);
      numbers += eKey;

    }
  } 

}

Thanks in advance guys!

I think because the function that handles the sending of the data only wants 1 character, but i can be wrong.

In this case, you are. The message is telling you that the argument you specified is a String object, and the transmit function can only send string or float. That's string with a lower case a, not String with an upper case s.

Ditch the String object, and use a NULL terminated array of characters (otherwise known as a string).

Hi paul,

Well i tried to figure out what you said, with the strong object, and made the following changes that did compile.
Dont’s have the hardware yet so i cant test it though, does it look good?
Changed the String numbers = ""; with char numbers[1] = "";

my complete sketch:

#include <Keypad.h>
#include <SPI.h>
#include <Mirf.h>

char numbers[1] = "";
int i = 0;
int redLedpin = 7;
int greenLedpin = 8;
int power = 3300;

const byte rows = 4; //four rows
const byte cols = 3; //three columns

void transmit( float v)
{
  byte c; 
  char buf[10];

  dtostrf(v,9,3,buf);

  for( int i=0 ; i<8 ; i++ )
  { 
    c = buf[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// sends a string via the nRF24L01
void transmit(const char *string)
{
  byte c; 

  for( int i=0 ; string[i]!=0x00 ; i++ )
  { 
    c = string[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// send a CR/LF sequence via the nRF24L01
void transmitlf(void)
{
  byte c;

  c = '\r';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;

  c = '\n';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;
}



// pulse sequence of the leds: 1 = keypress, 2 != 4 chars, 3 = verzonden, 4 = stroom error, 5 = bijna op
int ledPulse(int x){

  if(x == 1){
    digitalWrite(greenLedpin, HIGH);
    delay(50);
    digitalWrite(greenLedpin, LOW);

  }
  if(x == 2){ // error sequence
    int y = 0;
    while(y < 5){
      digitalWrite(redLedpin, HIGH);
      delay(100);
      digitalWrite(redLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }
  if(x == 3){  //  verzonden
    int y = 0;
    while(y < 5){
      digitalWrite(greenLedpin, HIGH);
      delay(100);
      digitalWrite(greenLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }

  if(x == 4){  //  bijna op
    int y = 0;
    while(y < 4){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }
  if(x == 5){  //  geen stroom
    int y = 0;
    while(y < 1000){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }


  return 1;
}

//char [][] k2 = new char[5][6];  //useless?

char keys[rows][cols] = {  

  {
    '1','2','3'  } 
  ,
  {
    '4','5','6'  } 
  ,
  {
    '7','8','9'  } 
  ,
  {
    '*','0','#'  } 
  ,
};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these pins, 
// eg. ROW0 = Arduino pin2.
byte rowPins[rows] = { 
  0, 1, 2, 3 };

// Connect keypad COL0, COL1 and COL2 to these pins, 
// eg. COL0 = Arduino pin6.
byte colPins[cols] = { 
  6, 5, 4 };

//create a new Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

//#define 13 13 	 //sds	

void setup() {

  Mirf.csnPin = 10;
  Mirf.cePin = 9;
  // init the transceiver
  Mirf.init();

  // we transmit only a single byte each time
  Mirf.payload = 6;

  // selecting a channel which is not too noisy
  Mirf.channel = 2;
  Mirf.config();

  // Set 1MHz data rate
  Mirf.configRegister(RF_SETUP,0x06);

  // Set address - this one must match the 
  // address the receiver is using!
  Mirf.setTADDR((byte *)"TX_01");

  digitalWrite(greenLedpin, HIGH);   // sets the LED on
  Serial.begin(9600);
 keypad.addEventListener(keypadEvent); //add an event listener
}

void loop() 
{
  if(power < 3200 & power > 3100){
    ledPulse(4);
  }
  if(power < 3100){
    ledPulse(5);
  }
  keypad.getKey();


}

//take care of some special events
void keypadEvent(char eKey) {

  switch (eKey) {
  case '*': 
    if(i == 4){
      transmit(numbers);
      char numbers[1] = "";
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      char numbers[1] = "";
      i = 0;
    }
    break;
  case '#': 
    if(i == 4){
      transmit(numbers[1]);
      char numbers[1] = "";
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      char numbers[1] = "";
      i = 0;
    }
    break;
  case KEY_RELEASED:
    break;
  default:
    if (eKey != NO_KEY ){
      i++;
      ledPulse(1);
      numbers[1] += eKey;

    }
  } 

}

does it look good?

No. The array for the characters is sized to hold one character. It needs to be sized to hold as many characters as would reasonably be entered.

char numbers[16];

It does not need to be initialized, because the compiler does that for you.

You also need an index into the array, to define where to store the next character;

byte index = 0;
      transmit(numbers);
      char numbers[1] = "";

Creating a new, one element array, after dealing with the current array is pointless. After the array is sent, reset index and null the existing global array.

index = 0; numbers[index] = '\0';

This, too, is wrong.

      numbers[1] += eKey;

It should be:

numbers[index] = aKey;
index++;
numbers[index] = '\0';

Okay this is getting far to complex for me, why cant i just have a variable to store the numbers of the keypad in?
Is it the way the transmitter wants it’s data?

Well i’ve tried to understand what you said and modified my code. it compiles, though.

#include <Keypad.h>
#include <SPI.h>
#include <Mirf.h>

int i = 0;
int redLedpin = 7;
int greenLedpin = 8;
int power = 3300;
byte index = 0;
char numbers[6];

const byte rows = 4; //four rows
const byte cols = 3; //three columns

void transmit( float v)
{
  byte c; 
  char buf[10];

  dtostrf(v,9,3,buf);

  for( int i=0 ; i<8 ; i++ )
  { 
    c = buf[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// sends a string via the nRF24L01
void transmit(const char *string)
{
  byte c; 

  for( int i=0 ; string[i]!=0x00 ; i++ )
  { 
    c = string[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// send a CR/LF sequence via the nRF24L01
void transmitlf(void)
{
  byte c;

  c = '\r';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;

  c = '\n';
  Mirf.send(&c);
  while( Mirf.isSending() ) ;
}



// pulse sequence of the leds: 1 = keypress, 2 != 4 chars, 3 = verzonden, 4 = stroom error, 5 = bijna op
int ledPulse(int x){

  if(x == 1){
    digitalWrite(greenLedpin, HIGH);
    delay(50);
    digitalWrite(greenLedpin, LOW);

  }
  if(x == 2){ // error sequence
    int y = 0;
    while(y < 5){
      digitalWrite(redLedpin, HIGH);
      delay(100);
      digitalWrite(redLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }
  if(x == 3){  //  verzonden
    int y = 0;
    while(y < 5){
      digitalWrite(greenLedpin, HIGH);
      delay(100);
      digitalWrite(greenLedpin, LOW);
      delay(100);
      y++;
    }
    y = 0;
  }

  if(x == 4){  //  bijna op
    int y = 0;
    while(y < 4){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }
  if(x == 5){  //  geen stroom
    int y = 0;
    while(y < 1000){
      digitalWrite(redLedpin, HIGH);
      delay(50);
      digitalWrite(redLedpin, LOW);
      delay(50);
      y++;
    }
    y = 0;
  }


  return 1;
}

//char [][] k2 = new char[5][6];  //useless?

char keys[rows][cols] = {  

  {
    '1','2','3'  } 
  ,
  {
    '4','5','6'  } 
  ,
  {
    '7','8','9'  } 
  ,
  {
    '*','0','#'  } 
  ,
};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these pins, 
// eg. ROW0 = Arduino pin2.
byte rowPins[rows] = { 
  0, 1, 2, 3 };

// Connect keypad COL0, COL1 and COL2 to these pins, 
// eg. COL0 = Arduino pin6.
byte colPins[cols] = { 
  6, 5, 4 };

//create a new Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

//#define 13 13 	 //sds	

void setup() {

  Mirf.csnPin = 10;
  Mirf.cePin = 9;
  // init the transceiver
  Mirf.init();

  // we transmit only a single byte each time
  Mirf.payload = 6;

  // selecting a channel which is not too noisy
  Mirf.channel = 2;
  Mirf.config();

  // Set 1MHz data rate
  Mirf.configRegister(RF_SETUP,0x06);

  // Set address - this one must match the 
  // address the receiver is using!
  Mirf.setTADDR((byte *)"TX_01");

  digitalWrite(greenLedpin, HIGH);   // sets the LED on
  Serial.begin(9600);
 keypad.addEventListener(keypadEvent); //add an event listener
}

void loop() 
{
  if(power < 3200 & power > 3100){
    ledPulse(4);
  }
  if(power < 3100){
    ledPulse(5);
  }
  keypad.getKey();


}

//take care of some special events
void keypadEvent(char eKey) {

  switch (eKey) {
  case '*': 
    if(i == 4){
      transmit(numbers);
      index = 0;
      numbers[index] = '\0';
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      index = 0;
      numbers[index] = '\0';
      i = 0;
    }
    break;
  case '#': 
    if(i == 4){
      transmit(numbers);
      index = 0;
      numbers[index] = '\0';
      ledPulse(3);
      i = 0;
    } 
    else if(i != 4){
      ledPulse(2);
      index = 0;
      numbers[index] = '\0';
      i = 0;
    }
    break;
  case KEY_RELEASED:
    break;
  default:
    if (eKey != NO_KEY ){
      i++;
      ledPulse(1);
      //numbers[1] += eKey;
      numbers[index] = eKey;
      index++;
      numbers[index] = '\0';
    }
  } 

}