Using the “Wio-SX1262 for XIAO” to easily build LoRa point-to-point communication with various XIAOs

Hi there,

So I got the Open Receiver code up on the Dev Expansion Board, Displays “Beacon Message” on first line and is sent in // REV 5.5b - SX1262 Beacon Sender with LED + Button + Power Modes // Posted below.
Press the button to send message with different power levels…
on the Sender (beacon) intervals of 2 dB Transmit power. Watch display on Open receiver and note the RSSI & SNR .
(next experiment will be a press button on each end to change modes.)
OPEN Receiver:

// REV 5.6n - SX1262 Open Receiver with OLED Display
// Board: ESP32-S3 with SX1262 LoRa Module + OLED (XIAO Expansion Board)
// Receives LoRa messages and displays: 
//   1) Beacon Message (1st line)
//   2) RSSI and SNR values (formatted & centered)
//   3) Blinks onboard LED (GPIO 48) on message reception
//   4) Serial output stays consistent with previous 5.5b version

#include <RadioLib.h>
#include <Wire.h>
#include <U8g2lib.h>

// SX1262 Module Pins: NSS, DIO1, RST, BUSY
SX1262 radio = new Module(41, 39, 42, 40);

// OLED: I2C (128x64), flipped orientation (USB on right side)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE);

// LED for RX activity
const int LED_PIN = 48;

// Last received values for change detection
float lastRSSI = 0;
float lastSNR = 0;
String lastMsg = "";

// Thresholds for display update
const float RSSI_THRESHOLD = 0.25;
const float SNR_THRESHOLD = 0.25;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Serial.begin(115200);
  delay(500);
  Serial.println();
  Serial.println(F("// REV 5.6n - SX1262 Open Receiver with OLED Display"));
  Serial.println(F("// Board: ESP32-S3 with SX1262 LoRa Module + OLED"));
  Serial.print(F("Initializing SX1262 LoRa radio... "));

  if (radio.begin() != RADIOLIB_ERR_NONE) {
    Serial.println(F("FAILED!"));
    while (true);
  }
  Serial.println(F("SUCCESS!"));
  Serial.println(F("Listening for LoRa messages..."));

  // LoRa radio config
  radio.setOutputPower(22);
  radio.setSpreadingFactor(7);
  radio.setBandwidth(125.0);
  radio.setCodingRate(5);

  // OLED startup screen
  display.begin();
  display.setFlipMode(1);  // Flip vertically for correct orientation
  display.clearBuffer();
  display.setFont(u8g2_font_6x12_tf);
  display.setCursor(0, 12);
  display.print("SX1262 Open Receiver");
  display.setCursor(0, 28);
  display.print("XIAO S3 + OLED");
  display.setCursor(0, 44);
  display.print("REV 5.6n");
  display.sendBuffer();
  delay(2000);

  // Initial Listening Screen
  display.clearBuffer();
  display.setCursor(0, 12);
  display.print("Listening...");
  display.sendBuffer();
}

void loop() {
  String msg;
  int state = radio.receive(msg);

  if (state == RADIOLIB_ERR_NONE) {
    float rssi = radio.getRSSI();
    float snr = radio.getSNR();
    bool updated = false;

    if (msg != lastMsg) {
      Serial.print("Received: ");
      Serial.println(msg);
      lastMsg = msg;
      updated = true;
    }

    if (abs(rssi - lastRSSI) > RSSI_THRESHOLD || abs(snr - lastSNR) > SNR_THRESHOLD) {
      Serial.print("  RSSI: ");
      Serial.print(rssi, 2);
      Serial.print(" dBm\tSNR: ");
      Serial.print(snr, 2);
      Serial.println(" dB");
      lastRSSI = rssi;
      lastSNR = snr;
      updated = true;
    } else {
      Serial.print(".");
    }

    if (updated) {
      display.clearBuffer();
      display.setFont(u8g2_font_6x12_tf);
      display.setCursor(0, 12);
      display.print(lastMsg);  // Line 1

      display.setCursor(0, 28);
      display.print("  RSSI    -    SNR");  // Line 3

      display.setFont(u8g2_font_7x13B_tf);
      display.setCursor(10, 44);
      display.printf("%.0f", lastRSSI);
      display.setCursor(74, 44);
      display.printf("%.2f", lastSNR);

      display.setFont(u8g2_font_6x12_tf);
      display.setCursor(15, 60);
      display.print("dBm");
      display.setCursor(86, 60);
      display.print("dB");

      display.sendBuffer();
    }

    digitalWrite(LED_PIN, HIGH);
    delay(30);
    digitalWrite(LED_PIN, LOW);
  }
}

Serial output for receiver ;


// REV 5.6n - SX1262 Open Receiver with OLED Display
// Board: ESP32-S3 with SX1262 LoRa Module + OLED
Initializing SX1262 LoRa radio... SUCCESS!
Listening for LoRa messages...
Received: Seeed Studio
  RSSI: -125.00 dBm	SNR: -9.25 dB

// REV 5.6n - SX1262 Open Receiver with OLED Display
// Board: ESP32-S3 with SX1262 LoRa Module + OLED
Initializing SX1262 LoRa radio... SUCCESS!
Listening for LoRa messages...
Received: Seeed Studio
  RSSI: -125.00 dBm	SNR: -8.75 dB
.  RSSI: -125.00 dBm	SNR: -9.25 dB
  RSSI: -125.00 dBm	SNR: -8.75 dB
.  RSSI: -125.00 dBm	SNR: -9.25 dB
...  RSSI: -125.00 dBm	SNR: -8.50 dB
  RSSI: -125.00 dBm	SNR: -9.25 dB
  RSSI: -126.00 dBm	SNR: -9.50 dB
.  RSSI: -125.00 dBm	SNR: -9.25 dB
..  RSSI: -126.00 dBm	SNR: -9.50 dB
  RSSI: -125.00 dBm	SNR: -9.25 dB
  RSSI: -126.00 dBm	SNR: -9.50 dB
  RSSI: -126.00 dBm	SNR: -10.50 dB
  RSSI: -125.00 dBm	SNR: -8.75 dB
  RSSI: -126.00 dBm	SNR: -9.75 dB
.  RSSI: -125.00 dBm	SNR: -8.50 dB
  RSSI: -125.00 dBm	SNR: -9.00 dB
.
  RSSI: -115.00 dBm	SNR: 1.25 dB
  RSSI: -115.00 dBm	SNR: 1.75 dB
  RSSI: -115.00 dBm	SNR: 1.25 dB
  RSSI: -113.00 dBm	SNR: 3.50 dB
  RSSI: -117.00 dBm	SNR: -0.50 dB
  RSSI: -114.00 dBm	SNR: 2.00 dB
.....  RSSI: -114.00 dBm	SNR: 2.50 dB
  RSSI: -114.00 dBm	SNR: 2.00 dB
..  RSSI: -115.00 dBm	SNR: 1.25 dB
  RSSI: -114.00 dBm	SNR: 1.75 dB
  RSSI: -116.00 dBm	SNR: 0.25 dB
  RSSI: -114.00 dBm	SNR: 2.25 dB
.....  RSSI: -114.00 dBm	SNR: 1.75 dB
  RSSI: -115.00 dBm	SNR: 1.25 dB
  RSSI: -114.00 dBm	SNR: 2.00 dB
.....  RSSI: -113.00 dBm	SNR: 2.50 dB
  RSSI: -114.00 dBm	SNR: 2.00 dB
..  RSSI: -114.00 dBm	SNR: 2.50 dB
..  RSSI: -113.00 dBm	SNR: 2.75 dB
  RSSI: -114.00 dBm	SNR: 2.50 dB
.  RSSI: -114.00 dBm	SNR: 2.00 dB
  RSSI: -114.00 dBm	SNR: 2.50 dB
....  RSSI: -115.00 dBm	SNR: 1.00 dB
  RSSI: -113.00 dBm	SNR: 3.00 dB
  RSSI: -110.00 dBm	SNR: 5.75 dB
  RSSI: -108.00 dBm	SNR: 7.00 dB
...............................  RSSI: -109.00 dBm	SNR: 6.25 dB
  RSSI: -108.00 dBm	SNR: 7.25 dB
  RSSI: -109.00 dBm	SNR: 6.50 dB
.  RSSI: -108.00 dBm	SNR: 6.75 dB
.  RSSI: -109.00 dBm	SNR: 6.25 dB
  RSSI: -108.00 dBm	SNR: 7.25 dB
................  RSSI: -107.00 dBm	SNR: 7.25 dB
  RSSI: -109.00 dBm	SNR: 6.25 dB
  RSSI: -108.00 dBm	SNR: 7.25 dB
