Dear all, hope anyone can shed some light on what's wrong in my code.
My hardware: an Arduino (Pro Mini) with RFM69 module as slave node, and an ESP8266 + RFM69 as master. I've tested this with the server/client example sketches of the RadioHead library and everything works as expected.
What the below sketch is doing:
Send (broadcast) message to find a master to connect to.
Master replies with packet of 8 bytes of data, which includes a.o. the assigned node number and a timestamp (the current time).
Upon uploading this sketch on the Arduino it works perfectly, but after a reset it fails: the reply of the master is received, but I don't get the actual data, it says 0 bytes received.
After lots of time trying and trying I finally narrowed down the problem to line 102:
memcpy(×tamp, data + 2, 4);
If that line is not present, or the number of bytes copied is 2, the code continues to work perfectly after a reset. However when present in this form (which is what it should be - and after the initial upload it does what it should do: I get the correct timestamp) it doesn't work any more after the reset. It is really as if after the reset my code is not what it used to be, somehow somewhere something appears to get changed.
#include <SPI.h>
#include <RH_RF69.h>
#include <RHReliableDatagram.h>
#define CLIENT_ADDRESS 254
enum registrationStates { // Whether this node is registered or not.
REGISTRATION_UNREGISTERED,
REGISTRATION_AWAITING_MASTER_RESPONSE,
REGISTRATION_FAILED,
REGISTRATION_SUCCESS
};
registrationStates registrationState = REGISTRATION_UNREGISTERED;
uint32_t messageSentTime;
uint8_t data[RH_RF69_MAX_MESSAGE_LEN];
bool registered;
uint8_t masterAddress = RH_BROADCAST_ADDRESS; // Address of our registered master - default to broadcast (255).
uint8_t nodeAddress = 254; // Address assigned to us by master - default to 254 (unregistered node).
uint16_t nextAlarm; // When the next alarm will be (in minutes from start of the week).
uint8_t retries;
#define DATA_REQUEST_REGISTRATION 0x50
#define DATA_REGISTRATION_ACCEPTED 0x51
#define DATA_REGISTRATION_FAILED 0x52
RH_RF69 rf69Device(10, 2); // SS, interrupt
RHReliableDatagram rf69(rf69Device, CLIENT_ADDRESS); // (device, address)
void setup() {
Serial.begin(115200);
if (!rf69.init()) {
Serial.println("init failed");
}
if (!rf69Device.setFrequency(868.0)) {
Serial.println("setFrequency failed");
}
uint8_t key[] = "Ha8b44QGfyTlYTt5";
rf69Device.setEncryptionKey(key);
Serial.println();
Serial.println("Init done.");
}
uint32_t lastRegistered;
void loop() {
if (registered == false) {
doRegistration();
}
if (millis() - lastRegistered > 5000) {
lastRegistered = millis();
registered = false;
registrationState = REGISTRATION_UNREGISTERED;
}
}
void doRegistration() {
uint8_t msgLen;
uint8_t msgFrom;
switch (registrationState) {
case REGISTRATION_UNREGISTERED: // Start registration procedure: search master.
data[0] = DATA_REQUEST_REGISTRATION;
Serial.print(F("Attempting to register this node, attempt "));
Serial.println(retries);
rf69.sendtoWait(data, 1, RH_BROADCAST_ADDRESS);
registrationState = REGISTRATION_AWAITING_MASTER_RESPONSE;
messageSentTime = millis();
break;
case REGISTRATION_AWAITING_MASTER_RESPONSE:
// Expected response (8 bytes):
// 0: DATA_REGISTRATION_ACCEPTED
// 1: node address
// 2-5: timestamp
// 6-7: next alarm
if (millis() - messageSentTime > 1000) { // 1 second timeout on recieving a response.
retries++;
if (retries == 5) {
retries = 0;
registrationState = REGISTRATION_FAILED;
}
else {
registrationState = REGISTRATION_UNREGISTERED;
}
}
if (rf69.available()) {
if (rf69.recvfromAck((uint8_t *)data, &msgLen, &msgFrom)) { // Message received.
Serial.print("Got ");
Serial.print(msgLen);
Serial.print(" bytes response from : 0x");
Serial.println(msgFrom, HEX);
RH_RF69::printBuffer("Data content: ", data, msgLen);
switch (data[0]) {
case DATA_REGISTRATION_ACCEPTED:
if (msgLen == 8) {
masterAddress = msgFrom;
nodeAddress = data[1];
uint32_t timestamp;
memcpy(×tamp, data + 2, 4); // Uncomment this line and it works perfectly!
rf69.setThisAddress(nodeAddress);
registered = true;
registrationState = REGISTRATION_SUCCESS;
Serial.print(F("Node successfully registered as #"));
Serial.print(nodeAddress);
Serial.print(F(", timestamp: "));
Serial.print(timestamp);
Serial.println(F("."));
}
break;
case DATA_REGISTRATION_FAILED:
registrationState = REGISTRATION_FAILED;
break;
}
}
}
break;
}
}
Then the output on the Serial monitor. This is from two runs: the first lines are after the above code was uploaded; the second "Init done." is when I pressed the reset button. The master was untouched during this test.
Init done.
Attempting to register this node, attempt 0
Got 8 bytes response from : 0x1
Data content:
51 52 2E 2A 0 0 0 0
Node successfully registered as #82, timestamp: 10798.
Attempting to register this node, attempt 0
Got 8 bytes response from : 0x1
Data content:
51 53 33 2A 0 0 0 0
Node successfully registered as #83, timestamp: 10803.
Attempting to register this node, attempt 0
Got 8 bytes response from : 0x1
Data content:
51 54 38 2A 0 0 0 0
Node successfully registered as #84, timestamp: 10808.
Init done.
Attempting to register this node, attempt 0
Attempting to register this node, attempt 1
Got 0 bytes response from : 0x1
Data content:
Attempting to register this node, attempt 2
Got 0 bytes response from : 0x1
Data content: