Skip to main content

Working with ESP32S3

This chapter contains the following sections. Please read as needed:

Setting Up Development Environment

1. Installation and Configuration

  • For setting up the ESP32S3 environment and basic usage, please refer to the following links:
  • Once the environment is set up, you can connect the LoRa module and download the example programs

Hardware Connection

Connect according to the table below.

Core2021-XFESP32S3
CLK40
MISO46
MOSI45
CS42
DIO1138
RESET39
BUSY41

Example

  • ESP32S3 example programs are located in the core2021-xf\examples\esp32s3 directory of the example package.
  • Examples 01, 02, and 03 require two Core2021-XF modules: one for transmission and one for reception.
ExampleBasic DescriptionDependency Library
01_lr2021_txLR2021 TransmitRadioLib
02_lr2021_rxLR2021 ReceiveRadioLib
03_lr2021_pingpongLR2021 Ping‑PongRadioLib
04_lr2021_tx_cwLR2021 CW Mode TransmitRadioLib
05_lr2021_LoRaWANLoRaWANRadioLib

Run Arduino ESP32 Example

  • Navigate to core2021-xf\examples\esp32s3\arduino and select the example program you wish to test.
  • Select the development board:
    ESP32-S3
  • Select the port for the ESP32S3, then compile and upload.
  • After the upload is completed, open the serial port monitor, and the relevant information will be output.

01_lr2021_tx

Example Description

  • Based on the ESP32S3 + Core2021-XF module, implements periodic LoRa packet transmission using interrupts.
  • Custom SPI pins (CLK/MOSI/MISO) to match the ESP32S3 hardware design.
  • Uses non‑blocking transmission, does not occupy CPU resources in the main loop.
  • After each packet is sent, automatically delays 1 second before sending the next packet.
  • Supports string data transmission, with a built‑in packet sequence number for easy debugging.

Code Analysis

  • SPI.begin(...): Initializes ESP32S3 hardware SPI pins with custom CLK/MOSI/MISO.
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin; must be set before initialization.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure frequency accuracy.
  • setFlag(void): Interrupt callback function triggered automatically after the module finishes transmission, sets a transmission‑complete flag.
  • radio.setPacketSentAction(setFlag): Binds the transmission‑complete interrupt function.
  • radio.startTransmit("content"): Starts asynchronous LoRa transmission (supports string / byte array).
  • radio.finishTransmit(): Cleanup after transmission, turns off the transmit circuit and resets the module state.
  • loop() main logic: Check transmission‑complete flag → print status → delay → send next packet with sequence number.

Operation Result

  • After compiling and uploading, open the serial monitor to see logs indicating transmission completion, as shown below (in combination with 02_lr2021_rx):

02_lr2021_rx

Example Description

  • Based on the ESP32S3 + Core2021-XF module, implements wireless LoRa packet reception using interrupts.
  • Custom hardware SPI pins to match the ESP32S3 hardware design.
  • Uses non‑blocking listening mode; the module automatically waits for data without consuming CPU resources.
  • After successful reception, automatically parses the data and prints the packet content, RSSI, and SNR.
  • The same frequency, spreading factor, bandwidth, and coding rate must be configured on both the transmitter and receiver for successful communication.

Code Analysis

  • SPI.begin(...): Initializes ESP32S3 hardware SPI with custom CLK/MOSI/MISO pins.
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin; must be set before initialization.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure frequency accuracy and improve reception stability.
  • setFlag(void): Interrupt callback function triggered automatically after a complete packet is received.
  • radio.setPacketReceivedAction(setFlag): Binds the reception‑complete interrupt service function.
  • radio.startReceive(): Starts continuous LoRa reception mode, enters a data‑waiting state.
  • radio.readData(str): Reads the received wireless data (supports string parsing).
  • radio.getRSSI() / radio.getSNR(): Retrieves signal quality parameters for debugging and link evaluation.
  • loop() main logic: Check reception‑complete flag → read data → parse and print → continue listening.

Operation Result

  • After compiling and uploading, open the serial monitor to see real‑time reception logs including data content, RSSI, and SNR, as shown below (in combination with 01_lr2021_tx):

03_lr2021_pingpong

Example Description

  • Based on the ESP32S3 + Core2021-XF module, implements LoRa automatic ping‑pong (question‑answer) two‑way communication.
  • Custom hardware SPI pins to match the ESP32S3 hardware design.
  • Two modules can send and receive to each other without manual control.
  • Enabling INITIATING_NODE sets the module as the initiator; the other module acts as the responder.
  • Automatically switches between transmit and receive states, driven by non‑blocking interrupts.

Code Analysis

  • SPI.begin(...): Initializes ESP32S3 hardware SPI with custom CLK/MOSI/MISO pins.
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin; must be set before initialization.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure communication frequency accuracy.
  • setFlag(void): General interrupt callback, triggered on either transmit or receive completion.
  • radio.setIrqAction(setFlag): Binds the shared transmit/receive interrupt function.
  • INITIATING_NODE macro: Used to distinguish the initiating node.
  • radio.startTransmit(): Starts packet transmission.
  • radio.startReceive(): Switches the module to listening (receive) mode.
  • radio.readData(str): Reads the received LoRa packet.
  • loop() main logic: Transmit complete → enter receive; receive complete → delay reply → transmit again.

Operation Result

  • Flash the program onto two modules, enabling the INITIATING_NODE macro on one of them.
  • After power‑on, they automatically send and receive to each other; the serial monitor prints the transmit/receive status, data, RSSI, and SNR, as shown below:

04_lr2021_tx_cw

Example Description

  • Based on the ESP32S3 + Core2021-XF module, implements LoRa continuous wave (CW) / direct transmit.
  • Custom SPI pins to match the ESP32S3 hardware design.
  • Outputs a fixed‑frequency carrier signal without packet formatting, used for band testing, signal detection, and instrument calibration.
  • Fixed frequency 868 MHz, transmit power 22 dBm.
  • Upon power‑up, transmits continuously with no additional logic.

Code Analysis

  • SPI.begin(...): Initializes ESP32S3 hardware SPI with custom CLK/MOSI/MISO pins.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure carrier frequency accuracy.
  • OUT_HZ 868000000UL: Defines the direct transmit frequency (868 MHz); can be modified.
  • radio.setOutputPower(22): Sets the transmit power to 22 dBm.
  • radio.transmitDirect(OUT_HZ): Enters continuous direct transmission mode, outputting a fixed‑frequency carrier.
  • loop(): No business logic; the carrier continues to transmit without program intervention.

Operation Result

  • After flashing, the module immediately outputs a fixed‑frequency carrier signal.

  • The serial port prints initialization and transmission start status; a spectrum analyzer or receiving module can detect the continuous RF signal, as shown below:

05_lr2021_LoRaWAN

Example Description

  • Based on the ESP32S3 + Core2021-XF module, implements LoRaWAN OTAA join + uplink/downlink communication.
  • Custom SPI pins to match the ESP32S3 hardware design.
  • Uses NVS flash to store session information, allowing fast reconnection after power‑off reboot without re‑joining.
  • Periodically uploads random data (default every 5 minutes) and automatically listens for server downlink messages.
  • Supports printing downlink data in HEX/ASCII formats for easy debugging and link verification.

Code Analysis

  • SPI.begin(...): Initializes ESP32S3 hardware SPI with custom CLK/MOSI/MISO pins.
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping; must be set before initialization.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure LoRaWAN frequency accuracy.
  • prefs.begin(...): Initializes the ESP32 NVS partition for storing LoRaWAN session information.
  • restoreLoRaWANState(): Restores session information from NVS for fast reconnection.
  • node.beginOTAA() / node.activateOTAA(): OTAA join functions.
  • saveLoRaWANState(): Saves session information to NVS after successful join.
  • node.sendReceive(): Sends uplink data and automatically listens for server downlink messages.
  • printHex / printAscii: Formats and prints received data.

Operation Result

  • After flashing, the module automatically completes OTAA join, periodically reports data, and listens for downlink messages.

  • The serial port prints join status, uplink/downlink messages, signal quality, etc., as shown below:

Run ESP-IDF Example

01_lr2021_tx

Example Description

  • Based on the native ESP‑IDF framework + ESP32S3 + Core2021-XF module, implements periodic LoRa packet transmission using interrupts.
  • Includes a dedicated hardware abstraction layer EspHal.h that perfectly adapts to the ESP‑IDF environment.
  • Custom SPI pin configuration supporting hardware SPI2 bus.
  • Uses interrupt‑driven non‑blocking transmission, automatically sending one packet with sequence number every second.
  • Log output uses the native ESP‑IDF ESP_LOG for stable and reliable operation.

Core Files

  • EspHal.h: ESP‑IDF hardware abstraction layer providing low‑level implementations for GPIO, SPI, delays, and interrupts (common to all examples).
  • main.cpp: LoRa transmit main program.

Code Analysis

  • EspHal* hal = new EspHal(...): Initializes the ESP‑IDF hardware abstraction layer.
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure frequency accuracy.
  • setFlag(void): Transmit‑complete interrupt callback function.
  • radio.setPacketSentAction(setFlag): Binds the transmit‑complete interrupt.
  • radio.startTransmit(...): Starts asynchronous LoRa transmission.
  • radio.finishTransmit(): Turns off the RF circuit after transmission to ensure low‑power stability.

Operation Result

  • After compiling and flashing, the serial port prints the transmission status and packet sequence number in real time.
  • Can be paired with 02_lr2021_rx to complete one‑way LoRa wireless communication in the ESP‑IDF environment.

02_lr2021_rx

Example Description

  • Based on the native ESP‑IDF framework + ESP32S3 + Core2021-XF module, implements wireless LoRa packet reception using interrupts.
  • Relies on the generic hardware abstraction layer EspHal.h for perfect adaptation to the ESP‑IDF environment.
  • Custom SPI pin configuration supporting hardware SPI2 bus.
  • Interrupt‑driven non‑blocking listening, receiving data in real time.
  • After reception, automatically prints: length, RSSI, SNR, HEX format, and string format.

Core Files

  • EspHal.h: Low‑level hardware abstraction (common to all examples).
  • main.cpp: LoRa receive main program.

Code Analysis

  • EspHal* hal: Initializes ESP‑IDF hardware abstraction (GPIO/SPI/interrupts).
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure receive frequency accuracy.
  • setFlag(void): Receive‑complete interrupt callback.
  • radio.setPacketReceivedAction(setFlag): Binds the receive‑complete interrupt.
  • radio.startReceive(): Starts continuous LoRa listening.
  • radio.readData(): Reads and parses the received packet.
  • Automatically restarts listening, enabling continuous reception.

Operation Result

  • After flashing, the module enters listening mode and prints data as soon as it is received.
  • Can be paired with 01_lr2021_tx to complete full wireless communication.

03_lr2021_pingpong

Example Description

  • Based on the native ESP‑IDF framework + ESP32S3 + Core2021-XF module, implements automatic LoRa ping‑pong bidirectional communication (question‑answer).
  • Relies on the generic hardware abstraction layer EspHal.h for perfect adaptation to the ESP‑IDF environment.
  • Custom SPI pin configuration supporting hardware SPI2 bus.
  • Uses interrupt‑driven non‑blocking mechanisms, automatically switching between transmit and receive states.
  • Supports distinguishing the initiating node from the listening node via a macro; upon power‑up they automatically send and receive to each other.
  • Upon receiving a packet, automatically prints the payload content, RSSI, and SNR for easy link debugging.

Core Files

  • EspHal.h: Low‑level hardware abstraction (common to all ESP‑IDF examples).
  • main.cpp: LoRa ping‑pong bidirectional communication application.