..  RSSI: -108.00 dBm	SNR: 6.75 dB
.  RSSI: -109.00 dBm	SNR: 7.00 dB
..  RSSI: -108.00 dBm	SNR: 6.50 dB
.  RSSI: -108.00 dBm	SNR: 7.00 dB
.................

Beacon Sender…:


// REV 5.5b - SX1262 Beacon Sender with LED + Button + Power Modes
// Board: ESP32-S3 with SX1262 LoRa Module
// Sends "Seeed Studio" as beacon every 5 seconds
// LED on GPIO 48 blinks on TX
// Button on GPIO 21 cycles TX power level (2 to 22 dBm)

#include <RadioLib.h>

#define NSS     41
#define DIO1    39
#define RST     42
#define BUSY    40
#define LED_PIN 48
#define BTN_PIN 21

SX1262 radio = new Module(NSS, DIO1, RST, BUSY);

const char beaconMessage[] = "Seeed Studio";
int txPower = 22;
unsigned long lastSendTime = 0;
const unsigned long beaconInterval = 5000;

int lastButtonState = HIGH;
bool firstPrint = true;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP);
  digitalWrite(LED_PIN, LOW);

  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("// REV 5.5b - SX1262 Beacon Sender");
  Serial.println("// Board: ESP32-S3 with SX1262 LoRa Module");
  Serial.print("Initializing SX1262 LoRa radio... ");

  if (radio.begin() != RADIOLIB_ERR_NONE) {
    Serial.println("FAILED!");
    while (true);
  }

  Serial.println("SUCCESS!");
  radio.setOutputPower(txPower);
  radio.setSpreadingFactor(7);
  radio.setBandwidth(125.0);
  radio.setCodingRate(5);

  Serial.print("TX Power: ");
  Serial.print(txPower);
  Serial.println(" dBm");
  Serial.println("Beacon message: \"Seeed Studio\"");
  Serial.println("Transmitting every 5 seconds...\n");
}

void loop() {
  unsigned long now = millis();

  // Button handling to change TX power
  int btnState = digitalRead(BTN_PIN);
  if (btnState == LOW && lastButtonState == HIGH) {
    txPower += 2;
    if (txPower > 22) txPower = 2;
    radio.setOutputPower(txPower);
    Serial.print("\nTX Power changed to: ");
    Serial.print(txPower);
    Serial.println(" dBm");
    delay(250);  // debounce
  }
  lastButtonState = btnState;

  // Send beacon every interval
  if (now - lastSendTime >= beaconInterval) {
    lastSendTime = now;

    digitalWrite(LED_PIN, HIGH);
    int state = radio.transmit(beaconMessage);
    digitalWrite(LED_PIN, LOW);

    if (state == RADIOLIB_ERR_NONE) {
      if (firstPrint) {
        Serial.print("Sent: ");
        Serial.println(beaconMessage);
        firstPrint = false;
      } else {
        Serial.print(".");
      }

      static int dotCount = 0;
      dotCount++;
      if (dotCount % 80 == 0) Serial.println();
    } else {
      Serial.print("Transmit failed, code ");
      Serial.println(state);
    }
  }
}

Sender Serial Output.:

// REV 5.5b - SX1262 Beacon Sender
// Board: ESP32-S3 with SX1262 LoRa Module
Initializing SX1262 LoRa radio... SUCCESS!
TX Power: 22 dBm
Beacon message: "Seeed Studio"
Transmitting every 5 seconds...

Sent: Seeed Studio
...............................................................................
................................................................................
................................................................................
.......................................................................
TX Power changed to: 2 dBm
.........
.
TX Power changed to: 4 dBm
.....
TX Power changed to: 6 dBm
...
TX Power changed to: 8 dBm
..........
TX Power changed to: 10 dBm
....
TX Power changed to: 12 dBm
.............................................
TX Power changed to: 14 dBm

TX Power changed to: 16 dBm
.
TX Power changed to: 18 dBm

TX Power changed to: 20 dBm

TX Power changed to: 22 dBm
...
TX Power changed to: 2 dBm
........
................................................................................
........................................................
// REV 5.5b - SX1262 Beacon Sender
// Board: ESP32-S3 with SX1262 LoRa Module
Initializing SX1262 LoRa radio... SUCCESS!
TX Power: 22 dBm
Beacon message: "Seeed Studio"
Transmitting every 5 seconds...

Sent: Seeed Studio
...............................................................................
...................................

Starts at 22 dBm , press button goes to 2,4,6,8, etc…

HTH
GL :slight_smile: PJ :v:
Like, Share and subscribe… LOL

