How to make RFM69 work on Photon? [SOLVED - new library RFM69-Particle]


#11

@bloukingfisher Thanks for adding the library to the interface!

I have 2 different versions of the RFM69 modules and have gotten a good 1 mile range out of then in suburban areas using a simple wire antenna which I think is great.

I think these low cost 2 way radios allow for some really neat long range applications to be developed which helps overcome the short range of WiFi Hotspots.

Can you share the link to where you bought the RFM69 module from that is working for you? All mine are on boards with Atmel processors already on board.


#12

I got mine from the official US distributor for $4-$5 each (arrived shipped in about 1-2 days, neat!). I’ve not yet had time to do a longer range test but certainly works way beyond WiFi range which solved something for me.

I’m also just using a simple wire dipole antenna.

PS: The exact model I’m using is the RFM69HCW but requires some soldering as the pin sizes don’t match a normal breadboard. And I don’t use it at the high power 20 dBM setting as my battery cannot source enough current for that (130 mA!). Lower power setting of 10 works awesome and requires only ~30 mA.


#13

@bloukingfisher I was actually getting the 1-mile range on the RF96 modules, sorry. Got the 69 confused with the 96 :smile:

I don’t think the libraries are compatible.


#14

Outstanding work gentleman!!! Thanks a million for the library. Soon I will get to using it.


#15

Thanks guys. This library is working great when communicating between Photons. Has anyone tried setting up a Photon with the RFM69 as a receiver and an arduino pro mini with RFM69 as a transmitter? I am trying to have them both communicate with each other and unfortunately the Photon is not able to receive any messages from the Arduino pro mini. Below are my codes for each device. Has anybody had any success with getting the Photon and Arduino to communicate with each other?

Arduino Pro Mini Code

#include <RFM69.h>
#include <RFM69_ATC.h>
#include <RFM69registers.h>
#include <SPI.h>

int16_t NETWORKID = 0;
int16_t MYNODEID = 9;
int16_t TONODEID = 3;

//#define NETWORKID     0   // Must be the same for all nodes
//#define MYNODEID      1   // My node ID
//#define TONODEID      3   // Destination node ID
#define FREQUENCY     RF69_915MHZ
//#define USEACK        true // Request ACKs or not
#define LED           6 // LED positive pin
#define GND           8 // LED ground pin
#define BTN 7


RFM69 radio;

void setup()
{
  Serial.begin(9600);
  Serial.print("Node ");
  Serial.print(MYNODEID,DEC);
  Serial.println(" ready");  

  pinMode(BTN, INPUT); 
  pinMode(GND,OUTPUT);
  digitalWrite(GND,LOW);

  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW
}

void loop()
{
  if(digitalRead(BTN) == HIGH){
    
     Serial.print("begin - pushed");
     static int sendlength = 8;
     static char sendbuffer[] = "411";
  
     Serial.print("sending to node ");
     Serial.print(TONODEID, DEC);
     Serial.print(", message [");
      for (byte i = 0; i < sendlength; i++)
      Serial.print(sendbuffer[i]);
      Serial.println("]");
  
//      if (USEACK)
//        {
//          if (radio.sendWithRetry(TONODEID, sendbuffer, sendlength))
//            Serial.println("ACK received!");
//          else
//            Serial.println("no ACK received");
//        }
//  
//        else // don't use ACK
//        {
//          radio.send(TONODEID, sendbuffer, sendlength);
//        }
        
        sendlength = 8; // reset the packet
  }
}

Photon Code

#include "RFM69-Particle/RFM69-Particle.h"
#include "RFM69-Particle/RFM69_ATC.h"
#include "RFM69-Particle/RFM69registers.h"

// Adjustments to library to work with Particle Photon including in Web IDE by Jurie Pieterse
// Forked library for Photon at https://github.com/bloukingfisher/RFM69/
// Serial NOT required to confirm working - you can watch your Particle Console logs!

/* RFM69 library and code by Felix Rusu - felix@lowpowerlab.com
// Get libraries at: https://github.com/LowPowerLab/
// Make sure you adjust the settings in the configuration section below !!!
// **********************************************************************************
// Copyright Felix Rusu, LowPowerLab.com
// Library and code by Felix Rusu - felix@lowpowerlab.com
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it 
// and/or modify it under the terms of the GNU General    
// Public License as published by the Free Software       
// Foundation; either version 3 of the License, or        
// (at your option) any later version.                    
//                                                        
// This program is distributed in the hope that it will   
// be useful, but WITHOUT ANY WARRANTY; without even the  
// implied warranty of MERCHANTABILITY or FITNESS FOR A   
// PARTICULAR PURPOSE. See the GNU General Public        
// License for more details.                              
//                                                        
// You should have received a copy of the GNU General    
// Public License along with this program.
// If not, see <http://www.gnu.org/licenses></http:>.
//                                                        
// Licence can be viewed at                               
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************/


//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
int16_t NETWORKID = 0;  //the same on all nodes that talk to each other
int16_t NODEID = 3;  

//Match frequency to the hardware version of the radio on your Feather
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY      RF69_915MHZ
//#define ENCRYPTKEY     "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HCW    false // set to 'true' if you are using an RFM69HCW module

//*********************************************************************************************

#define RFM69_CS      A2 
#define RFM69_IRQ     2
#define RFM69_IRQN    2 //On Photon it is the same unlike Arduino
#define RFM69_RST     6

int16_t packetnum = 0;  // packet counter, we increment per xmission

RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);  //initialize radio with potential custom pin outs; otherwise you may use for default: RFM69 radio;

//*********************************************************************************************
// ***********                  Wiring the RFM69 Radio to Photon                  *************
//*********************************************************************************************
/* Arduino wiring provided for reference, color 
    Photon      Arduino	    RFM69	Color
    GND         GND	        GND	    Black
    3V3         3.3V	    VCC	    Red
    A2          10	        NSS	    Yellow
    A3          13	        SCK	    Green
    A5          11	        MOSI	Blue
    A4          12	        MISO	Violet
    D2          2	        DI00	Gray
                            ANA	    Antenna
    D6                      RST     Optional
*/

void setup() 
{
 
    Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
    Particle.publish("RFM69 RX Startup setup","Completed",360,PRIVATE);
    Particle.publish("WiFi signal",String(WiFi.RSSI()),360,PRIVATE);
    Serial.println("RFM69 Based Receiver");
  
    // Hard Reset the RFM module - Optional
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, HIGH);
  delay(100);
  digitalWrite(RFM69_RST, LOW);
  delay(100);
  
    // Initialize radio
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  if (IS_RFM69HCW) {
    radio.setHighPower();    // Only for RFM69HCW & HW!
  }
  
  // To improve distance set a lower bit rate. Most libraries use 55.55 kbps as default
  // See https://lowpowerlab.com/forum/moteino/rfm69hw-bit-rate-settings/msg1979/#msg1979
  // Here we will set it to 9.6 kbps instead 
  radio.writeReg(0x03,0x0D); //set bit rate to 9k6
  radio.writeReg(0x04,0x05);
  
  radio.setPowerLevel(10); // power output ranges from 0 (5dBm) to 31 (20dBm)
                          // Note at 20dBm the radio sources up to 130 mA! 
                         // Selecting a power level between 10 and 15 will use ~30-44 mA which is generally more compatible with Photon power sources
                        // As reference, power level of 10 transmits successfully at least 300 feet with 0% packet loss right through a home, sufficient for most use
    
  //radio.encrypt(ENCRYPTKEY);
  
  Serial.print("\nListening at ");
  Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(" MHz");
  radio.receiveDone(); //put radio in RX mode
}


//=========================MAIN LOOP===========================================
void loop() {

Serial.print("."); //THis gives us a neat visual indication of time between messages received

  //check if something was received (could be an interrupt from the radio)
  if (radio.receiveDone())
  {
    //print message received to serial
    Serial.println(" ");
    Serial.print('[');Serial.print(radio.SENDERID);Serial.print("] ");
    Serial.print((char*)radio.DATA);
    Serial.print("   [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]");
    
    //send message to Particle console if not using serial
    String RXMessage = "[" + String(radio.SENDERID) + "]  " + String((char*)radio.DATA) + " [RSSI: " + String(radio.RSSI) + "]";
    Particle.publish("Message received",RXMessage,360,PRIVATE);

    //check if received message contains Hello
    if (strstr((char *)radio.DATA, "Hello"))
    {
      //check if sender wanted an ACK
      if (radio.ACKRequested())
      {
        radio.sendACK();
        Serial.println(" - ACK sent");
      }
      else {Serial.println(" - No ACK sent");}
    }  
  }

  radio.receiveDone(); //put radio in RX mode
  
  delay(1000);


} //end loop

Thanks in advance for the help guys!


RadioHead library + Photon (Tx) +Electron(Rx) +MiCS-5524 +433Mhz (Sparkfun)Tx/Rx module
#16

Yes! I have confirmed the below code on an Arduino pro mini as transmitter to a Photon. Make changes or for initial testing use the exact sample code from the Photon library (that it is, same network ID, set encryption, etc.) And make sure you’re using the latest RFM69 library on the Arduino (and not the Particle library).

/* RFM69 library and code by Felix Rusu - felix@lowpowerlab.com
// Get libraries at: https://github.com/LowPowerLab/
// Make sure you adjust the settings in the configuration section below !!!
// **********************************************************************************
// Copyright Felix Rusu, LowPowerLab.com
// Library and code by Felix Rusu - felix@lowpowerlab.com
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it 
// and/or modify it under the terms of the GNU General    
// Public License as published by the Free Software       
// Foundation; either version 3 of the License, or        
// (at your option) any later version.                    
*/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>

#include <Arduino.h>            // assumes Arduino IDE v1.0 or greater
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>

//watchdog interrupt
ISR (WDT_vect) {
  wdt_disable();
}

//#include <LowPower.h> //get library from: https://github.com/lowpowerlab/lowpower
                      //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/
                      
//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NETWORKID     100  // The same on all nodes that talk to each other
#define NODEID        2    // The unique identifier of this node
#define RECEIVER      1    // The recipient of packets

//Match frequency to the hardware version of the radio on your Feather
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HCW   false // set to 'true' if you are using an RFM69HCW module

//*********************************************************************************************
#define SERIAL_BAUD   115200

#define RFM69_CS      10
#define RFM69_IRQ     2
#define RFM69_IRQN    0  // Pin 2 is IRQ 0!
#define RFM69_RST     9

#define LED           13  // onboard blinky


int16_t packetnum = 0;  // packet counter, we increment per xmission

RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);

void setup() {
 
  pinMode(RFM69_RST, INPUT);
  pinMode(RFM69_CS, OUTPUT);
    digitalWrite(RFM69_CS, LOW);  
  
//  while (!Serial); // wait until serial console is open, remove if not tethered to computer
  Serial.begin(SERIAL_BAUD);

  Serial.println("Arduino RFM69 Transmitter");
  
  // Hard Reset the RFM module
  /*
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, HIGH);
  delay(100);
  digitalWrite(RFM69_RST, LOW);
  delay(100);
*/

  // Initialize radio
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  if (IS_RFM69HCW) {
  //  radio.setHighPower();    // Only for RFM69HCW & HW!
  }
  
    // https://lowpowerlab.com/forum/moteino/rfm69hw-bit-rate-settings/msg1979/#msg1979
  radio.writeReg(0x03,0x0D); //set bit rade to 9k6
  radio.writeReg(0x04,0x05);
  
  radio.setPowerLevel(10); // power output ranges from 0 (5dBm) to 31 (20dBm)
  
  radio.encrypt(ENCRYPTKEY);
  
  radio.sleep();
  

  pinMode(LED, OUTPUT);
  Serial.print("\nTransmitting at ");
  Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(" MHz");
  
    power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();
  
  
}


