Adafruit RFM69HCW and RFM9X LoRa Packet Radio Breakouts Created by lady ada Last updated on 2018-08-22 03:53:28 PM UTC
Guide Contents Guide Contents Overview Pinouts Power Pins SPI Logic pins: Radio GPIO Antenna Connection Assembly Prepare the header strip: Add the breakout board: And Solder! Antenna Options 2 4 8 8 9 10 11 13 13 14 14 16 Wire Antenna 16 uFL Connector 18 uFL SMT Antenna Connector SMA to uFL/u.
Design Considerations Wiring With Breakout Usage with All-In-One Feather M0 Adafruit Feather M0 with RFM95 LoRa Radio - 900MHz Adafruit Feather M0 RFM96 LoRa Radio - 433MHz Module Install 49 49 50 50 51 51 Usage Beyond RX & TX Python Docs for RFM9x LoRa RFM9X Test Arduino Library 51 54 57 58 58 RadioHead RFM9x Library example 58 Basic RX & TX example 59 Transmitter example code Receiver example code 59 61 Radio Pinout Frequency Setup 64 64 64 Initializing Radio Transmission Code Receiver Code
Overview "You see, wire telegraph is a kind of a very, very long cat. You pull his tail in New York and his head is meowing in Los Angeles. Do you understand this? And radio operates exactly the same way: you send signals here, they receive them there. The only difference is that there is no cat." Sending data over long distances is like magic, and now you can be a magician with this range of powerful and easyto-use radio modules.
Packet radio with ready-to-go Arduino libraries Uses the amateur or license-free ISM bands (https://adafru.it/mOE): 433MHz is ITU "Europe" license-free ISM or ITU "American" amateur with limitations. 900MHz is license free ISM for ITU "Americas" Use a simple wire antenna or spot for uFL or SMA radio connector RFM69HCW in either 433 MHz or 868/915MHz These are +20dBm FSK packet radios that have a lot of nice extras in them such as encryption and auto-retransmit.
RFM9x LoRa in either 433 MHz or 868/915MHz These are +20dBm LoRa packet radios that have a special radio modulation that is not compatible with the RFM69s but can go much much farther.
All radios are sold individually and can only talk to radios of the same part number. E.g. RFM69 900 MHz can only talk to RFM69 900 MHz, LoRa 433 MHz can only talk to LoRa 433, etc. Each radio comes with some header, a 3.3V voltage regulator and levelshifter that can handle 3-5V DC power and logic so you can use it with 3V or 5V devices. Some soldering is required to attach the header.
Pinouts Both RFM69 and RFM9x LoRa breakouts have the exact same pinouts. The silkscreen will say RFM69HCW or LoRa depending on which variant you have. If there's a green or blue dot on top of the module, its 900 MHz. If there's a red dot, its 433 MHz Power Pins © Adafruit Industries https://learn.adafruit.
The left-most pins are used for power Vin - power in. This is regulated down to 3.3V so you can use 3.3-6VDC in. Make sure it can supply 150mA since the peak radio currents can be kinda high GND - ground for logic and power EN - connected to the enable pin of the regulator. Pulled high to Vin by default, pull low to completely cut power to the radio. SPI Logic pins: © Adafruit Industries https://learn.adafruit.
All pins going into the breakout have level shifting circuitry to make them 3-5V logic level safe. Use whatever logic level is on Vin! SCK - This is the SPI Clock pin, its an input to the chip MISO - this is the Master In Slave Out pin, for data sent from the radio to your processor, 3.3V logic level MOSI - this is the Master Out Slave In pin, for data sent from your processor to the radio CS - this is the Chip Select pin, drop it low to start an SPI transaction.
The radio's have another 5 GPIO pins that can be used for various notifications or radio functions. These aren't used for the majority of uses but are available in case you want them! All are 3.3V logic with no level shifting Antenna Connection This three-way connection lets you select which kind of Antenna you'd like, from the lowest cost wire dipole to the fanciest SMA © Adafruit Industries https://learn.adafruit.
© Adafruit Industries https://learn.adafruit.
Assembly Prepare the header strip: Cut the strip to length if necessary. It will be easier to solder if you insert it into a breadboard - long pins down © Adafruit Industries https://learn.adafruit.
Add the breakout board: Place the breakout board over the pins so that the short pins poke through the breakout pads And Solder! Be sure to solder all pins for reliable electrical contact. (For tips on soldering, be sure to check out our Guide to Excellent Soldering (https://adafru.it/aTk)). © Adafruit Industries https://learn.adafruit.
© Adafruit Industries https://learn.adafruit.
You're done! Check your solder joints visually and continue onto the next steps Antenna Options These radio breakouts do not have a built-in antenna. Instead, you have three options for attaching an antenna. For most low cost radio nodes, a wire works great. If you need to put the radio into an enclosure, soldering in uFL and using a uFL to SMA adapter will let you attach an external antenna.
Strip a mm or two off the end of the wire, tin and solder into the ANT pad. © Adafruit Industries https://learn.adafruit.
That's pretty much it, you're done! uFL Connector If you want an external antenna that is a few inches away from the radio, you need to do a tiny bit more work but its not too difficult. You'll need to get an SMT uFL connector, these are fairly standard (http://adafru.it/1661) uFL SMT Antenna Connector $0.75 IN STOCK ADD TO CART You'll also need a uFL to SMA adapter (http://adafru.it/851) (or whatever adapter you need for the antenna you'll be using, SMA is the most common SMA to uFL/u.
Of course, you will also need an antenna of some sort, that matches your radio frequency uFL connectors are rated for 30 connection cycles, but be careful when connecting/disconnecting to not rip the pads off the PCB. Once a uFL/SMA adapter is connected, use strain relief! Check the bottom of the uFL connector, note that there's two large side pads (ground) and a little inlet pad. The other small pad is not used! Put down a touch of solder on the signal pad © Adafruit Industries https://learn.adafruit.
Solder in the first pad while holding the uFL steady Solder in the two side pads, they are used for signal and mechanical connectivity so make sure there's plenty of solder © Adafruit Industries https://learn.adafruit.
Once done, check your work visually Once done attach your uFL adapter and antenna! SMA Edge-Mount Connector OK so © Adafruit Industries https://learn.adafruit.
You'll need an SMA (or, if you need RP-SMA for some reason) Edge-Mount connector with 1.6mm spacing The SMA connector 'slides on' the top of the PCB © Adafruit Industries https://learn.adafruit.
Once lined up, solder the center contact first Solder in the two side ground pads. Note you will need a lot of heat for this, because the connector is an excellent heat sink and its got a huge ground plane © Adafruit Industries https://learn.adafruit.
Flip over and also do the other side ground/mechanical contacts © Adafruit Industries https://learn.adafruit.
Attach on your antenna, you're done! © Adafruit Industries https://learn.adafruit.
Arduino Wiring https://adafru.it/vhb https://adafru.it/vhb Wiring up the radio in SPI mode is pretty easy as there's not that many pins! The library requires hardware SPI and does not have software SPI support so you must use the hardware SPI port! Start by connecting the power pins Vin connects to the Arduino 5V pin. If you're using a 3.3V Arduino, connect to 3.3V GND connects to Arduino ground CLK connects to SPI clock. On Arduino Uno/Duemilanove/328-based, thats Digital 13.
Using the RFM69 Radio This page is shared between the RFM69 breakout and the all-in-one Feather RFM69's. The example code and overall functionality is the same, only the pinouts used may differ! Just make sure the example code is using the pins you have wired up. Before beginning make sure you have your Arduino or Feather working smoothly, it will make this part a lot easier. Once you have the basic functionality going - you can upload code, blink an LED, use the serial output, etc.
receipt when the packet was delivered. Basically, you get the transparency of a data pipe without the annoyances of radio transmission unreliability Arduino Libraries These radios have really great libraries already written, so rather than coming up with a new standard we suggest using existing libraries such as LowPowerLab's RFM69 Library (https://adafru.it/mCz) and AirSpayce's Radiohead library (https://adafru.
Before uploading, check for the #define FREQUENCY RF69_915MHZ line and comment that out (and uncomment the line above) to match the frequency of the hardware you're using These examples are optimized for the Feather 32u4/M0.
Basic receiver example code This code will receive and reply with a small packet of data. Open up the example RadioHead -> feather -> RadioHead69_RawDemo_RX Load this code into your Receiver Arduino/Feather! Before uploading, check for the #define FREQUENCY RF69_915MHZ line and comment that out (and uncomment the line above) to match the frequency of the hardware you're using These examples are optimized for the Feather 32u4/M0.
And, on the transmitter side, it is now printing Got Reply after each transmisssion because it got a reply from the receiver That's pretty much the basics of it! Lets take a look at the examples so you know how to adapt to your own radio network Radio Freq. Config Each radio has a frequency that is configurable in software. You can actually tune outside the recommended frequency, but the range won't be good. 900 MHz can be tuned from about 850-950MHz with good performance.
For all radios they will need to be on the same frequency. If you have a 433MHz radio you will want to stick to 433. If you have a 900 Mhz radio, go with 868 or 915MHz, just make sure all radios are on the same frequency Configuring Radio Pinout At the top of the sketch you can also set the pinout. The radios will use hardware SPI, but you can select any pins for RFM69_CS (an output), RFM_IRQ (an input) and RFM_RST (an output). RFM_RST is manually used to reset the radio at the beginning of the sketch.
void setup() { Serial.begin(115200); //while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer pinMode(LED, OUTPUT); pinMode(RFM69_RST, OUTPUT); digitalWrite(RFM69_RST, LOW); Serial.println("Feather RFM69 RX Test!"); Serial.
Basic Transmission Code If you are using the transmitter, this code will wait 1 second, then transmit a packet with "Hello World #" and an incrementing packet number, then check for a reply void loop() { delay(1000); // Wait 1 second between transmits, could also 'sleep' here! char radiopacket[20] = "Hello World #"; itoa(packetnum++, radiopacket+13, 10); Serial.print("Sending "); Serial.println(radiopacket); // Send a message! rf69.send((uint8_t *)radiopacket, strlen(radiopacket)); rf69.
void loop() { if (rf69.available()) { // Should be a message for us now uint8_t buf[RH_RF69_MAX_MESSAGE_LEN]; uint8_t len = sizeof(buf); if (rf69.recv(buf, &len)) { if (!len) return; buf[len] = 0; Serial.print("Received ["); Serial.print(len); Serial.print("]: "); Serial.println((char*)buf); Serial.print("RSSI: "); Serial.println(rf69.lastRssi(), DEC); if (strstr((char *)buf, "Hello World")) { // Send a reply! uint8_t data[] = "And hello back to you"; rf69.send(data, sizeof(data)); rf69.
This demo code shows how you can listen for packets and also check for button presses (or sensor data or whatever you like) and send them back and forth between the two radios! Addressed RX and TX Demo OK so the basic demo is well and good but you have to do a lot of management of the connection to make sure packets were received. Instead of manually sending acknowledgements, you can have the RFM69 and library do it for you! Thus the Reliable Datagram part of the RadioHead library.
Because the data is being sent to address #1, but #1 is not acknowledging that data. If you have the server running, with no clients, it will sit quietly: Turn on the client and you'll see acknowledged packets! © Adafruit Industries https://learn.adafruit.
And the server is also pretty happy The secret sauce is the addition of this new object: // Class to manage message delivery and receipt, using the driver declared above RHReliableDatagram rf69_manager(rf69, MY_ADDRESS); Which as you can see, is the manager for the RFM69. In setup() you'll need to init it, although you still configure the underlying rfm69 like before: if (!rf69_manager.init()) { Serial.
if (rf69_manager.sendtoWait((uint8_t *)radiopacket, strlen(radiopacket), DEST_ADDRESS)) { on the 'other side' use the recvFromAck which will receive and acknowledge a packet // Wait for a message addressed to us from the client uint8_t len = sizeof(buf); uint8_t from; if (rf69_manager.recvfromAck(buf, &len, &from)) { That function will wait forever. If you'd like to timeout while waiting for a packet, use recvfromAckTimeout which will wait an indicated # of milliseconds if (rf69_manager.
CircuitPython for RFM69 It's easy to use the RFM69HCW radio with CircuitPython and the Adafruit CircuitPython RFM69 (https://adafru.it/BjE) module. This module allows you to easily write Python code that sends and receives packets of data with the radio.
Board 3V to radio VIN Board GND to radio GND Board SCK to radio SCK Board MOSI to radio MOSI Board MISO to radio MISO Board D5 to radio CS (or any other digital I/O pin) Board D6 to radio RST (or any other digital I/O pin) Usage with All-In-One Feather M0 Alternatively you can use the Feather M0 RFM69 board but be sure you've loaded the adafruit-circuitpythonfeather_m0_rfm69-*.bin (https://adafru.
Adafruit Feather M0 RFM69HCW Packet Radio - 433MHz $24.95 IN STOCK ADD TO CART Module Install Next you'll need to install the Adafruit CircuitPython RFM69 (https://adafru.it/BjE) module on your CircuitPython board. Before you do that make sure you are running the latest version of Adafruit CircuitPython (https://adafru.it/Amd) for your board too (again be sure to the load the Feather M0 RFM69 version if you're using that board and want to use its built-in radio module).
However if you're using the Feather M0 RFM69 board with a built-in RFM69 radio (and you've loaded the special version of CircuitPython just for this board as mentioned above), you instead want to use these pins for the CS and RST lines: cs = digitalio.DigitalInOut(board.RFM69_CS) reset = digitalio.DigitalInOut(board.RFM69_RST) You're ready to import the RFM69 module and create an instance of the RFM69 class inside it.
If you have another RFM69 on the same frequency and modulation waiting to receive messages (like another CircuitPython module running receive code below) you should see it receive the message.
One thing to note in Python byte strings aren't exactly like text strings and you might not be able to do all the text processing (like find, replace, etc.) as you expect. However you can convert a byte string into text by assuming a specific text encoding like ASCII. For example to receive a packet and convert the contents to an ASCII text string you can run code like: packet = rfm69.receive() # Wait for a packet to be received (up to 0.
That's all there is to the basic RFM69 radio usage! Remember the CircuitPython module is designed for sending and receiving small up to 60 byte control messages and not large or high bandwidth amounts of data. Here's a complete example of sending a message and waiting to receive and print any received messages. Save this as main.py on your board and open the serial REPL to see it print data and any received messages.
while True: packet = rfm69.receive() # Optionally change the receive timeout from its default of 0.5 seconds: #packet = rfm69.receive(timeout=5.0) # If no packet was received during the timeout then None is returned. if packet is None: print('Received nothing! Listening again...') else: # Received a packet! # Print out the raw bytes of the packet: print('Received (raw bytes): {0}'.format(packet)) # And decode to ASCII text and print it too.
Python Docs for RFM69 Python Docs for RFM69 (https://adafru.it/C5v) © Adafruit Industries https://learn.adafruit.
CircuitPython for RFM9x LoRa It's easy to use the RFM9x LoRa radio with CircuitPython and the Adafruit CircuitPython RFM9x (https://adafru.it/BjD) module. This module allows you to easily write Python code that sends and receives packets of data with the radio. Be careful to note this library is for the RFM95/96/97/98 LoRa radio only and will not work with the simper RFM69 packet radio.
Board 3V to radio VIN Board GND to radio GND Board SCK to radio SCK Board MOSI to radio MOSI Board MISO to radio MISO Board D5 to radio CS (or any other digital I/O pin) Board D6 to radio RST (or any other digital I/O pin) Usage with All-In-One Feather M0 Alternatively you can use the Feather M0 RFM9x board but be sure you've loaded the adafruit-circuitpythonfeather_m0_rfm9x-*.bin (https://adafru.
Adafruit Feather M0 RFM96 LoRa Radio - 433MHz $34.95 IN STOCK ADD TO CART Module Install Next you'll need to install the Adafruit CircuitPython RFM9x (https://adafru.it/BjD) module on your CircuitPython board. Before you do that make sure you are running the latest version of Adafruit CircuitPython (https://adafru.it/Amd) for your board too (again be sure to the load the Feather M0 RFM9x version if you're using that board and want to use its built-in radio module).
However if you're using the Feather M0 RFM69 board with a built-in RFM9x radio (and you've loaded the special version of CircuitPython just for this board as mentioned above), you instead want to use these pins for the CS and RST lines: cs = digitalio.DigitalInOut(board.RFM9X_CS) reset = digitalio.DigitalInOut(board.RFM9X_RST) You're ready to import the RFM9x module and create an instance of the RFM9x class inside it.
Remember you can only send a message up to 252 bytes in length at a time! Attempting to send a message longer than 252 bytes will fail with an exception error. If you need to send a longer message it will have to be broken up into multiple send calls and reconstructed on the receiving side. If you have another RFM9x on the same frequency waiting to receive messages (like another CircuitPython module running receive code below) you should see it receive the message.
One thing to note in Python byte strings aren't exactly like text strings and you might not be able to do all the text processing (like find, replace, etc.) as you expect. However you can convert a byte string into text by assuming a specific text encoding like ASCII. For example to receive a packet and convert the contents to an ASCII text string you can run code like: packet = rfm9x.receive() # Wait for a packet to be received (up to 0.
receiving small up to 252 byte control messages and not large or high bandwidth amounts of data. Here's a complete example of sending a message and waiting to receive and print any received messages. Save this as main.py on your board and open the serial REPL to see it print data and any received messages. If you have two boards and radios setup to run this code at the same time they'll send each other a message on start up! # Simple demo of sending and recieving data with the RFM95 LoRa radio.
print('Received nothing! Listening again...') else: # Received a packet! # Print out the raw bytes of the packet: print('Received (raw bytes): {0}'.format(packet)) # And decode to ASCII text and print it too. Note that you always # receive raw bytes and need to convert to a text format like ASCII # if you intend to do string processing on your data. Make sure the # sending side is sending ASCII data before you try to decode! packet_text = str(packet, 'ascii') print('Received (ASCII): {0}'.
Python Docs for RFM9x LoRa Python Docs for RFM9x LoRa (https://adafru.it/C5w) © Adafruit Industries https://learn.adafruit.
RFM9X Test Note that the sub-GHz radio is not designed for streaming audio or video! It's best used for small packets of data. The data rate is adjustbale but its common to stick to around 19.2 Kbps (thats bits per second). Lower data rates will be more successful in their transmissions You will, of course, need at least two paired radios to do any testing! The radios must be matched in frequency (e.g. 900 MHz & 900 MHz are ok, 900 MHz & 433 MHz are not).
https://adafru.it/mHC https://adafru.it/mHC Uncompress the zip and find the folder named RadioHead and check that the RadioHead folder contains RH_RF95.cpp and RH_RF95.h (as well as a few dozen other files for radios that are supported) Place the RadioHead library folder your arduinosketchfolder/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. We also have a great tutorial on Arduino library installation at: http://learn.adafruit.
// manual reset digitalWrite(RFM95_RST, LOW); delay(10); digitalWrite(RFM95_RST, HIGH); delay(10); while (!rf95.init()) { Serial.println("LoRa radio init failed"); while (1); } Serial.println("LoRa radio init OK!"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM if (!rf95.setFrequency(RF95_FREQ)) { Serial.println("setFrequency failed"); while (1); } Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); // Defaults after init are 434.
else { Serial.println("Receive failed"); } } else { Serial.println("No reply, is there a listener around?"); } delay(1000); } Once uploaded you should see the following on the serial console Now open up another instance of the Arduino IDE - this is so you can see the serial console output from the TX Arduino while you set up the RX Arduino. Receiver example code This code will receive and acknowledge a small packet of data.
#include #define RFM95_CS 10 #define RFM95_RST 9 #define RFM95_INT 2 // Change to 434.0 or other frequency, must match RX's freq! #define RF95_FREQ 915.0 // Singleton instance of the radio driver RH_RF95 rf95(RFM95_CS, RFM95_INT); // Blinky on receipt #define LED 13 void setup() { pinMode(LED, OUTPUT); pinMode(RFM95_RST, OUTPUT); digitalWrite(RFM95_RST, HIGH); while (!Serial); Serial.begin(9600); delay(100); Serial.
uint8_t len = sizeof(buf); if (rf95.recv(buf, &len)) { digitalWrite(LED, HIGH); RH_RF95::printBuffer("Received: ", buf, len); Serial.print("Got: "); Serial.println((char*)buf); Serial.print("RSSI: "); Serial.println(rf95.lastRssi(), DEC); // Send a reply uint8_t data[] = "And hello back to you"; rf95.send(data, sizeof(data)); rf95.waitPacketSent(); Serial.println("Sent a reply"); digitalWrite(LED, LOW); } else { Serial.
it got a reply from the receiver That's pretty much the basics of it! Lets take a look at the examples so you know how to adapt to your own radio setup Radio Pinout This is the pinout setup - you can change around the reset and CS pins to any pin. the IRQ pin should be an interrupt pin. On an UNO this is pin #2 or pin #3.
void setup() { pinMode(LED, OUTPUT); pinMode(RFM95_RST, OUTPUT); digitalWrite(RFM95_RST, HIGH); while (!Serial); // wait until serial console is open, remove if not tethered to computer Serial.begin(9600); delay(100); Serial.
void loop() { delay(1000); // Wait 1 second between transmits, could also 'sleep' here! Serial.println("Transmitting..."); // Send a message to rf95_server char radiopacket[20] = "Hello World # "; itoa(packetnum++, radiopacket+13, 10); Serial.print("Sending "); Serial.println(radiopacket); radiopacket[19] = 0; Serial.println("Sending..."); delay(10); rf95.send((uint8_t *)radiopacket, 20); Serial.println("Waiting for packet to complete..."); delay(10); rf95.
Once done it will automatically reply, which is a way for the radios to know that there was an acknowledgement // Send a reply uint8_t data[] = "And hello back to you"; rf95.send(data, sizeof(data)); rf95.waitPacketSent(); Serial.println("Sent a reply"); It simply sends back a string and waits till the reply is completely sent © Adafruit Industries https://learn.adafruit.
Downloads Datasheets & Files SX127x Datasheet (https://adafru.it/oBm)- The RFM9X LoRa radio chip itself SX1231 Datasheet (https://adafru.it/mCv) - The RFM69 radio chip itself RFM69HCW datasheet (https://adafru.it/mCu)- contains the SX1231 datasheet plus details about the module (https://adafru.it/mFX) RFM9X (https://adafru.it/mFX) - The radio module, which contains the SX1272 chipset RFM69 FCC Test Report (https://adafru.it/r6d) RFM9x FCC Test Report (https://adafru.
© Adafruit Industries https://learn.adafruit.
Radio Range F.A.Q. Which gives better range, LoRa or RFM69? All other things being equal (antenna, power output, location) you will get better range with LoRa than with RFM69 modules. We've found 50% to 100% range improvement is common. What ranges can I expect for RFM69 radios? The RFM69 radios have a range of approx. 500 meters line of sight with tuned uni-directional antennas.