Getting a Keypress to Transmit to Receiver

Hi Everyone,
I am fairly new to Arduino so have some question please about a project I am working on.
I have built a 17 button remote to use with a Moteino Board.
Plan is when a button is pressed on the remote the Moteino board will transmit the key letter that was pressed to the receiver. The receiver then checks the letter transmitted and will carry out a function.
I have the receiver working fine but the transmitter has me a little stumped.

I have written code using Switch Case statements to identify the keypress and it works perfectly.
I then want to transmit the key letter that was pressed and then the program will wait for the next key.
When I put the transmit code into the Case statement it doesn’t send it.

As a test I removed all Case statements and just put only the transmit code line in the loop function with a 1 second delay. When I do that the transmitter sends the signal and it is received by the receiver and processed correctly.

I am missing something in the Case Statement. I know if statements should work inside a case statement but at the moment what I have done does not work I am can not see why.

See the code below. In this code I am only transmitting code when button ‘H’ is pressed.
Can anyone see what I have done wrong. I am sure it is something simple.
I have used serial print line commands so I can watch the serial monitor to see where it gets stuck.
So When ‘H’ is pressed the serial monitor displays: “H Pressed”, then “500ms Delay” and nothing after that. That is where it gets stuck.

Can anyone see what I have done wrong?

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <LowPower.h> //get library from: https://github.com/lowpowerlab/lowpower
#include <Keypad.h>

const byte ROWS = 7; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'0', 'A', '0'},
  {'K', 'D', 'F'},
  {'V', 'L', 'P'},
  {'E', 'X', 'B'},
  {'S', 'I', 'R'},
  {'H', 'G', 'M'},
  {'0', 'C', '0'},

};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = {11, 10, 9, 8, 7, 6, 5};
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = {2, 3, 4};

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NETWORKID     100  //the same on all nodes that talk to each other
#define RECEIVER      1    //unique ID of the gateway/receiver
#define SENDER        2
#define NODEID        SENDER  //change to "SENDER" if this is the sender node (the one with the button)

#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Remove/comment if you have RFM69W!
//*********************************************************************************************
#define SERIAL_BAUD   115200
#define LED           9 // Moteinos have LEDs on D9
#define BUTTON_INT    1 //user button on interrupt 1 (D3)
#define BUTTON_PIN    3 //user button on interrupt 1 (D3)

#define LED_GREEN       4 //GREEN LED on the SENDER
#define LED_RED         5 //RED LED on the SENDER
#define RX_TOGGLE_PIN   7 //GPIO to toggle on the RECEIVER


RFM69 radio;

//int PinOut = 8;           //Pin used for Relay Output  - Not needed on transmitter


void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY == RF69_433MHZ ? 433 : FREQUENCY == RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  Serial.flush();
  //pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  //  attachInterrupt(BUTTON_INT, handleButton, FALLING);

  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(RX_TOGGLE_PIN, OUTPUT);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_RED, HIGH);


}

void loop()  {

  char key = kpd.getKey();
  
  if (key) // Check for a valid key.
  {
    switch (key)
    {
      case 'H':
        Serial.println("H Pressed");
        delay(500);                   //long debounce
        Serial.println("500ms Delay");
        if (radio.sendWithRetry(RECEIVER, "H", 1)) //target node Id, message as string or byte array, message length
        {
         Serial.println("Going to Blink Function");

          Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks
          Serial.println("Blink Function Complete");
          Serial.println("Marker H Sent Ack"); Serial.println("Command Transmitted");
        }
        break;

      case 'S':
        Serial.println("S Pressed");
        break;

      case 'E':
        Serial.println("E Pressed");
        break;

      case 'V':
        Serial.println("V Pressed");
        break;

      case 'K':
        Serial.println("K Pressed");
        break;

      case 'C':
        Serial.println("C Pressed");
        break;

      case 'G':
        Serial.println("G Pressed");
        break;

      case 'I':
        Serial.println("I Pressed");
        break;

      case 'X':
        Serial.println("X Pressed");
        break;

      case 'L':
        Serial.println("L Pressed");
        break;

      case 'D':
        Serial.println("D Pressed");
        break;

      case 'A':
        Serial.println("A Pressed");
        break;

      case 'M':
        Serial.println("M Pressed");
        break;

      case 'R':
        Serial.println("R Pressed");
        break;

      case 'B':
        Serial.println("B Pressed");
        break;

      case 'P':
        Serial.println("P Pressed");
        break;

      case 'F':
        Serial.println("F Pressed");
        break;

    }
  }
}

void Blink(byte PIN, byte DELAY_MS, byte loops)
{
  for (byte i = 0; i < loops; i++)
  {
    digitalWrite(PIN, HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN, LOW);
    delay(DELAY_MS);
  }
}

So When 'H' is pressed the serial monitor displays: "H Pressed", then "500ms Delay" and nothing after that. That is where it gets stuck.

Is it stuck or do you see the messages in the Serial monitor again if you press H again ?

Does

radio.sendWithRetry(RECEIVER, "H", 1);

return true ?

Hi UKHeliBob,

Thanks for your response.

Is it stuck or do you see the messages in the Serial monitor again if you press H again ?

The first time 'H' is pressed it will show "H Pressed" on the Serial Monitor and it locks up for a 20seconds and no other keys can be pressed. Then after the 20 seconds the other buttons can be pressed again. If 'H' is pressed too many times in a row it does lock up completely and needs to be reset to work.

