Create a gist now

Instantly share code, notes, and snippets.

LoRa_FeatherWing_DevBreakout_TransceiverMode
/* LoRa FeatherWing Tranceiver Mode Example Program
* By: Dan Watson | syncchannel.blogspot.com
* Date: 2-23-2016
* Version: 0.2
*
* Example Tranceiver Mode Program for the LoRa FeatherWing for Adafruit Feather
* Tested with Feather M0, Feather 32U4 and Feather HUZZAH
*
* This program configures the Feather as a LoRa receiver. It is intended as a companion
* to the LoRA FeatherWing Beacon Example Program, and can receive the beacon messages.
* It can also be modified to relay serial communications between Feather nodes, amongst
* other things.
*
* This program is adapted from the RFM95W_Nexus library created by Gerben den Hartog
* It has been adapted from his code to work specifically on Adafruit Feather with
* the LoRa FeatherWing. Credit is given to Gerben for is useful library and work!
* Check out his full github repo if you are interested in LoRaWAN.
*
* Based on a library by Gerben den Hartog
* https://github.com/Ideetron/RFM95W_Nexus
* http://www.ideetron.nl/LoRa
*
*/
// Only the Arduino SPI library is needed to compile this program
#include <SPI.h>
//Define pin descriptions (Adafruit Feather M0 and 32U4)
#define DIO0 5
#define DIO5 6
#define CS 10
#define LED 13
//Use these pin definitions instead for Feather HUZZAH
//#define DIO0 4
//#define DIO5 5
//#define CS 2
//#define LED 0
// Set frequency of RFM module
// Available frequencies depend on which RFM module you have
#define RFM_FREQ_MHZ 915000000
// Define the length of the user message payload in bytes
#define PACKAGE_LENGTH 10
// Holder for the received data bytes
unsigned char RFM_Package[PACKAGE_LENGTH];
void setup()
{
Serial.begin(9600);
//Initialize SPI
SPI.begin();
SPI.beginTransaction(SPISettings(4000000,MSBFIRST,SPI_MODE0));
//Initialize I/O pins
pinMode(DIO0,INPUT);
pinMode(DIO5,INPUT);
pinMode(CS,OUTPUT);
pinMode(LED,OUTPUT);
// Pull chip select high for now
digitalWrite(CS,HIGH);
// Minimum of 100ms recommended to allow RFM module to start up
delay(200);
//Initialize the RFM module
RFM_Init();
// Flash D13 LED on Feather to notify user that setup is complete
for (int i = 0; i <= 3; i++)
{
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(200);
}
}
void loop()
{
//Check if the RFM has received a package
if(digitalRead(DIO0) == HIGH)
{
digitalWrite(LED, HIGH);
//Get package from RFM
RFM_ReadPackage(RFM_Package);
//Send package over Serial
for(int i = 0; i < PACKAGE_LENGTH; i++)
{
Serial.print(RFM_Package[i], HEX);
Serial.print(" ");
}
Serial.println("");
delay(50);
digitalWrite(LED, LOW);
}
}
/*
* Function to initialize the RFM module.
* It is highly recommended that you read the datasheet for the module, there are lots of
* settings you can adjust to improve the wireless link parameters for your specific usage
* http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
*/
void RFM_Init()
{
//Set RFM module in sleep mode to change to LoRa mode
RFM_Write(0x01,0x00);
//Set LoRa mode
RFM_Write(0x01,0x80);
//Set RFM module in standby mode to change more settings
RFM_Write(0x01,0x81);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
// Set carrier frequency
// RFM_FREQ_MHZ / 61.035 Hz = 3 byte value to load
unsigned long freqHolder = RFM_FREQ_MHZ / 61.035; // round down
uint8_t freqLSB = freqHolder;
uint8_t freq2B = (freqHolder >> 8);
uint8_t freqMSB = (freqHolder >> 16);
RFM_Write(0x06,freqMSB);
RFM_Write(0x07,freq2B);
RFM_Write(0x08,freqLSB);
//Set maximum transmit power settings
RFM_Write(0x09,0xFF);
//Set bandwith 250 kHz, Coding rate = 4/8, Implicit header mode
RFM_Write(0x1D,0x89);
//Spreading factor 11, PayloadCRC on
RFM_Write(0x1E,0xB4);
//*NOTE: If you decide to change to Spreading Factor 6, you also need to set the following
//*two registers by uncommenting these lines
//RFM_Write(0x31,0xC5);
//RFM_Write(0x37,0x0C);
//Preamble length 0x0018 + 4 = 28
RFM_Write(0x20,0x00);
RFM_Write(0x21,0x18);
//Payload length
RFM_Write(0x22,PACKAGE_LENGTH);
//Set RFM in continues receive
RFM_Write(0x01,0x85);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
}
/* This function is used to read a value from a specific register of the RFM module
* Arguments: RFM_Adress Adress of the register to read
* Return: The value of the register is returned
*/
unsigned char RFM_Read(unsigned char RFM_Address)
{
unsigned char RFM_Data;
//Set CS pin low to start SPI communication
digitalWrite(CS,LOW);
//Send Address
SPI.transfer(RFM_Address);
//Send 0x00 to receive the answer from the RFM
RFM_Data = SPI.transfer(0x00);
//Set CS high to end communication
digitalWrite(CS,HIGH);
//Return received data
return RFM_Data;
}
/* This function is used to write a value to a specific register of the RFM module
* Arguments: RFM_Adress Adress of the register to be written
* RFM_Data Data that will be written
*/
void RFM_Write(unsigned char RFM_Address, unsigned char RFM_Data)
{
//Set CS pin low to start communication
digitalWrite(CS,LOW);
//Send Addres with MSB 1 to make it a write command
SPI.transfer(RFM_Address | 0x80);
//Send Data
SPI.transfer(RFM_Data);
//Set CS pin high to end communication
digitalWrite(CS,HIGH);
}
/* This function is used to send a message payload
* Arguments: *RFM_Package Pointer to the array with the data to send
*/
void RFM_SendPackage(unsigned char *RFM_Package)
{
//Switch RFM to standby
RFM_Write(0x01,0x81);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
//Set SPI pointer to Tx base address
RFM_Write(0x0D,0x80);
//Switch DIO to TxDone
RFM_Write(0x40,0x40);
//Write payload in to the FIFO
for(int i = 0; i < PACKAGE_LENGTH; i++)
{
RFM_Write(0x00,*RFM_Package);
RFM_Package++;
}
//Switch RFM to TX
RFM_Write(0x01,0x83);
while(digitalRead(DIO0) == LOW)
{
//Wait for Tx Done
}
//Clear interrupt
RFM_Write(0x12,0x08);
//Set DIO0 to RxDone
RFM_Write(0x40,0x00);
//Set RFM in continues receive
RFM_Write(0x01,0x85);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
}
/* This function is used to receive a message/payload from the RFM module
* Arguments: *RFM_Package Pointer to the array with the data to send
*/
void RFM_ReadPackage(unsigned char *RFM_Package)
{
unsigned char RFM_Interrupt;
unsigned char RFM_PackageLocation;
//Get interrupt register
RFM_Interrupt = RFM_Read(0x12);
//Switch RFM to Standby
RFM_Write(0x01,0x81);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
//Clear interrupt register
RFM_Write(0x12,0x60);
//Get package location
RFM_PackageLocation = RFM_Read(0x10);
//Set SPI pointer to Packagelocation
RFM_Write(0x0D,RFM_PackageLocation);
//Get message
for(int i = 0; i < PACKAGE_LENGTH; i++)
{
*RFM_Package = RFM_Read(0x00);
RFM_Package++;
}
//Switch RFM to receive
RFM_Write(0x01,0x85);
while(digitalRead(DIO5) == LOW)
{
//Wait for mode ready
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment