Skip to main content

Working with Arduino

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

Arduino Getting Started​

New to Arduino ESP32 development and looking for a quick start? We have prepared a comprehensive Getting Started Tutorial for you.

Note: This tutorial uses the ESP32-S3-Zero as a reference example, and all hardware code is based on its pinout. Before you start, we recommend checking the pinout of your development board to ensure the pin configuration is correct.

Set Up the Development Environment​

Install and Configure the Arduino IDE​

Use Arduino IDE 2.x and install esp32 by Espressif Systems 3.3.11. For the installation process, see the Arduino IDE Installation and Configuration Tutorial.

Add the Espressif official index to the Additional Boards Manager URLs under "File" > "Preferences", then select the above version in the Boards Manager:

https://espressif.github.io/arduino-esp32/package_esp32_index.json

Install Libraries and Select the Screen​

Obtain the complete project from ESP32-S3-LR1121-ePaper-2.9 example package.

LibraryVersionInstallation Method
RadioLib7.7.1Install via the Arduino Library Manager; the repository also includes the corresponding library
Waveshare LR1121 E-Paper0.1.0, use the copy included with the current projectCopy examples/arduino/libraries/Waveshare_LR1121_EPaper to the libraries directory of the Sketchbook
SPI, Wire, WiFi, Preferences, SD_MMCProvided with Arduino-ESP32 3.3.11Do not install separately

Restart the Arduino IDE after copying is complete. If libraries with the same name already exist, back them up and remove the old copies first, and confirm that the compilation log uses the current library path. This set of Arduino examples uses the native display driver and does not depend on GxEPD2, Adafruit_GFX, LVGL, or the ESP Board Manager.

Edit src/WaveshareConfig.h in the library and enable only the 2.9-inch configuration:

//#define WAVESHARE_EPAPER_213
#define WAVESHARE_EPAPER_290

Project Parameter Settings​

Set the following in the "Tools" menu:

OptionSetting
BoardESP32S3 Dev Module
USB CDC On BootEnabled
USB ModeHardware CDC and JTAG
Flash Size16MB (128Mb)
PSRAMOPI PSRAM
Partition SchemeDefault scheme; after adding features in example 09, the application space needs to be rechecked
PortThe actual port of the development board

Build and Upload​

  1. Connect the development board with a Type-C cable that supports data transfer.
  2. Open the .ino file with the same name as the directory, for example examples/arduino/03_epaper/03_epaper.ino.
  3. Confirm the board parameters and port, and click "Verify" to compile.
  4. After compilation succeeds, click "Upload". If connection fails, follow the Download Mode Instructions.
  5. Open the serial monitor, select the 115200 baud rate, and check the log and behavior of the corresponding example.

The following describes the operation steps and expected source code behavior for each example. The actual running results need to be verified against the corresponding logs and hardware behavior.

Example​

Each directory is an independent program. After switching examples, recompile and upload; before transmitting with the wireless examples, complete the Antenna and Wireless Parameter Check.

DirectoryFunctionAdditional Conditions
01_ws2812_ledRGB LED color changesNone
02_i2c_scanScan onboard I2C devicesNone
03_epaperBlack-and-white display and refresh count2.9-inch configuration
04_bat_axp2602Battery information readingMatching battery and correct sampling configuration
05_rtc_pcf85063Time readingSet a valid time as needed
06_lr1121_pingpongLoRa point-to-point transmit/receiveAntenna, peer with the same parameters
07_sd_cardStorage card read/write verification and e-paper status displayFAT32 card
08_deep_sleepTimed and button wake-upObserve the wake-up log
09_comprehensive_demoSelf-test, continuous load, and sleepAntenna; TF card, STA, and LoRa peer prepared as needed
10_lr1121_lorawanLoRaWAN Class A OTAAGateway, server, and OTAA credentials
11_LoRaWAN_ABPLoRaWAN Class A ABPSession parameters and counters matching
12_LoRaWAN_Class_CClass C asynchronous downlinkServer Class C configuration
13_LoRaWAN_MulticastClass C static multicast receptionMulticast configuration; multiple boards can check the one-to-many effect

01_ws2812_led: RGB LED​

Example Description

Uses GPIO21 to control 1 WS2812 in GRB format, with the color continuously changing between red, green, and blue, and the channel value limited to 48/255.

Operation Steps and Running Effect

Upload the example. The serial port should output WS2812: GPIO21, one GRB LED. Observe the color changes of the onboard LED. This example does not refresh the e-paper; the LED power is also controlled by the shared power supply of GPIO38.