Code Analysis

  • EspHal* hal: Instantiates the ESP‑IDF hardware abstraction layer (SPI, GPIO, delays, interrupts).
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure LoRa frequency accuracy.
  • setFlag(void): Common interrupt callback for both transmit and receive events.
  • radio.setIrqAction(setFlag): Binds the module interrupt callback.
  • INITIATING_NODE: Macro switch that defines the device as the active packet‑sending node.
  • radio.startTransmit() / radio.startReceive(): The program automatically switches between transmit and listen modes.
  • radio.readData(): Parses received packets and prints text and signal parameters.
  • Closed‑loop logic: after sending, switch to receive; after receiving, delay and automatically reply, continuing the ping‑pong cycle.

Operation Result

  • After flashing both ESP32s, they automatically establish a bidirectional LoRa link and exchange data continuously.
  • The serial terminal prints initialization status, transmission/reception results, RSSI, and SNR in real time.

04_lr2021_tx_cw

Example Description

  • Based on the native ESP‑IDF framework + ESP32S3 + Core2021-XF module, implements fixed‑frequency continuous wave (CW) transmission.
  • Relies on the generic hardware abstraction layer EspHal.h for perfect adaptation to the ESP‑IDF environment.
  • Custom SPI pin configuration supporting hardware SPI2 bus.
  • Outputs a clean, packet‑free continuous RF signal, suitable for instrument calibration, band testing, and signal strength detection.
  • Transmission frequency: 868 MHz, transmit power: 22 dBm; continuously transmits after power‑up without interruption.

Core Files

  • EspHal.h: Low‑level hardware abstraction (common to all ESP‑IDF examples).
  • 04_lr2021_direct_transmit.c: LoRa carrier transmission main program.

Code Analysis

  • EspHal* hal: Initializes ESP‑IDF hardware abstraction (SPI, GPIO, delays, interrupts).
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure carrier frequency accuracy.
  • OUT_HZ 868000000UL: Defines the continuous transmit frequency (868 MHz).
  • radio.setOutputPower(22): Sets the transmit power to 22 dBm.
  • radio.transmitDirect(OUT_HZ): Enters direct carrier transmission mode, starting continuous transmission.

Operation Result

  • After flashing, the module immediately outputs a stable continuous RF signal.
  • A spectrum analyzer or receiving device can detect the stable carrier for band testing and calibration.

05_lr2021_LoRaWAN

Example Description

  • Based on the native ESP‑IDF framework + ESP32S3 + Core2021-XF module, implements LoRaWAN OTAA join + periodic uplink + downlink reception.
  • Relies on the generic hardware abstraction layer EspHal.h; runs independently in the pure ESP‑IDF environment.
  • Uses NVS flash to persistently store session information, allowing fast recovery after power‑off without re‑joining.
  • Automatically reports random test data, supports parsing and printing of server downlink data.
  • Full log output: join status, signal quality, uplink/downlink data, session save records.

Core Files

  • EspHal.h: Low‑level hardware abstraction (common to all ESP‑IDF examples).
  • 05_lr2021_lorawan_otaa.c: LoRaWAN OTAA communication main program.

Code Analysis

  • EspHal* hal: Initializes ESP‑IDF hardware abstraction (SPI, GPIO, delays, interrupts).
  • radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin.
  • radio.XTAL = true: Enables the external crystal oscillator to ensure LoRa frequency accuracy.
  • nvs_flash_init(): Enables NVS storage for saving LoRaWAN session information.
  • restoreLoRaWANState(): Recovers session from flash for fast reconnection.
  • node.beginOTAA() / node.activateOTAA(): OTAA join key functions.
  • node.sendReceive(): Sends uplink data and listens for server downlink messages.
  • printHex / printAscii: Formats and prints downlink data.

Operation Result

  • After the program runs, it automatically completes OTAA join, periodically reports data, and receives downlink messages from the server.
  • The serial terminal prints join status, upload records, signal quality, and downlink content in real time.