void loop() {
  Serial.println("Start loop");
  delay(2000);  // 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);
    
  if (radio.sendWithRetry(RECEIVER, radiopacket, strlen(radiopacket))) { //target node Id, message as string or byte array, message length
    Serial.println("OK");
  }

  //send the message without retrying
 //  radio.send(RECEIVER, radiopacket, strlen(radiopacket));//target node Id, message as string or byte array, message length
 //   Serial.println("OK, sent without retrying");  
  
  radio.receiveDone(); //put radio in RX mode
  
  Serial.println("Radio going to sleep");
  radio.sleep();
  delay(4000);
  
  Serial.println("Everything going to sleep");
  Serial.flush(); //make sure all serial data is clocked out before sleeping the MCU
  deepsleep();
  
}

void deepsleep() 
{
  // disable ADC
  ADCSRA = 0;  
  // clear various "reset" flags
  MCUSR = 0;
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  //set interrupt mode and an interval
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); //set WDIE, and 8 seconds delay
  wdt_reset(); //pat the dog...
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts(); // timed sequence follows  
  sleep_enable();

  // turn off brown-out enable in software
  // BODS must be set to one and BODSE must be set to zero within four clock cycles
  MCUCR = bit (BODS) | bit (BODSE);
  // The BODS bit is automatically cleared after three clock cycles
  MCUCR = bit (BODS); 
  interrupts();
  sleep_cpu();

  //cancel sleep as a precaution
  sleep_disable();
}

Electron, nRF24L01 and Pro Mini
#17

Thank you so much man. This worked perfectly!


#18

FYI - There was an issue where ATC was not working with Photon. Corrected now. Make sure you use the new library version 0.0.2 (or later). This is pretty cool functionality that will dial down the transmit power level to reach a target RSSI level.


#19

@bloukingfisher What kind of range have you seen when testing these RFM69 modules?

I’ve only used the RFM96 modules that provided a 1-mile range for non-reliable datagram communication and I can not get past 10 feet when trying to use the reliable datagram messaging on a few different RFM96 modules for some reason.


#20