A point-to-point long distance communication experiment was carried out with XIAO_MG24 mounted on Wio-SX1262 for XIAO. The main parameters are: frequency 922.6[MHz], Txpower=13[dBm], bw=125[kHz], sf=12, cr=5, antenna λ/2.
Stable communication was achieved with RSSI=-127[dBm] and SNR=-15[dB] over a line of sight of 24.5[km].

This was the same as the results of the experiment with LoRa-E5 mini shown in the link below.

Here is the sketch I used for the experiment. The sketch should be easily modified for other XIAOs.
POST_SX1262_MG24_P2P.zip (8.5 KB)

1 Like

Hi there,

Bro , the Use of the cardboard is simply BAdA$$, :muscle: man way to use what you got :+1: just shows with some vision what one can achieve… :bowing_man:

GL :slight_smile: PJ :v:

Are those Seeed Studio Antennas? on web site?

Nice Pigtails… and I dont mean your hair…

Have you tried LoRa Board with Round Display… I dont think it will work because they use the SPI bus?.. also GPS mated? also Graphics Driver Issue I wonder if a Daughter Board could be created to remap pins between layers

the ESP32S3 may work with a IIC GPS

I dont know if meshtastic supports color display

Hi there,

Round will work, Just needs correct config on the buss. the new unit is good that it uses the B2B connector. Someone posted they had it working with the Clock Demo, but I never saw any code, so YMMV :lying_face:
I don’t see a reason it wouldn’t in present form WIO-SX1262 & S3 :+1:
The open Receiver code demo uses the Dev expansion board OLED straight away no issues. Same with Grove Expansion with the SD1306 I2C Cheep display.

I’ll wack & Chop something up for it, eventually.
HTH
GL :slight_smile: PJ :v:

The antenna was included with the LoRa-E5 mini.

Remembering my granddaughter’s craft, I fixed the antenna with cardboard.
It was enough for about an hour of experimentation.

1 Like

There was a problem with interrupts during reception, so the sketch has been updated.

POST_SX1262_MMG24_P2P_1.zip (8.5 KB)

There are sketches for long distance communication experiments with various XIAOs.I think these will work with any master/slave combination.
If you are interested, please use them.

SX1262_XIAOs_P2P_MasterSlave.zip (46.2 KB)

2 Likes

Yes, the Round Display does indeed work with the Wio-SX1262 module and ESP32S3, at least when using the B2B connector. I unfortunately no longer have the code to share but it is very easy to re-create what I did, just add the LoRa commands to any given round display sketch. Using the TFT_Clock example from the TFT_eSPI library, I simply added in the appropriate Radiolib commands to transmit a packet every x seconds. No changes were made to the usual LoRa config or to the existing code in the TFT_Clock sketch, it seemed to just work right off the bat. Both the display and touch input worked properly. You just have to make sure that you do not throw a transmit or receive interrupt while drawing to the display, or else you’ll get random garbage on the screen.

1 Like

Hi Crusty, I tried what you advise above. I have a pair of Xiao esp32-s3s with wio 1262 boards on the header connectors. I loaded ping pong sketches into both and was previously getting RSSI values of -100 dBm or lower with antennas very close. I now get RSSIs of -70 dBm or so, which is an improvement, but nothing like the figures you appear to be getting.

Wondering if there is anything else you are doing… I tried the same experiment with a pair of Heltec v3s and got RSSIs of about -10dBm which is what you would expect, and what you were getting…

ctho_admin,

Are you switching the RF switch to receive mode when receiving?

#define RF_SW Dxx          // RF_SW HIGH:Rx, LOW:default Tx

pinMode(RF_SW, OUTPUT);    // RF_SW
digitalWrite(RF_SW, HIGH); // Receive mode

Has anyone else had problems with power consumption or sleep mode using an Xiao NRF52840 + Wio SX1262 combo?

I’ve been supplying 3.7 V to the battery pads of the NRF52480 mounted on the WIO-SX1262 using the PPK2 and this sketch.


#include <Wire.h>
#include <Arduino.h>
#include <Adafruit_TinyUSB.h>
#include <RadioLib.h>

#define HICHG 22            // Charge current Hi:50mA Lo:100mA       D22 (13u)
#define CHG 23              // Charge LED Lo:ON                       D23 (17u)
#define VBAT_ENABLE 14      // Battery voltage read enable  Lo:enable D14 (14u)
#define VBAT_READ 32        // Battery voltage read pin               D32 (31u)
#define RF_SW   D5          // WIO-SX1262 RF Switch