radio.sendWithRetry(RECEIVER, "H", 1);

return true ?

No it doesn't return true it stops there.

Interesting though if all I put into the loop is the following below it will transmit happily every 2 seconds.

void Loop()
{
if(radio.sendWithRetry(RECEIVER,"H",1)
delay(2000);

}

I can't see what I have done wrong.

radio.sendWithRetry(RECEIVER, "H", 1);The function name seems to indicate that it is a blocking function that retries until it succeeds or a timeout occurs.

Yes it will try to send 3 times and if not successful move on.

I have had a play around with it some more today and now it doesn’t get stuck in the routine if the ‘H’ Button is pressed. But it still does not send.

I am at a loss to explain why. Need an experts advice :wink:

I think I have found the problem. I wired my Keypad onto the same pins as the onboard transmitter uses. Therefore if I use a loop with delay and no button presses it works fine. If I use button presses it does not as the button press is interferring with the transmit commands. I need to rewire it to use different pins. Fingers crossed it will fix the problem.

Hi Everyone,
I have the transmitter working great but I have a problem now with the receiver. Not sure if I need a new thread or I can use this one.

In my project there are 17 receivers boards that drive their own single outputs in total for my project, one for each button on the remote.
I have written the code so that after the ‘if (radio.receiveDone())’ statement I then do a check to see if this receiver board has an active output already and if it does turn it off.
So what I am trying to do is… Only one receiver can be active at a time so when any button is pressed the remote the active one will turn off and the receiver specific to the button pressed will turn on. Make sense?

I have the receiver code working some of the time. Most of the time it thinks the board is active when it is not. I have played around with different code options and are not getting very far.

There must be a better way to do this. Has anyone got any ideas?
Is there a better way to do this?

#include <RFM69.h>
#include <SPI.h>
#include <LowPower.h>

//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NETWORKID     100  //the same on all nodes that talk to each other
#define RECEIVER      1    //unique ID of the gateway/receiver
#define SENDER        2
#define NODEID        RECEIVER  //change to "SENDER" if this is the sender node (the one with the button)

#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Remove/comment if you have RFM69W!
//*********************************************************************************************
#define SERIAL_BAUD   115200
#define LED           9 // Moteinos have LEDs on D9
#define BUTTON_INT    1 //user button on interrupt 1 (D3)
#define BUTTON_PIN    3 //user button on interrupt 1 (D3)


RFM69 radio;

int Announce = 8;           //Pin used for Relay Output

void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY == RF69_433MHZ ? 433 : FREQUENCY == RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  Serial.flush();
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED, OUTPUT);

  // initialize digital pin 4 as an Output to drive the relay to control Turn the Flood Lights on/off
  pinMode(8, OUTPUT);
  digitalWrite(Announce, LOW);
}

byte LEDSTATE = LOW; //LOW=0
byte Delay = LOW;

void loop() {

  //Receive Signal
  //check if something was received (could be an interrupt from the radio)


  if (radio.receiveDone())    //if radio has received a signal check what it is
  {
    delay(200);
    //print message received to serial
    Serial.print('['); Serial.print(radio.SENDERID); Serial.print("] ");
    Serial.print((char*)radio.DATA);
    Serial.print("   [RX_RSSI:"); Serial.print(radio.RSSI); Serial.print("]");
    Serial.println();

    if (radio.DATALEN == 1 && radio.DATA[0] =='Q' && LEDSTATE == HIGH);   // If any button has been on the remote and this marker is already calling than stop it calling.
    {
      Serial.println("Receiver Output Activated so Turning off Outputs");
      LEDSTATE = LOW;
      digitalWrite(LED, LEDSTATE);
      Serial.print("LED State =    ");Serial.print(LEDSTATE);
      Serial.println();
      digitalWrite(Announce, LEDSTATE);           // Set Output Low
      radio.DATA[0] = 'U';                       //Set the DATA to a random letter like U to make sure of no false triggers
      Delay = LOW;
    }
  }
  //Exit out of if routine
  else
  {

  }

  //This section to looks for the Marker Letter for this Marker.
  //check if received message is 2 bytes long, and check if the message is specifically "H"

  if (radio.DATALEN == 1 && radio.DATA[0] == 'S' && LEDSTATE == LOW)
  {
    Serial.println("Receiver Board not Activated yet so turning on Outputs");
    LEDSTATE = HIGH;
    Delay = HIGH;                                                 //Activate Delay sequence until a button is pressed
    digitalWrite(Announce, HIGH);
    digitalWrite(LED, LEDSTATE);
    Serial.print("LEDSTATE Value:"); Serial.print(LEDSTATE);
    Serial.println();
    radio.DATALEN = 0;
    radio.DATA == 'Q';
  
  }

  //check if sender wanted an ACK
  if (radio.ACKRequested())
  {
    radio.sendACK();
    Serial.println(" - ACK sent");

  }


  radio.receiveDone(); //put radio in RX mode
  Serial.flush(); //make sure all serial data is clocked out before sleeping the MCU


/*  if (Delay == HIGH)
  {
    Serial.println(" entering Delay of 0.1 seconds");
    digitalWrite(Announce, LOW);
    delay(250);
    digitalWrite(Announce, HIGH);
  }
*/
}