02_i2c_scan: I2C Scan​

Example Description

Scans I2C devices via GPIO13/SDA and GPIO14/SCL, outputting only serial logs.

Operation Steps and Running Effect

After uploading, check the addresses and device names in the serial port. The onboard RTC address is 0x51, and the AXP2602 address is 0x62. If scanning fails, check the power supply, bus levels, and pull-ups; an address response does not mean that all functions of the device have been verified.

03_epaper: E-Paper Display​

Example Description

Displays landscape text and a refresh count. The first frame is a full refresh, after which the driver manages full-screen fast refreshes, inserting a full refresh after the limit is reached.

Operation Steps and Running Effect

Confirm that only WAVESHARE_EPAPER_290 is enabled, then upload. The serial port outputs the selected panel and visible dimensions, RAM dimensions, and BUSY=HIGH, and the screen displays EPAPER and an incrementing REFRESH count.

Chinese and other non-ASCII characters require separate font library adaptation.

04_bat_axp2602: Fuel Gauge​

Example Description

Reads the battery voltage, signed current, SOC, chip temperature, and remaining time estimate through the AXP2602 driver in the repository library, and outputs them to the serial port and e-paper.

Operation Steps and Running Effect

Check the battery and sampling circuit according to the Battery Connection Instructions, then upload the example. Check whether consecutive samples change reasonably with the actual power supply state; do not treat an uncalibrated SOC or time estimate as a measured battery capacity value.

05_rtc_pcf85063: RTC Time​

Example Description

Reads the PCF85063A time and the low-voltage flag. When the time is invalid, writes the example default time 2026-01-01 12:00:00; it does not automatically obtain the current time.

Operation Steps and Running Effect

If you need an actual date, first modify the initial time in the .ino and then upload. Check the date, time, and voltage_low on the serial port, and observe the time changes on the screen. An existing valid time will not be overwritten by the default value; if you need to set the time again, you should explicitly call rtc.set().

06_lr1121_pingpong: LoRa Point-to-Point​

Example Description

The program periodically sends PING, replies with PONG after receiving a peer's PING, and outputs RSSI, SNR, and status codes.

Notes

The default parameters are provided by LR1121BoardRadio::begin() in WaveshareRadio.h: 868 MHz, 125 kHz, SF7, coding rate 4/5, 22 dBm. Adjust them first according to regional, hardware, and antenna limits; the default power cannot be directly used as the basis for permitted transmission.

Operation Steps and Running Effect

  1. Prepare two development boards and matching antennas, and confirm that the parameters on both sides are consistent.
  2. If you need to modify the parameters, explicitly pass them to boardRadio.begin() in the .ino, keeping both ends consistent.
  3. Upload them separately and open the serial ports, checking LR1121 init: 0, PING/PONG, and the received RSSI and SNR.

An initialization return of 0 indicates that this RadioLib initialization succeeded; it does not replace the two-board transmit/receive test.

07_sd_card: Storage Card Read/Write​

Example Description

Uses the SD_MMC built into Arduino-ESP32 to access the card in 1-bit mode via GPIO10/CMD, GPIO11/D0, and GPIO12/CLK.

The e-paper displays the card capacity, mount, read/write, and unmount status, and the title is updated from SD TEST to SD PASS or SD FAIL. After unmounting, refresh the final result, then let the screen sleep, stop SPI, and turn off the shared power supply; the result screen is still retained.

Operation Steps and Running Effect

  1. Power off, insert a FAT32 card, and confirm the Test File Impact.
  2. Upload the example, and check the card information, root directory listing, write and byte-by-byte read-back results in the serial port, as well as the various statuses on the screen.
  3. Check the final SD PASS / SD FAIL screen and the serial port FINAL result.

The program does not format or overwrite existing test files. PASS means this process completed; it does not mean all cards are compatible.

Arduino's SD_MMC.end() does not return an unmount result, so the screen displays Unmount: done, which does not mean unmounting has been verified as successful. A display failure does not interrupt the TF test; the serial port DISPLAY separately reports the display result, and FINAL indicates the TF test result.

08_deep_sleep: Deep Sleep​

Example Description

Displays a sleep prompt, puts the LR1121, e-paper, and detected AXP2602 into sleep, stops bus access, isolates the wireless pins, and then turns off and holds off the GPIO38 shared power supply. The default configuration is a 600-second (10-minute) timer and BOOT/GPIO0 low-level wake-up.

Operation Steps and Running Effect

