This RF ring oscillator runs on the Adafruit Feather board incorporates a ATSAMD21G18 ARM Cortex M0 processor, clocked at 48 MHz with a RFM95 Low Power Long Range Transceiver Module.
I used Adafruit's documentation to get the oscillator running using the Arduino IDE.
Code is included below. The oscilloscope output was generated by pulling a GPIO pin high while the radio sent a message and waited to verify delivery of the message. The round trip time was 127ms which equates to a frequency of 7.9Hz. This is pretty long in comparison to other modules that we've been testing however the real benefit of the LoRa Radio Module is it's capability over long ranges. Code for this measurement is included below.
The data sheet for the RFM95 has data which can be used to determine what the minimum round trip could be. Total time for a round trip could theoretically be 2*TS_HOP + TS_RE + TS_TR where TS_TR = 5us + 1.25*PaRamp + 0.5*TBit. These quantities are described below.
A potential round trip time of 2.5ms is vastly shorter than the 127ms measured in the experiment. The next step to minimise the apparent round trip time would be to pull out the functions being called from the various Arduino libraries into a single program, this would help to gain more transparency for the code that's actually being compiled and run. (To do this grep "FuntionName" *.*
is useful command for searching through multiple files from the command line). However the most exciting feature of these chips are there capability over long distances. Therefore the next step is to determine a test setup to quantify this capability.
The code below is used on both modules with two lines changed to enable the ring to start. The counter variable should be adjusted as described in the comment and the starting sequence should be uncommented, again as described in the comment in the code.
#include
#include
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 3
#define RF95_FREQ 915.0
#define FIRE 12
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
void setup()
{
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
while (!Serial);
Serial.begin(9600);
delay(100);
Serial.println("Feather LoRa TX 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);
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// The default transmitter power is 13dBm, using PA_BOOST.
// 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);
}
int counter = 1; // 1 for the starter, 0 for the follower
int message;
bool start = true;
void loop(){
// include for the starter, comment out for the follower
if(start == true){Serial.println("Starting");start = false;delay(2000);uint8_t data[] = "1";rf95.send(data, sizeof(data));rf95.waitPacketSent();}
// listen for a message, and add it to counter
if (rf95.available()){
// process the message, not sure whether the length check is necessary
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len)){
message = atoi((char*)buf);
char buf[20];
//Serial.print("Message = "); Serial.print(message); Serial.print(" Counter = "); Serial.println(counter);
// if the message is greater than counter, then add one and send back
if(message > counter){
counter += 2;
itoa(counter, buf, 10);
digitalWrite(FIRE,HIGH);
rf95.send((uint8_t*)buf,20);
rf95.waitPacketSent();
//delay(1);
digitalWrite(FIRE,LOW);
//Serial.print("Message = "); Serial.print(message); Serial.print(" Counter = "); Serial.println(counter);
}
}
}
}