Last active
August 4, 2026 22:16
-
-
Save Tech500/73ff160249ff1eec437cc68712aa884c to your computer and use it in GitHub Desktop.
SX1262 with Channel Activity Detection-Wake-on-Radio-Deep Sleep
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
| #define EoRa_PI_V1 | |
| #include <RadioLib.h> | |
| #include <boards.h> | |
| #include <SPI.h> | |
| #include "driver/rtc_io.h" | |
| // --- Pin Definitions | |
| //Using Ebyte's EoRa-S3-900TB Configuration files | |
| #define WAKEUP_PIN GPIO_NUM_16 | |
| const float radioFreq = 915.0; // MHz | |
| const float bandWidth = 125.0; // kHz | |
| const uint8_t spreadingFactor = 7; | |
| const uint8_t codingRate = 7; | |
| const uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE; | |
| SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); | |
| // flag to indicate that a packet was detected or CAD timed out | |
| volatile bool scanFlag = false; | |
| // this function is called when a complete packet | |
| // is received by the module | |
| // IMPORTANT: this function MUST be 'void' type | |
| // and MUST NOT have any arguments! | |
| #if defined(ESP8266) || defined(ESP32) | |
| ICACHE_RAM_ATTR | |
| #endif | |
| void setFlag(void) { | |
| // something happened, set the flag | |
| scanFlag = true; | |
| } | |
| void setupLoRa() { | |
| SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN, RADIO_CS_PIN); | |
| radio.standby(); | |
| delay(50); | |
| radio.resetOnStartup = true; | |
| delay(50); | |
| radio.tcxoVoltage = 1.6; // Crucial 1.6V reference for Ebyte modules | |
| int state = radio.begin( | |
| radioFreq, | |
| 125.0, | |
| 7, | |
| 7, | |
| RADIOLIB_SX126X_SYNC_WORD_PRIVATE, | |
| 2, | |
| 5000, // <--- SET PREAMBLE TO 5000 TO MATCH TRANSMITTER | |
| 1.6, | |
| false | |
| ); | |
| if (state == RADIOLIB_ERR_NONE) { | |
| radio.setRegulatorDCDC(); | |
| // Force explicit 5000 symbol preamble configuration | |
| radio.setPreambleLength(5000); | |
| Serial.println(F("[SX1262] Battery Receiver Initialized with 5000-symbol Preamble.")); | |
| } else { | |
| Serial.printf("[SX1262] Initialization failed, code %d\n", state); | |
| } | |
| } | |
| // --- Your 10-Pass Diagnostic Logic repurposed as a Filter --- | |
| bool verifySignalWithBusyLoop(int totalPasses = 10, int requiredHits = 3) { | |
| Serial.println(F("\n--- [WAKE DIAGNOSTIC & MULTI-SCAN START] ---")); | |
| // 1. Verify Sleep Wakeup Reason | |
| esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); | |
| Serial.printf(" Wakeup Cause Code: %d ", wakeup_reason); | |
| if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT0) { | |
| Serial.println(F("(ESP_SLEEP_WAKEUP_EXT0 - DIO1 High)")); | |
| } else { | |
| Serial.println(F("(Other Wakeup Reason / Cold Boot)")); | |
| } | |
| // 2. Read Physical Pins at Boot | |
| int dio1State = digitalRead(WAKEUP_PIN); | |
| int busyState = digitalRead(RADIO_BUSY_PIN); | |
| Serial.printf(" Pin Levels at Boot -> DIO1 (GPIO %d): %d | BUSY (GPIO %d): %d\n", | |
| RADIO_DIO1_PIN, dio1State, RADIO_BUSY_PIN, busyState); | |
| // 3. Query Radio Internal IRQ Flags | |
| uint16_t irqFlags = radio.getIrqFlags(); | |
| Serial.printf(" SX1262 Internal IRQ Register: 0x%04X\n", irqFlags); | |
| if (irqFlags & RADIOLIB_SX126X_IRQ_CAD_DETECTED) { | |
| Serial.println(F(" [IRQ CHECK] -> RADIOLIB_SX126X_IRQ_CAD_DETECTED is SET!")); | |
| } | |
| if (irqFlags & RADIOLIB_SX126X_IRQ_HEADER_VALID) { | |
| Serial.println(F(" [IRQ CHECK] -> RADIOLIB_SX126X_IRQ_HEADER_VALID is SET!")); | |
| } | |
| //esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); | |
| if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT0) { | |
| Serial.println("Woke from hub WOR -- reading and sending BME280 data"); | |
| digitalWrite(BOARD_LED, LED_ON); | |
| } | |
| return false; | |
| } | |
| void enterLowPowerWOR() { | |
| radio.clearIrqFlags(RADIOLIB_SX126X_IRQ_ALL); | |
| int state = radio.startReceiveDutyCycleAuto( | |
| 5000, | |
| 0, | |
| RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | | |
| RADIOLIB_SX126X_IRQ_HEADER_VALID | | |
| RADIOLIB_SX126X_IRQ_RX_DONE, | |
| RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | | |
| RADIOLIB_SX126X_IRQ_HEADER_VALID | | |
| RADIOLIB_SX126X_IRQ_RX_DONE | |
| ); | |
| if (state != RADIOLIB_ERR_NONE) { | |
| Serial.printf("[SX1262] DutyCycleAuto failed, code: %d\n", state); | |
| return; | |
| } | |
| // DIO1 = GPIO16, already defined by EoRa board file | |
| pinMode(WAKEUP_PIN, INPUT); | |
| // EXT0 is level triggered | |
| // SX1262 DIO1 goes HIGH on interrupt | |
| esp_sleep_enable_ext0_wakeup(WAKEUP_PIN, 1); | |
| Serial.printf("DIO1 GPIO %d before sleep = %d\n", | |
| WAKEUP_PIN, | |
| digitalRead(WAKEUP_PIN)); | |
| Serial.println(F( | |
| "=== SX1262 WOR armed - ESP32-S3 entering deep sleep ===" | |
| )); | |
| Serial.flush(); | |
| esp_deep_sleep_start(); | |
| } | |
| void setup() { | |
| initBoard(); | |
| delay(1500); | |
| Serial.begin(115200); | |
| delay(1500); // Give CDC Serial monitor time to connect | |
| Serial.println(F("\n==============================================")); | |
| Serial.println(F("--- ESP32-S3 WOR NODE (BOOT DIAGNOSTIC) ---")); | |
| // 1. Initialize Radio SPI & SX1262 | |
| setupLoRa(); | |
| // 2. ALWAYS run diagnostic on boot to verify pin states and test CAD | |
| Serial.println(F("Executing mandatory boot-up radio diagnostic...")); | |
| verifySignalWithBusyLoop(10, 3); | |
| // 3. Enter WOR Sleep | |
| enterLowPowerWOR(); | |
| } | |
| void loop() { | |
| // Unused | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment