Working with Arduino
This chapter contains the following sections. Please read as needed:
Setting Up Development Environment
1. Installation and Configuration
- For setting up the Arduino environment and basic usage, please refer to this R4 link; R3 comes pre-installed by default.
- After setting up the environment, connect the sensor and download the example package.
2. Hardware Configuration
- The IO level of the Arduino development board must be 3.3V. If using 5V IO levels, a level shifter is required; otherwise the sensor may be damaged.
- When using Waveshare R3/R4, the following jumper caps must be set to 3.3V before use.
| Image | Description |
|---|---|
| Arduino UNO R3 | |
| Arduino UNO R4 | |
| Arduino UNO R4 WIFI |
Hardware Connection
Connect according to the table below.
| Core2021-XF | Arduino UNO |
|---|---|
| CLK | 13 |
| MISO | 12 |
| MOSI | 11 |
| CS | 10 |
| DIO11 | 2 |
| RESET | 3 |
| BUSY | 9 |
Example
- Arduino example programs are located in the
core2021-xf\examples\arduinodirectory of the example package. - Examples 01, 02, and 03 require two Core2021-XF modules: one for transmission and one for reception.
| Example | Basic Description | Dependency Library |
|---|---|---|
| 01_lr2021_tx | LR2021 Transmit | RadioLib |
| 02_lr2021_rx | LR2021 Receive | RadioLib |
| 03_lr2021_pingpong | LR2021 Ping‑Pong | RadioLib |
| 04_lr2021_tx_cw | LR2021 CW Mode Transmit | RadioLib |
| 05_lr2021_LoRaWAN | LoRaWAN (not available on Arduino R3) | RadioLib |
-
Select the development board:
Image Description 
Arduino UNO R3 
Arduino UNO R4 -
Select the port for the development board, 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 Core2021-XF module, implements periodic LoRa packet transmission using interrupts.
- 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
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 Core2021-XF module, implements wireless LoRa packet reception using interrupts.
- 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
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, sets a reception‑complete flag.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 Core2021-XF module, implements LoRa automatic ping‑pong (question‑answer) two‑way communication.
- Two modules can send and receive to each other without manual control.
- Enabling
INITIATING_NODEsets 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
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_NODEmacro: 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_NODEmacro 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 Core2021-XF module, implements LoRa continuous wave (CW) / direct transmit.
- 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
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 Core2021-XF module + Arduino UNO R4 platform, implements LoRaWAN OTAA join and uplink/downlink communication.
- Supports OTAA dynamic join, and EEPROM‑based session storage to quickly restore connection after power‑off reboot.
- Periodically sends uplink data (default every 5 minutes) and listens for server downlink messages.
- Automatically prints the received data in both HEX and ASCII formats, and supports signal quality monitoring.
Code Analysis
radio.irqDioNum = 11: Configures the LR2021 interrupt mapping pin; must be set before initialization.radio.XTAL = true: Enables the external crystal oscillator to ensure LoRaWAN frequency accuracy.EEPROM.begin(): Initializes the on‑chip EEPROM for storing LoRaWAN session information.restoreLoRaWANState(): Restores join session and random values from EEPROM to achieve fast reconnection.node.beginOTAA(): Initializes OTAA join parameters (JoinEUI, DevEUI, AppKey, NwkKey).node.activateOTAA(): Initiates an OTAA join request to the server.saveLoRaWANState(): Saves session information to EEPROM after successful join.node.sendReceive(): Sends uplink data and automatically opens receive windows to listen for downlink messages.printHex / printAscii: Prints the downlink data in hexadecimal and ASCII formats.
Operation Result
-
Refer to the LoRaWAN environment setup document for environment configuration.
-
After flashing, the module automatically performs OTAA join; once joined successfully, it periodically uploads data.
-
The serial port prints join status, uplink/downlink messages, RSSI, SNR, etc., as shown below:
