Skip to content

Instantly share code, notes, and snippets.

@mrcodetastic
Created March 10, 2024 20:04
Show Gist options
  • Save mrcodetastic/7deb4724d89c1f0c882c53ff64e9c05e to your computer and use it in GitHub Desktop.
Save mrcodetastic/7deb4724d89c1f0c882c53ff64e9c05e to your computer and use it in GitHub Desktop.
/*
RadioLib SX127x Ping-Pong Example
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---lora-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
Customised for a ESP32 S3 'hat' that uses the following PIN mappings:
// SX127x
GPIO 3 for SX127x 'NSS' (Slave Select) PIN
GPIO 11 for SX127x 'DII00' PIN
GPIO 12 for SX127x 'Reset' PIN
GPIO 9 for SX127x SPI Clock Pin
GPIO 7 for SX127x SPI MISO Pin
GPIO 5 for SX127x SPI MOSI Pin
GPIO 3 for SX127x 'NSS' (Slave Select) PIN
// OLED Screen - One of these generic 128x32 ones from AliExpress
// https://www.aliexpress.com/item/1005005973981064.html?spm=a2g0o.productlist.main.1.5870g7JMg7JMYv
GPIO 33 for SDK (Clock)
GPIO 18 for SDA (Data)
// Set one of the devices to the transmitter by uncommenting 'MASTER_TRANSMIT_NODE' and the other as a reciever.
*/
// include the library
#include <RadioLib.h>
#include <Arduino.h>
#include <U8x8lib.h>
#include <Adafruit_NeoPixel.h>
// uncomment the following only on one
// of the nodes to initiate the pings
//#define MASTER_TRANSMIT_NODE
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 39 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 1 // Popular NeoPixel ring size
SPIClass spi(HSPI); // for esp32s2
// When we are NOT the transmitter
#ifndef MASTER_TRANSMIT_NODE
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE, /* clock=*/33, /* data=*/18); // pin remapping with ESP8266 HW I2C
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#endif
// SX1278 has the following connections:
// NSS pin: 10
// DIO0 pin: 2
// NRST pin: 9
// DIO1 pin: 3
SX1278 radio = new Module(3, 11, 12, RADIOLIB_NC, spi);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 radio = RadioShield.ModuleA;
// save transmission states between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate transmission or reception state
bool transmitFlag = false;
// flag to indicate that a packet was sent or received
volatile bool operationDone = false;
// this function is called when a complete packet
// is transmitted or received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we sent or received packet, set the flag
operationDone = true;
}
void blink_led() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(300);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
}
unsigned long last_packet_recieve_ms = 0;
unsigned long time_elapsed_ms_start = 0;
void setup() {
delay(3000);
Serial.begin(112500);
#ifdef MASTER_TRANSMIT_NODE
pinMode(LED_BUILTIN, OUTPUT);
#endif
// IF NOT the transmitter
#ifndef MASTER_TRANSMIT_NODE
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(0, 1, "Starting!");
u8x8.setInverseFont(1);
u8x8.drawString(0, 0, "012345678901234567890123456789");
u8x8.drawString(0, 3, "012345678901234567890123456789");
u8x8.setInverseFont(0);
//u8x8.drawString(0,8,"Line 8");
//u8x8.drawString(0,9,"Line 9");
// u8x8.refreshDisplay(); // only required for SSD1606/7
delay(1000);
u8x8.setInverseFont(0);
#endif
/*
for (int i = 0; i <3; i++)
{
Serial.println("Starting...");
delay(1000);
}
*/
Serial.println("Starting...");
spi.begin(9, 7, 5, 3);
// initialize SX1278 with default settings
Serial.print(F("[SX1278] Initializing ... "));
int state = radio.begin();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true)
;
}
// set output power to 10 dBm (accepted range is -3 - 17 dBm)
// NOTE: 20 dBm value allows high power operation, but transmission
// duty cycle MUST NOT exceed 1%
if (radio.setOutputPower(16) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) {
Serial.println(F("Selected output power is invalid for this module!"));
while (true)
;
}
// set the function that will be called
// when new packet is received
radio.setDio0Action(setFlag, RISING);
#if defined(MASTER_TRANSMIT_NODE)
// send the first packet on this node
Serial.print(F("[SX1278] Sending first packet ... "));
transmissionState = radio.startTransmit("Hello World!");
transmitFlag = true;
#else
// start listening for LoRa packets on this node
Serial.print(F("[SX1278] Starting to listen ... "));
state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true)
;
}
#endif
time_elapsed_ms_start = millis();
}
void loop() {
unsigned long time_elapsed_sec = (millis() - time_elapsed_ms_start) / 1000;
if ((millis() - last_packet_recieve_ms > 3000)) {
// send another one
Serial.print(F("[SX1278] Timeout occured, sending another packet ... "));
transmissionState = radio.startTransmit("You there?");
transmitFlag = true;
last_packet_recieve_ms = millis();
operationDone = true;
transmitFlag = true;
}
// check if the previous operation finished
if (operationDone) {
// reset flag
operationDone = false;
if (transmitFlag) {
// the previous operation was transmission, listen for response
// print the result
if (transmissionState == RADIOLIB_ERR_NONE) {
// packet was successfully sent
Serial.println(F("transmission finished!"));
#ifdef MASTER_TRANSMIT_NODE
blink_led();
#endif
last_packet_recieve_ms = millis();
} else {
Serial.print(F("failed, code "));
Serial.println(transmissionState);
}
// listen for response
radio.startReceive();
transmitFlag = false;
} else {
// the previous operation was reception
// print data and send another packet
String str;
int state = radio.readData(str);
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
Serial.println(F("[SX1278] Received packet!"));
#ifndef MASTER_TRANSMIT_NODE
blink_led();
#endif
// print data of the packet
Serial.print(F("[SX1278] Data:\t\t"));
Serial.println(str);
// print RSSI (Received Signal Strength Indicator)
Serial.print(F("[SX1278] RSSI:\t\t"));
float rssi = radio.getRSSI();
Serial.print(rssi);
Serial.println(F(" dBm"));
// print SNR (Signal-to-Noise Ratio)
Serial.print(F("[SX1278] SNR:\t\t"));
Serial.print(radio.getSNR());
Serial.println(F(" dB"));
#ifndef MASTER_TRANSMIT_NODE
u8x8.clearDisplay();
u8x8.drawString(0, 0, "Got packet!");
u8x8.drawString(0, 1, String(str).c_str());
char dbm_cstr[16];
snprintf(dbm_cstr, 15, "%.0f dBm", rssi);
u8x8.drawString(0, 2, dbm_cstr);
// Print Millis
u8x8.drawString(0, 3, String(time_elapsed_sec).c_str());
if (rssi > -50) {
// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color:
pixels.setPixelColor(0, pixels.Color(0, 192, 0));
} else if (rssi > -90) {
// orange
// https://www.w3schools.com/colors/colors_picker.asp
pixels.setPixelColor(0, pixels.Color(255, 153, 51));
} else {
pixels.setPixelColor(0, pixels.Color(192, 0, 0));
}
pixels.show(); // Send the updated pixel colors to the hardware.
#endif
}
// wait a second before transmitting again
delay(1000);
// send another one
Serial.print(F("[SX1278] Sending another packet ... "));
transmissionState = radio.startTransmit("Hello World!");
transmitFlag = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment