Hi Guys,
I am using the standard Moteino to read a custom 17key keypad I made and then transmit the Key pressed to a receiver. Once the receiver receives the code it will drive a relay output. Sounds simple :)
I have written the code for the Keypad and it works great, all buttons are Identified when pressed.
I am using the keypad.h library for this.
As a test to make sure it would transmit and be received before I went any further I used this simple code on a 1 second delay. It worked great and the receiver board received the commands every second. So I know all my other settings are correct.
if (radio.sendWithRetry(RECEIVER, "H", 1)) //target node Id, message as string or byte array, message length
{
Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks
Serial.println("Marker C Sent Ack"); Serial.println("Command Transmitted");
}
Here is my Loop function that is not working. When I press the 'H' button it does not transmit.
Is there some rule to say I can not do this within the Switch Case?
If I remove the sendwithretry and put a simple Serial.println("Marker H Pressed"); then it works every time so the Switch condition is working.
But as soon as I put the sendwithretry back in it will not transmit. I am sure I am missing something simple here.
Do I need to call a function from the Switch Condition? I tried that but couldn't get the button pressed to transfer into the function I made correctly.
I also tried a seperate if condition at the end of the Switch Case looking for the Key pressed and then calling the sendwithretry but no luck.
I may not have written this properly as I am still learning.
Can someone please have a look and let me know what I am doing wrong. I am sure it is something simple I have missed.
void loop() {
char key = kpd.getKey();
if (key) // Check for a valid key.
{
switch (key)
{
case 'H':
if (radio.sendWithRetry(RECEIVER, "H", 1)) //target node Id, message as string or byte array, message length
{
Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks
Serial.println("Marker C Sent Ack"); Serial.println("Command Transmitted");
}
break;
case 'C':
if (radio.sendWithRetry(RECEIVER, "C", 1)) //target node Id, message as string or byte array, message length
{
Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks
Serial.println("Marker C Sent Ack"); Serial.println("Command Transmitted");
}
break;
default:
Serial.println(key); Serial.println(" Transmitted");
}
}
}
UPTDATED: TomWS: enclosed in code blocks
Thank you Tom,
I am new to this so didn't realise you could do that. It makes it much easier.
Yes as soon as a button is pressed it shows instantly in the Serial monitor screen.
With the switch Case commands if 'H' is pressed it will display the 'H' button then there is a break command that puts it back into the loop waiting for another button to be pressed. It doesn't keep displaying 'H' continuously until another is pressed.
Although just to check I might clear the key pressed to make sure.
I will also add a delay at the bottom to give it a chance to transmit the first keypress.
The serial monitor shows everything as if it should work, maybe there is a key bounce that the serial monitor is not picking up causing an instant retransmit.
I know it works otherwise as if I make it really simple and don't put any getkey calls in just a loop with a 1 second delay it transmits without fail.
if (radio.sendWithRetry(RECEIVER, "H", 1)) //target node Id, message as string or byte array, message length
{
Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks
Serial.println("Marker C Sent Ack"); Serial.println("Command Transmitted");
delay(1000);
}
Is there anything else I may have done wrong?
Ignoring your redundant and duplicate (but harmless) .ino.ino naming convention, I suspect that your problem is related to this:
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};
Note that the Moteino radio uses pins: 2, 10, 11, 12, & 13.
Note that the Moteino flash memory uses pins: 8, 11, 12, 13
Note that the Moteino LED uses pin 9.
You can send H's all day long as long as you don't press a key...
Tom
Hi Everyone,
I have a problem now with the receiver. Not sure if I need a new thread or I can use this one.
There are 17 receivers boards that drive there 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? I have attached the transmit and receiver files.
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 is pressed on the remote and this marker is already calling than stop it calling and turn outputsoff
{
Serial.println("Receiver Output is 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 output is 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);
}
*/
}
Ok Cool,
So what I need to do on the transmitter code is
#define RF69_BROADCAST_ADDR 255;
Then in place of:
if (radio.sendWithRetry(RECEIVER, "S", 1));
I use:
radio.send(RECEIVER, "S",1);
This will send to all Nodes on the network and will not ask for an ACK to be sent.
On the Receivers is there any point setting up the #define RF69_BROADCAST_ADDR 255; ? I would guess probably not as they are just receiving?
The Command on the receiver will be the same:
if (radio.receiveDone());
And I can look for the radio data sent the same way as I did before?
if (radio.DATALEN == 1 && radio.DATA[0] == 'S')
Ok Cool,
So what I need to do on the transmitter code is
#define RF69_BROADCAST_ADDR 255;
No. It is already a predefined constant. Have you read the RFM69.h file at all?
Then in place of:
if (radio.sendWithRetry(RECEIVER, "S", 1));
I use:
radio.send(RECEIVER, "S",1);
sigh... no, you would use
radio.send(RF69_BROADCAST_ADDR,"S",1);