I’ve only been testing for reliable communications in about 150 feet, indoors and outdoors. And they work for that. A couple of challenges in the process. Once the dust settles I’ll try to take them for a walk to get an idea of longer range (I’ve read other people getting long range especially using the ‘H’ versions for higher power and turning down the rate.


#21

@RWB Is this Photon to Photon or how are you using the RFM96? To my frustration I discovered today with RFM69 difference between Arduino and Photon. For desk testing in Arduino if I don’t specify a transmit power level it works 100%, but for Photon if transmit power level is unspecified packets are only received 0% - 50% of the time when 3-6 feet apart.

I’ve not dug deeper into the ported library but I suspect in Arduino there’s a register or base default value that gets set, and in the Photon it isn’t set or set to the lowest possible value. Sorry, can’t help more with UDP vs reliable.

EDIT: RFM69 does offer options on acknowledgement, retries, encryption and error checking if that helps.


#22

My range testing was done with these modules.

With unreliable communication, I can get the receiver to acknowledge receipt of the message up to 1 mile away. Using the Reliable Datagram code I can’t get more than 10 feet away. It’s the same with this module also: http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/

Here is an article they have on range testing the RFM69 you have: http://www.rocketscream.com/blog/2016/03/10/radio-range-test-with-rfm69hcw/


#23

Thanks @RWB that was good reading.

I came across this and wondered if the same may resolve your issue of reliable datagram not getting over 10 feet. This is for RFM95 instead of RFM96.

"Found the fix. I had set the power incorrectly based on the module I had. Here’s what was needed:
driver.setTxPower(20); "


#24

Thanks for the info.

I made the changes but I still get the 10 feet range before dropping out.

The guy in the link you provided seems to have figured it out so at least I know who to contact when I want to try this again.


#25

@bloukingfisher Somebody got the RadioHead library to work with the Particle DEV.


#26

I have tested both modules RFM95 and RFM 96 and in not perfect line of sight and the range is 5-8km at 20dbm, at 5dbm I got a decent range of 1.5km.
I did some modification to spreading factors(SF) and bandwidth on the RFM95 library.
see the links and sample codes.
https://lowpowerlab.com/forum/moteino/lora-rfm96-433mhz-range-test-gt5-2-miles-8-3km-!!!/
https://lowpowerlab.com/forum/moteino/lora-rfm96-915mhz-range-test-gt3-7miles-6km!!/


#27

@luisgcu I have seen your range test before and they are impressive ranges! I’ve seen 1 mile range with simple copper wire antennas on the RF95 915 Mhz models.

I see these as an easy way to add remote sensors up to 1-3 miles away from Web-connected Photons or Electrons


#28

bloukingfisher,
Thanks for putting in all the work to get the photon with Rfm69 chip.
I decided I would try to revisit this. I am hopefully going to get the photon to receive info. via the rfm69 chip so the photon can relay mqtt info to my openhab setup.
I am still having trouble getting your example on the the particle IDE to work consistently.
I have tried photon to photon with the RFM69HCW chips.
I got a few seconds of transmission and then it stopped. Nothing has worked since?
I copied the the examples rx and tx verbatim.
Have you used this set up for MQTT at all?
Any pointers?
Thanks,
Webzter30


#29

You’re welcome @Webzter30

I’ve not set it up with MQTT. OK, so sounds like you’re on the right path if you successfully transmitted for a few seconds. What happens after a few seconds. Is the TX unit still showing incrementing transmissions or is it stuck? If the TX unit is still transmitting, is it just that the RX unit stopped receiving?

Before you test again, or after each of the below efforts completely unplug your Photon/RFM board from power. In my experience the RFM board can get stuck in a transmit state and only a power down will reset it.

How are you powering the Photons? Have you tried a capacitor on the RFM69HCW board? What is the power level you are transmitting at (defined in the setup section)?

I’m fairly sure you are seeing an issue related with power…not IDE or code specifically. You may see in the example code this little comment reference: “Note at 20dBm the radio sources up to 130 mA!”. I’m not sure the Photon is capable of delivering that, and even if you power it directly from the right voltage source something like a battery setup probably can’t deliver 130 mA or can’t deliver that level for very long which is probably the issue you are experiencing. Here is what I would try:

  1. See what happens if you dial down radio.setPowerLevel(X); where X is 0, or 5 or 7…something low. On the CW chip I find I can dial it up to 17-23 at the most before running into problems when battery powered. I’m assuming at this point you have both Photons in same room proximity - at least a couple of feet from each other but say no more than 15 feet?

  2. Since you transmitted for a few seconds, first try in the TX example to increase the delay after send from 2000 to say 5000 or 10000. That should be enough time for capacitors and power to settle down and get ready for another burst.

  3. Set the registry to transmit at a lower speed (line 107 in the example code “radio.writeReg(0x03,0x0D); //set bit rate to 9k6”. The comment above it provides a link on where to get info on setting this. In fact, maybe you even want to test increasing the bit rate - transmit more data in less time before you run into power issues?)

  4. If you’ve exhausted the above code efforts…hardware. Add capacitors to the radio, check antennas (you have used antennas right? Transmitting without an antenna I believe can ruin your chip). Try another power source. If you have, try the non-H version of RFM69CW. Basically between the code dial down power use, and on the hardware side beef up power supply until you get it to work reliably. From there you can step by step tune it up until you run into failures.

I’d love to hear if you come right, and how you solve it.


#30

I tried all the above suggestions.
Thanks for your quick reply.
Is the example code in the particle web IDE for TX and RX the exact same that you used to get this to work?
If so, shouldn’t it work as long as I follow the pin out you listed in the example, and hook each photon to the RFM69HCW? Did you change anything in your set up?
Thanks so much for your help with this.