I recently bought a couple of radio transceivers to allow slow speed transfer of data between two Arduinos. I used the RFM69HCW $10 modules from Adafruit. These do not use the LoRa protocol but a simpler packet protocol that suited my application. Point to Point.
Here in the UK I bought them from https://shop.pimoroni.com/products/adafruit-rfm69hcw-transceiver-radio-breakout?variant=19594984071 at just under a tenner, I choose the 433MHz versions as it is easier to make antennas for 70cms and I have test equipment that allows tuning such antennas.
A declared power of 100mW and range of 500m sounded good. The data sheet says 50mA (+13 dBm) to 150mA (+20dBm) current draw for transmissions, ~30mA during active radio listening. The range figure is for line of sight and depends on the antennas. My application will have a PC linked to an Arduino on shore and a mobile model boat on water, the shore station can use a Yagi or decent antenna even if the boat only uses a simple quarter wave whip.
The tutorial on the Adafruit website shows it wired to their own metro boards, I had a couple of Seeduino Nano modules and used them. Their +5 volt output can source 200mA and can power the module directly. There are Arduinos that have limited power supply outputs from the internal 5 volt regulator so you might need to power the transceivers separately in some applications.
There are two Arduino libraries that support these modules, one from LowPowerLabs and one from RadioHead. I had a lot of bother initially when I was using the LowPowerLabs libraries but have since concluded it was probably not the fault of the library. I moved on to the RadioHead Libraries as Adafruit had a modifed version in their Github account.
Their tutorial is at https://learn.adafruit.com/adafruit-rfm69hcw-and-rfm96-rfm95-rfm98-lora-packet-padio-breakouts and the software they recommend is at https://github.com/adafruit/RadioHead
Be very careful! the current RadioHead library at their site is version 1.145 and the Arduino IDE keeps wanting to update your IDE to this version. RESIST THE TEMPTATION TO UPDATE THE LIBRARY when a pop-up appears in your IDE. The AdaFruit version is based on version 1.121.
The Adafruit has many more examples than the up to date version, use the Adafruit version and DO NOT UPDATE it. Or at least, I know if you use the Adafruit one the code below will work, by all means, once you have a working system, change libraries, test it and let me know. I just wanted to get a basic working system and then move on (to write a Python Tkinter program to interface to the arduinos)
The Adafruit library can be downloaded as a .ZIP file from their github account. You can easily install a Zipped library into your Arduino IDE installation by copying it to your libraries folder. The Libraries folder is in your Sketch folder. By default in your Documents folder although in my installation I have moved mine to a folder on the desktop, if you move your sketch folder the libraries folder moves with it.
Place your downloaded .zip into the libraries folder and start the Arduino IDE, select the top line menu item "Sketch"->Include Library>Add .Zip Library. Do not use the new built in library manager icon on the left of the IDE.
I initially used the simple examples you get when you install the library but couldn't get them working, I tried several different wirings and then started to look at other examples. Some had code to pulse the reset line, some examples didn't even wire up the reset pin on the module. I suspect that on some Arduinos the i/o lines come up with a rise time that allows the module to reset itself on powerup. In any case by modifying the "feather arduino" example and adding reset code and wiring I was able to get it going. YMMV.
Here is my wiring;
As you can see the SCK,MOSI and MISO pins goto the Arduino SPI pins. The CS select pin and G0 pin (interrrupt) go to suitable digital pins and are specified when you create the RH_RF69 object from the RF69 class. The RST reset pin is just wired to a digital pin that you make an output.I stripped the code down to the minimum and it is listed below.
Note the "tx" code calls .send and then .waitPacketSent before using .waitAvailableTimeout to wait for data which is picked up with a .recv call. Just for interest I pickup the Received Signal Strength Indication (RSSI) to see how well the antennas are working and range tests (yet to done). The method .lastRssi returns a number in dB (I think). Setup uses the methods .init, .setFrequency, .setTxPower and .setEncryption
Note the receive code has similar setup code and its loop section calls .available to see if data has arrived. The .recv method gets the data into a buffer and I, again, read the signal strength of the last received packet with .lastRssi. A quick .send and .waitPacketSent gives a handshake back to the transmitter code to repeat the cycle
If you look into the .zip library and read the .h and .cpp files you can see the documentation, or at least a list of the various methods (functions) available to you.
// From Feather RawDemo Tx
#include <SPI.h>
#include <RH_RF69.h> //Version 1.121 has more examples than later, don't update for now!!!
#define RF69_FREQ 434.0
#define RFM69_CS 10 // "B"
#define RFM69_INT 2 // "C"
#define RFM69_RST 6 // "A"
uint8_t rudder_position=49;// pick up new values from PC
uint8_t sail_position=48;
RH_RF69 rf69(RFM69_CS, RFM69_INT); // create Object
void setup() {
Serial.begin(115200);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);delay(10);// slow reset
digitalWrite(RFM69_RST, HIGH);delay(10);
digitalWrite(RFM69_RST, LOW);delay(10);
if (!rf69.init()) {Serial.println("RFM69 radio init failed");while (1);}//hang
Serial.println("RFM69 radio init OK!");
if (!rf69.setFrequency(RF69_FREQ)) {Serial.println("setFrequency failed");}
rf69.setTxPower(20, true);// 2nd argument must be true for RFM69HCW
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02,
0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02};//IMcC chose..
rf69.setEncryptionKey(key);
}
void loop() {
delay(2000);// don't flood the receiver, could make bigger...
char radiopacket[7] = "r00s00";// Rudder and sail position
// Pick up variables from PC here, test with 00 <<<<<
rudder_position=51;// test
sail_position=61;// test
itoa(rudder_position, radiopacket+1, 10);// overwrite first 00, base 10
itoa(sail_position, radiopacket+4, 10);// overwrite 2nd 00, base 10
Serial.println(radiopacket);
// Send a message!
rf69.send((uint8_t *)radiopacket, strlen(radiopacket));
rf69.waitPacketSent();
// Now wait for a reply
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf69.waitAvailableTimeout(500)) {
// Should be a reply message for us now
if (rf69.recv(buf, &len)) {
Serial.println((char*)buf);
// Should be GPS position, pass on up to PC
Serial.print("RSSI: ");Serial.println(rf69.lastRssi(), DEC);
} else {
Serial.println("Receive failed");
}
} else {
Serial.println("No reply");
}
}
Here also is the code for a suitable receiver

No comments:
Post a Comment