Particle Photon / Electron + RFN95W Long Range Radio

@luisgcu What I did get going was some code to get the Photon + RFM95 915Mhz Adafruit Feather with Atmel 32u4 chip to talk together over the TX & RX lines.

I figured this was easier than trying to get an individual RFM95 chip working directly with the Photon because I am no expert at modifying libraries :smile: Plus the library for the Adafruit RFM95 Feather boards is already working.

Here is the code for the Photon which is connected to the Adafruit RFM95 Feather Board via the TX & RX lines:

#include "Particle.h"

// Constants
const size_t READ_BUF_SIZE = 256;

// Structures
typedef struct {
int temperature;
int humidity;
int pressure;
int luminosity;
int winddir;
int windspeed;
int rainfall;
} WeatherData;

// Forward declarations
void processBuffer();
void handleWeatherData(const WeatherData &data);

// Global variables
int counter = 0;
unsigned long lastSend = 0;

char readBuf[READ_BUF_SIZE];
size_t readBufOffset = 0;

void setup() {
Serial.begin(19200);

// Serial1 RX is connected to Arduino TX (1)
// Serial2 TX is connected to Arduino RX (0)
// Photon GND is connected to Arduino GND
Serial1.begin(19200);
}

void loop() {

// Read data from serial
while(Serial1.available()) {
if (readBufOffset < READ_BUF_SIZE) {
char c = Serial1.read();
if (c != '\n') {
// Add character to buffer
readBuf[readBufOffset++] = c;
}
else {
// End of line character found, process line
readBuf[readBufOffset] = 0;
processBuffer();
readBufOffset = 0;
}
}
else {
Serial.println("readBuf overflow, emptying buffer");
readBufOffset = 0;
}
}

}

void processBuffer() {
// Serial.printlnf("Received from Arduino: %s", readBuf);
WeatherData data;

if (sscanf(readBuf, "%d,%d,%d,%d,%d,%d,%d", &data.temperature, &data.humidity, &data.pressure,
&data.luminosity, &data.winddir, &data.windspeed, &data.rainfall) == 7) {

handleWeatherData(data);
}
else {
Serial.printlnf("invalid data %s", readBuf);
}
}

void handleWeatherData(const WeatherData &data) {
Serial.printlnf("got temperature=%d humidity=%d pressure=%d luminosity=%d winddir=%d windspeed=%d rainfall=%d",
data.temperature, data.humidity, data.pressure, data.luminosity, data.winddir, data.windspeed, data.rainfall);
}

Here is the code I’m running on the RFM95 Adafruit Feather board:

// Feather9x_RX
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client (receiver)
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example Feather9x_TX

#include <SPI.h>
#include <RH_RF95.h>

/* for feather32u4 */
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7

// Constants

// Structures
typedef struct {
  int temperature;
  int humidity;
  int pressure;
  int luminosity;
  int winddir;
  int windspeed;
  int rainfall;
} WeatherData;

// Forward declarations
void getWeatherData(WeatherData &data);
void sendWeatherData(const WeatherData &data);

// Global variables
char sendBuf[256];



// 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);

  // Serial TX (1) is connected to Photon RX
  // Serial RX (0) is connected to Photon TX
  // Ardiuno GND is connected to Photon GND
  Serial.begin(19200);
  Serial1.begin(19200);
  
  delay(100);

  Serial.println("Feather LoRa RX Test!");
  
  // 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);


  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
  // you can set transmitter powers from 5 to 23 dBm:
   rf95.setTxPower(23, false);
}

void loop()
{

  WeatherData data;
  getWeatherData(data);
  sendWeatherData(data);
  

  /*
  if (rf95.available())
   {
    // Should be a message for us now   
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    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);
      delay(10);
      // 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.println("Receive failed");
    }
  }*/
  delay(1000);
}

void getWeatherData(WeatherData &data) {
  // This just generates random data for testing
  data.temperature = rand();
  data.humidity = rand();
  data.pressure = rand();
  data.luminosity = rand();
  data.winddir = rand();
  data.windspeed = rand();
  data.rainfall = rand();
}

void sendWeatherData(const WeatherData &data) {

  snprintf(sendBuf, sizeof(sendBuf), "%d,%d,%d,%d,%d,%d,%d\n",
      data.temperature, data.humidity, data.pressure, data.luminosity, data.winddir, data.windspeed, data.rainfall);
  Serial1.print(sendBuf);
}

Part of this code comes from this LORA HAM project: https://github.com/travisgoodspeed/loraham

And the Serial to Serial transfer part came from this tutorial: https://github.com/rickkas7/serial_tutorial/blob/master/example1.md

1 Like