After uploading, confirm the wake cause, radio pins isolated; shared power held off, and start deep sleep logs, release BOOT, and wait for the timed wake-up, or briefly press BOOT to wake up early. The USB port may disconnect during deep sleep; reconnect the serial monitor after waking up. To modify the timer period, adjust kWakeupSeconds in 08_deep_sleep.ino.

If SLEEP aborted appears, the program remains awake; troubleshoot the error and press RESET to retry. If the AXP2602 is not detected, it will prompt and continue running; this cannot be taken to mean that the fuel gauge has entered sleep. The basic shutdown process has been aligned with ESP-IDF example 08, and the actual current needs to be measured separately; for the process that includes shutting down Wi-Fi, BLE, MicroSD, and running tasks, see example 09.

09_comprehensive_demo: Comprehensive Example​

Example Description

After power-on or wake-up, it runs a self-test, displays the BOARD TEST result page, and then enters RUNTIME. Runtime includes dual-core computation, memory stress, Wi-Fi APSTA, BLE passive scanning, and LoRa reception; the TF is read-only and no files are written.

Operation Steps

  1. Modify app_config.h in the example directory to set the STA, SoftAP, and LoRa parameters. If STA is not configured, it does not affect SoftAP startup.
  2. After checking the antenna and wireless parameters, upload and observe the self-test and runtime pages.
  3. Press KEY/GPIO1 to send one frame of LoRa for each stable press.
  4. Double-press BOOT/GPIO0 to enter sleep; during deep sleep, single-press BOOT to wake up, and check whether the self-test and runtime services are rebuilt.

Result Judgment

The serial port reports status every 30 seconds by default, and the screen refreshes every 5 minutes by default; transmit/receive events can trigger an earlier refresh. When a card, STA credentials, or LoRa peer is missing, judge based on the corresponding untested status; success in other items cannot be substituted for it. The BLE count includes duplicate advertisements and is not the number of unique devices.

This example does not enable timed wake-up. Arduino uses the native display and core libraries and does not use the ESP-IDF Board Manager/LVGL; the two cannot share build steps.

10_lr1121_lorawan: Class A OTAA​

Example Description

Uses LoRaWAN 1.1 OTAA to activate or restore a session, periodically sends uplinks, and handles the Class A receive windows, saving the nonce and session state.

Operation Steps and Running Effect

Fill in the JoinEUI, DevEUI, NwkKey, and AppKey in lorawan_credentials.h in the example directory, verify the region object and server configuration in the .ino, and then upload. Observe the activation status and the incrementing FCntUp; the current application transmission period is 60 seconds, and it is also subject to protocol scheduling.

If the placeholder values are not replaced, the program displays CONFIG ERROR and stops wireless operations. For configuration and session saving instructions, see LoRaWAN Usage Instructions.

11_LoRaWAN_ABP: Class A ABP​

Example Description

Directly configures or restores an ABP session without sending an OTAA Join Request. The current Arduino implementation uses the four independent session keys of LoRaWAN 1.1.

Operation Steps and Running Effect

Fill in the DevAddr, AppSKey, FNwkSIntKey, SNwkSIntKey, and NwkSEncKey in abp_credentials.h, and use the same MAC version and keys on the server. After uploading, check the session status and uplink counter; in addition to periodic transmission, you can also request transmission by pressing GPIO1.

Do not copy the same 1.0.x NwkSKey into the three 1.1 network key positions. Keep the local session consistent with the server frame counters.

12_LoRaWAN_Class_C: Continuous Reception​

Example Description

Switches to Class C after completing OTAA, handles asynchronous downlinks, and periodically sends uplinks.

Operation Steps and Running Effect

Configure the device credentials in lorawan_credentials.h, enable Class C on the server, and verify RX2/RXC. After uploading, check Class C ready, then send downlinks from the server, and check the port, downlink count, and length.

Do not add deep sleep that stops reception during operation. The screen showing ready does not mean the server downlink has been received; you need to actually send a downlink and check the reception record.

13_LoRaWAN_Multicast: Static Multicast​

Example Description

First establishes the device's own OTAA session, then enables static Class C multicast. The multicast counter is written to Preferences, and duplicate or rollback counts are rejected.

Operation Steps and Running Effect

In multicast_credentials.h, configure the independent OTAA credentials for each device and the shared multicast address, AppSKey, and NwkSKey for the same group. Configure the same multicast parameters on the server, wait for multicast ready, then send multicast downlinks, and check the multicast accepted and incrementing counters on each board.

This example does not include remote group creation, Class B, or full FUOTA. If the multicast state write fails, wireless operations will be disabled; the storage problem should be resolved first.