Last active
September 19, 2024 14:43
-
-
Save SyncChannel/30fcedae57075484f9c0 to your computer and use it in GitHub Desktop.
LoRa_FeatherWing_DevBreakout_BeaconMode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* LoRa FeatherWing Beacon Mode Example Program | |
* By: Dan Watson | syncchannel.blogspot.com | |
* Date: 2-23-2016 | |
* Version: 0.2 | |
* | |
* Example Beacon 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 transmit-only beacon. It transmits a payload of data | |
* at a set interval using the LoRa long range wireless protocol. This program is intended as | |
* a companion to the LoRA FeatherWing Tranceiver Example Program, which can receive the | |
* beacon transmissions. | |
* | |
* 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 | |
// Test variables so that we have something to send in beacon mode transmissions | |
uint8_t testCounter = 0; | |
uint8_t testCounterRollover = 0; | |
// Holder for the user data payload bytes | |
uint8_t RFM_Tx_Package[PACKAGE_LENGTH]; | |
void setup() | |
{ | |
//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); | |
// Load some random data into the payload. Only the lower two bytes will be updated with the count | |
RFM_Tx_Package[0] = 0xFF; | |
RFM_Tx_Package[1] = 0xFF; | |
RFM_Tx_Package[2] = 0x00; | |
RFM_Tx_Package[3] = 0x00; | |
RFM_Tx_Package[4] = 0x01; | |
RFM_Tx_Package[5] = 0x4B; | |
RFM_Tx_Package[6] = 0x23; | |
RFM_Tx_Package[7] = 0x00; | |
RFM_Tx_Package[8] = testCounterRollover; | |
RFM_Tx_Package[9] = testCounter; | |
//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() | |
{ | |
uint32_t gotMillis = millis() + 5000; | |
digitalWrite(LED, HIGH); | |
// Update the payload contents with the count | |
RFM_Tx_Package[8] = testCounterRollover; | |
RFM_Tx_Package[9] = testCounter; | |
// Send the payload! | |
RFM_SendPackage(RFM_Tx_Package); | |
// At higher Spreading Factors, the transmission takes long enough to make the LED blink visible | |
// Add a slight delay if you want the LED notification of a transmission to be longer | |
// delay(50); | |
digitalWrite(LED, LOW); | |
testCounter++; | |
if (testCounter == 0) | |
testCounterRollover++; | |
while(gotMillis > millis()) | |
{ | |
// Make the main loop take five seconds to complete every time | |
// Include small delay to prevent the watchdog from timing out on HUZZAH ESP8266 | |
delay(10); | |
} | |
} | |
/* | |
* 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