SPIClass SPI_2(NRF_SPIM2, PIN_QSPI_IO1, PIN_QSPI_SCK, PIN_QSPI_IO0);
SX1262 radio = new Module(/*NSS*/D4, /*DIO1*/D1, /*NRST*/D2, /*BUSY*/D3);

void blink(uint8_t times, uint32_t pin)
{
  for (int i = 0; i < times; i++)
    {
      digitalWrite(pin, LOW);
      delay(200);
      digitalWrite(pin, HIGH);
      delay(200);
    }
}

void errorBlink(uint8_t err)
{
  while (true)
  {
    blink(err, LED_RED);
    delay(500);
  }
}

void flashAll(){
  digitalWrite(LED_RED, LOW);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_BLUE, LOW);
  delay(100);
  digitalWrite(LED_RED, HIGH);
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(LED_BLUE, HIGH);
}

void setup()
{
  NRF_POWER->DCDCEN = 1; // Enable DC/DC converter for REG1 stage

  // Pin initialization
  pinMode(VBAT_READ, INPUT);
  pinMode(CHG, INPUT_PULLUP);
  pinMode(HICHG, OUTPUT);
  pinMode(VBAT_ENABLE, OUTPUT);

  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);

  pinMode(PIN_QSPI_CS, OUTPUT);  // CS#
  pinMode(PIN_QSPI_IO2, OUTPUT); // WP#
  pinMode(PIN_QSPI_IO3, OUTPUT); // HOLD#

  digitalWrite(HICHG, LOW);       // Charge current 100mA
  digitalWrite(VBAT_ENABLE, HIGH); // Battery voltage read enable, only enable during measuring

  digitalWrite(LED_RED, HIGH);   
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(LED_BLUE, HIGH);

  digitalWrite(PIN_QSPI_CS, HIGH);
  digitalWrite(PIN_QSPI_IO2, HIGH);
  digitalWrite(PIN_QSPI_IO3, HIGH);

  SPI_2.begin();
    digitalWrite(PIN_QSPI_CS, LOW);
    SPI_2.transfer(0xB9);           // 0xB9 enter Deep Power-down
    digitalWrite(PIN_QSPI_CS, HIGH);
  SPI_2.end();  


  int state = radio.begin(922.6, 125.0, 12, 5, 0x12, 13, 8, 1.7, 0);

  if (state != RADIOLIB_ERR_NONE) {
    errorBlink(4);
  }

  radio.sleep();
}

void loop()
{
  flashAll();
  delay(2000);
}

As a baseline this is the power consumption without the wio (after removing the radio.begin() and error check):

About 4uA very nice!
Now with the wio mounted and the proper radio.begin() but without radio.sleep()

About 1mA, seems plausible since the radio is powered and idle.
But now with radio.sleep():

Well, this is unexpected. The consumption becomes very “noisy.” The upper range is the same as it is without radio.sleep(), but the lower range drops drastically.
After reading this, I tried pulling up the NSS-Pin with a 10K resistor, but there was no difference.
Can anyone chime in? Am I missing something obvious?

Hi there,

Looking good so far… :v: So which BSP are you using?
also which version of Radio.LIB is that?

GL :slight_smile: PJ :v:

Is nRF52 in sleep mode?
If nRF52 is not in sleep mode, I think the current consumption may not decrease due to frequent access to SX1262. What happens
if nRF52 is also put into sleep mode?

@PJ_Glasso
Normally i use Platformio, but i´ve verified the exact same behaviour with Arduino IDE and BSP: 1.1.10
Radiolib Version is: 7.2.1

@msfujino
I´ve added a NRF_POWER->SYSTEMOFF = 1; at the end of setup():

You seem to be right! Power goes down to 3uA so the radio is definitely sleeping! But how can I achieve the same with light sleep? I would strongly prefer to use light sleep instead of deep sleep if possible.

From the perspective of the WIO, isn’t the only difference between light sleep and deep sleep that light sleep keeps the pin states? Do I need to pull the SPI pins low prior to delay()?

1 Like
radio.sleep();
SPI.end();.

This should reduce consumption to around 5uA in LightSleep mode.

2 Likes

Works like a charm! Thank you very much!
Now I just have to check how the radio/radiolib is handling re-starting the SPI after SPI.end(). I will start with SPI.begin() + radio.standby() and check if everything is working as expected.