Hello! I'm new to all of this (electronics and radios), and slowly building my way towards a basic sensor network. Right now I'm prototyping the wireless communication using RFM69s on two breadboards. As far as I can tell the setup is pretty standard (see diagram below):
- 3v power from arduino
- 16MHZ crystal and the CKDIV8 fuse set so the 328p is running at 2MHZ
- RFM69W connected via SPI as shown
I have written a short test program (code below) which
should make some pseudo Morse code: node 0 blinks a three-item code, then node 1 blinks the same three-item code. Then they switch: node 1 sends a message to node 0.
Several things are working:
- Program on both nodes starts up correctly, and the `testRadio` function returns true (tests that the RFM69 is working by trying to set a register and then confirming that it was set by reading the register out).
- Node 0 blinks a code, at expected speed.
- Node 1 starts to listen for a message.
And then node 0 lights up indicating that the message was not received and node 1 continues to listen for a message. I'm not sure how to debug from here. The only thing I've thought of is to solder two replacement RFM69s to perf board in case I accidentally busted the radio by running briefly without an antenna. I might have also let 5v in at one point or another, but then I wouldn't think `testRadio` would work. I was hoping that instead my naivete has lead to some obvious error.
Questions / curiosities:
- R4, on the slave-select pin, is necessary for programming (to disable the SPI communication with the radio?). However, leaving it connected when running the program seems to have no effect. This seems strange to me.
- In the RFM69 library I believe the SPI clock is normally set to 4,000,000 (4 MHZ?) (`_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);`). Based on what I've read it should be 1/4 the 328p's clock speed, so I tried changing that to 500,000, but with no change in the results above.
Thanks for any suggestions!
// Copyright Felix Rusu 2016, http://www.LowPowerLab.com/contact
...
// http://www.gnu.org/licenses/gpl-3.0.txt
#include <Arduino.h>
#include <RFM69.h> //get it here: https://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h> //get it here: https://github.com/lowpowerlab/spiflash
#include <SPI.h> //included with Arduino IDE (www.arduino.cc)
//unique for each node on same network
#define NODEID 0
#define NODES 2
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_915MHZ
#define ENCRYPTKEY "Ow4ihs(*E#qt8HOH" //exactly the same 16 characters/bytes on all nodes!
#define LED_SEND 9
#define LED_RECEIVE 8
#define MESSAGE_LENGTH 3
#define DIT_MS 300
#define SERIAL_BAUD 9600
int TRANSMITPERIOD = 2000; //transmit a packet to gateway so often (in ms)
char buff[50];
byte sendSize = 0;
int targetNodeId;
#ifdef ENABLE_ATC
RFM69_ATC radio;
#else
RFM69 radio;
#endif
void Blink(byte PIN, int DELAY_MS)
{
digitalWrite(PIN, HIGH);
delay(DELAY_MS);
digitalWrite(PIN, LOW);
}
void BlinkBits(byte pin, byte data)
{
int i = 0;
Serial.print("Blink: ");
Serial.println(data, BIN);
while (i < MESSAGE_LENGTH)
{
if (data & 0x01)
{
Serial.print(1);
Blink(pin, DIT_MS * 3);
}
else
{
Serial.print(0);
Blink(pin, DIT_MS);
}
delay(DIT_MS);
i++;
data = data >> 1;
}
delay(DIT_MS * 2);
Serial.println();
}
bool testRadio()
{
if (radio.readReg(0x2F) != 0x2D)
{
return false;
}
uint32_t start = millis();
uint32_t timeout = 1000;
do
{
radio.writeReg(0x2F, 0xAA);
if (millis() - start > timeout)
return false;
} while (radio.readReg(0x2F) != 0xAA);
// Rewrite config value from initialize.
radio.writeReg(0x2F, 0x2D);
return true;
}
void errorDisplay()
{
digitalWrite(LED_SEND, HIGH);
digitalWrite(LED_RECEIVE, HIGH);
while (1)
{
}
}
void setup()
{
pinMode(LED_SEND, OUTPUT);
pinMode(LED_RECEIVE, OUTPUT);
Serial.begin(SERIAL_BAUD);
SPI.setClockDivider(SPI_CLOCK_DIV16);
if (!radio.initialize(FREQUENCY, NODEID, NETWORKID) || !testRadio())
{
Serial.println("Error: Unable to initialize radio!");
// Turn both lights on to indicate an error.
errorDisplay();
}
radio.encrypt(ENCRYPTKEY);
#ifdef ENABLE_ATC
radio.enableAutoPower(ATC_RSSI);
#endif
randomSeed(analogRead(0));
targetNodeId = (NODEID + 1) % NODES;
sprintf(buff, "\nNode %d, transmitting to node %d at %d Mhz...", NODEID, targetNodeId, FREQUENCY == RF69_433MHZ ? 433 : FREQUENCY == RF69_868MHZ ? 868 : 915);
Serial.println(buff);
Blink(NODEID == 0 ? LED_SEND : LED_RECEIVE, 3000);
delay(500);
}
byte randNumber = 0;
bool sendMessage = NODEID == 0;
int blinkCounter = 0;
int blinkFrequency = 10000;
bool blinkOn = true;
void loop()
{
if (sendMessage)
{
sendMessage = false;
randNumber = random(pow(2, MESSAGE_LENGTH));
Serial.print("Sending data to node ");
Serial.print(targetNodeId);
Serial.println(":");
Serial.println(randNumber, BIN);
BlinkBits(LED_SEND, randNumber);
if (radio.sendWithRetry(targetNodeId, &randNumber, 1))
{
Serial.print(" Sent ok!");
}
else
{
Serial.print(" No response...");
errorDisplay();
}
Serial.println();
}
else if (radio.receiveDone())
{
digitalWrite(LED_SEND, LOW);
Serial.print("Receiving from node ");
Serial.print(radio.SENDERID, DEC);
Serial.println(":");
Serial.println(radio.DATA[0], BIN);
Serial.print(" [RX_RSSI:");
Serial.print(radio.RSSI);
Serial.print("]");
if (radio.ACKRequested())
{
radio.sendACK();
Serial.print(" - ACK sent");
}
BlinkBits(LED_RECEIVE, radio.DATA[0]);
Serial.println();
sendMessage = true;
}
else if (blinkCounter++ > blinkFrequency)
{
if (blinkOn)
{
Serial.print(".");
digitalWrite(LED_SEND, HIGH);
}
else
{
digitalWrite(LED_SEND, LOW);
}
blinkOn = !blinkOn;
blinkCounter = 0;
}
}