I am having troubling getting the manager.sendtoWait and/or manager.recvfromAck functions of the RHReliableDatagram.h library working using two identical RF69 boards, and two Arduino Nanos (using the Serial Monitor). I know there are other libraries but I want to understand what I am doing wrong here please.
I have confirmed my wiring and have a working set of code without using these functions above (no acknowledgements of transmissions), but as soon as I try to use these functions above, I get sendtoWait failed when I try to use manager.sendtoWait, which I know either means the sendtoWait isn't working to produce a proper transmission, or that the recvfromAck isn't working to produce the acknowledgement that sendtoWait is waiting for (hence when it times out after the default number of retries it fails).
Please could someone help. I am just using the example libraries to build up my understanding of the RF69 boards at the moment.
Working Code (Uploaded to both Arduino Nanos using RF69 boards). Using the Serial Monitor I can send and receive messages fine. But without any acknowledgements for those messages.
// rf69 demo tx rx.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client
// with the RH_RF69 class. RH_RF69 class does not provide for addressing
// or reliability, so you should only use RH_RF69 if you do not need the
// higher level messaging abilities.
// It is designed to work with the other example RadioHead69_RawDemo_RX.
// Demonstrates the use of AES encryption, setting the frequency and
// modem configuration.
#include <SPI.h>
#include <RH_RF69.h>
/************ Radio Setup ***************/
// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 434.0
// Arduino Nano
#define RFM69_CS 10 // "B"
#define RFM69_INT 3 // "C"
#define RFM69_RST 2 // "A"
#define LED 5
#define RFM69_IRQN digitalPinToInterrupt(RFM69_INT)
// Singleton instance of the radio driver
RH_RF69 driver(RFM69_CS, RFM69_INT);
int16_t packetnum = 0; // packet counter, we increment per xmission
void setup()
{
Serial.begin(115200);
//while (!Serial) delay(1); // Wait for Serial Console (comment out line if no computer)
pinMode(LED, OUTPUT);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
Serial.println("Feather RFM69 TX Test!");
Serial.println();
// manual reset
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(10);
if (!driver.init())
{
Serial.println("RFM69 radio init failed");
while (1);
}
Serial.println("RFM69 radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
// No encryption
if (!driver.setFrequency(RF69_FREQ))
{
Serial.println("setFrequency failed");
}
// If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
// ishighpowermodule flag set like this:
driver.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
driver.setEncryptionKey(key);
Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz");
}
void loop()
{
//delay(1000); // Wait 1 second between transmits, could also 'sleep' here!
static char sendbuffer[62];
static int sendlength = 0;
// SENDING
// In this section, we'll gather serial characters and
// send them to the other node if we (1) get a carriage return,
// or (2) the buffer is full (61 characters).
// If there is any serial input, add it to the buffer:
if (Serial.available() > 0)
{
char input = Serial.read();
if (input != '\r') // not a carriage return
{
sendbuffer[sendlength] = input;
sendlength++;
}
// If the input is a carriage return, or the buffer is full:
if ((input == '\r') || (sendlength == 61)) // CR or buffer full
{
// Send the packet!
Serial.print("Transmitting [");
for (byte i = 0; i < sendlength; i++)
{
Serial.print(sendbuffer[i]);
}
Serial.println("]");
driver.send((uint8_t *)sendbuffer, strlen(sendbuffer));
driver.waitPacketSent();
sendlength = 0; // reset the packet
}
}
// Now wait for a reply
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (driver.recv(buf, &len))
{
if (!len) return;
buf[len] = 0;
Serial.print("Got a reply: ");
Serial.println((char*)buf);
}
}
Not Working Code (Transmitter Side)
#include <RHReliableDatagram.h>
#include <RH_RF69.h>
#include <SPI.h>
uint8_t CLIENT_ADDRESS = 1;
uint8_t SERVER_ADDRESS = 2;
//For Teensy 3.x and T4.x the following format is required to operate correctly
//This is a limitation of the RadioHead radio drivers
#define RFM69_CS 10 // "B"
#define RFM69_INT 3 // "C"
#define RFM69_RST 2 // "A"
#define RFM69_IRQN digitalPinToInterrupt(RFM69_INT)
// Singleton instance of the radio driver
RH_RF69 driver(RFM69_CS, RFM69_INT);
//----- END TEENSY CONFIG
//RH_RF69 driver(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, CLIENT_ADDRESS);
void setup()
{
Serial.begin(115200);
delay(100);
//For Teensy 3.x and T4.x the following format is required to operate correctly
//pinMode(LED, OUTPUT);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
// manual reset - added for Teensy
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(100);
//----- END TEENSY CONFIG
if (!manager.init())
Serial.println("init failed");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
driver.setFrequency(434.0);
// If you are using a high power RF69, you *must* set a Tx power in the
// range 14 to 20 like this:
driver.setTxPower(20);
}
uint8_t data[] = "Hello World!";
// Dont put this on the stack:
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
void loop()
{
Serial.println("Sending to rf69_reliable_datagram_server");
// Send a message to manager_server
if (manager.sendtoWait(data, sizeof(data), SERVER_ADDRESS))
{
// Now wait for a reply from the server
uint8_t len = sizeof(buf);
uint8_t from;
if (manager.recvfromAckTimeout(buf, &len, 2000, &from))
{
Serial.print("got reply from : 0x");
Serial.print(from, HEX);
Serial.print(": ");
Serial.println((char*)buf);
}
else
{
Serial.println("No reply, is rf69_reliable_datagram_server running?");
}
}
else
Serial.println("sendtoWait failed");
delay(5);
}
Not Working Code (Receiver Side)
#include <RHReliableDatagram.h>
#include <RH_RF69.h>
#include <SPI.h>
uint8_t CLIENT_ADDRESS = 1;
uint8_t SERVER_ADDRESS = 2;
//For Teensy 3.x and T4.x the following format is required to operate correctly
//This is a limitation of the RadioHead radio drivers
#define RFM69_CS 10 // "B"
#define RFM69_INT 3 // "C"
#define RFM69_RST 2 // "A"
#define RFM69_IRQN digitalPinToInterrupt(RFM69_INT)
// Singleton instance of the radio driver
RH_RF69 driver(RFM69_CS, RFM69_INT);
//----- END TEENSY CONFIG
//RH_RF69 driver(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, SERVER_ADDRESS);
void setup()
{
Serial.begin(115200);
delay(100);
//For Teensy 3.x and T4.x the following format is required to operate correctly
//pinMode(LED, OUTPUT);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
// manual reset - added for Teensy
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(100);
//----- END TEENSY CONFIG
if (!manager.init())
Serial.println("init failed");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
driver.setFrequency(434.0);
// If you are using a high power RF69, you *must* set a Tx power in the
// range 14 to 20 like this:
driver.setTxPower(20);
Serial.println("init pass");
}
uint8_t data[] = "And hello back to you";
// Dont put this on the stack:
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
void loop()
{
// Wait for a message addressed to us from the client
uint8_t len = sizeof(buf);
uint8_t from;
if (manager.recvfromAck(buf, &len, &from))
{
Serial.print("got request from : 0x");
Serial.print(from, HEX);
Serial.print(": ");
Serial.println((char*)buf);
// Send a reply back to the originator client
if (!manager.sendtoWait(data, sizeof(data), from))
Serial.println("sendtoWait failed");
}
}