Hardware
| Component | Details |
|---|---|
| MCU | ESP32 DOIT DevKitV1 |
| Radio | Waveshare Pico-LoRa-SX1262 |
| Connection | Manual SPI wiring (HAT not used as intended) |
Pin Mapping
| SX1262 Signal | ESP32 GPIO |
|---|---|
| NSS (CS) | GPIO 5 |
| SCK | GPIO 18 |
| MISO | GPIO 19 |
| MOSI | GPIO 23 |
| BUSY | GPIO 26 |
| DIO1 | GPIO 35 |
| RESET | GPIO 14 |
| 3.3V | 3.3V |
| GND | GND |
GPIOs 18/19/23/5 are the ESP32 VSPI bus — the best choice for SPI. GPIO 35 is input-only, which is ideal for DIO1 (interrupt line).
ESP32 Pinout Reference Pico-LoRa-SX1262 - Waveshare Wiki
Environment Setup
OS: ArchLinux
Arch blocks system-wide pip by default (PEP 668), so a virtual environment is required.
python3 -m venv ~/.venv/pio
source ~/.venv/pio/bin/activate
pip install platformioClone Firmware
git clone https://github.com/meshtastic/firmware meshtastic_firmware
cd meshtastic_firmware
git submodule update --init --recursiveCreating the Custom Variant
Directory Structure
variants/esp32/diy_sx1262/
├── variant.h
├── pins_arduino.h
└── platformio.ini
variants/esp32/diy_sx1262/variant.h
First attempt (wrong macro names) — FAILED:
// ❌ Wrong — firmware expects SX126X_* prefix, not LORA_*
#define LORA_CS 5
#define LORA_SCK 18
#define LORA_MISO 19
#define LORA_MOSI 23
#define LORA_RESET 14
#define LORA_DIO1 35
#define LORA_BUSY 26
// ❌ Wrong — HW_VENDOR needs the meshtastic_ prefix
#define HW_VENDOR HardwareModel_PRIVATE_HWErrors produced:
src/mesh/RadioInterface.cpp:336: error: 'SX126X_CS' was not declared in this scope
src/mesh/RadioInterface.cpp:336: error: 'SX126X_DIO1' was not declared in this scope
src/mesh/RadioInterface.cpp:336: error: 'SX126X_RESET' was not declared in this scope
src/mesh/RadioInterface.cpp:336: error: 'SX126X_BUSY' was not declared in this scope
// Also: "HW_VENDOR" redefined warning on every file
Final working variant.h:
#pragma once
#define PRIVATE_HW
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#define USE_SX1262
// Correct macro names expected by the firmware
#define SX126X_CS 5
#define SX126X_SCK 18
#define SX126X_MISO 19
#define SX126X_MOSI 23
#define SX126X_RESET 14
#define SX126X_DIO1 35
#define SX126X_BUSY 26
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8f
#define SERIAL0_RX_GPIO 3
#define SERIAL0_TX_GPIO 1
#define LED_PIN 2
#define LED_STATE_ON HIGHvariants/esp32/diy_sx1262/pins_arduino.h
#pragma once
#include "../esp32/pins_arduino.h"variants/esp32/diy_sx1262/platformio.ini
The correct pattern is to put a platformio.ini inside the variant folder — the root platformio.ini already has extra_configs that auto-discovers these files.
[env:diy-sx1262]
extends = esp32_base
board = esp32dev
build_flags =
${esp32_base.build_flags}
-D PRIVATE_HW
-I variants/esp32/diy_sx1262Do NOT add a
[env:diy-sx1262]block to the rootplatformio.ini— this causes theRadioLibHal does not name a typeerror due to incorrect build flag inheritance.
Build Attempts
Attempt 1 — pip missing on Arch
pio run -e diy-sx1262
# Error: /usr/bin/python: No module named pipFix:
python3 -m venv ~/.venv/pio
source ~/.venv/pio/bin/activate
pip install platformioAttempt 2 — Wrong macro names in variant.h
pio run -e diy-sx1262
# Error: 'SX126X_CS' was not declared in this scope
# Error: 'SX126X_DIO1' was not declared in this scopeFix: Rename all LORA_* defines to SX126X_* in variant.h.
Attempt 3 — RadioLibHal error
pio run -e diy-sx1262
# Error: 'RadioLibHal' does not name a type
# RadioLibHal *RadioLibHAL = NULL;Cause: The [env:diy-sx1262] block was in the root platformio.ini instead of inside the variant folder. Build flags were not being inherited correctly, so RadioLib headers weren’t included in the right order.
Fix:
- Remove
[env:diy-sx1262]from rootplatformio.ini - Create
variants/esp32/diy_sx1262/platformio.iniwith the env block instead - Add
#define SX126X_DIO3_TCXO_VOLTAGE 1.8ftovariant.h
Attempt 4 — SUCCESS ✅
pio run -e diy-sx1262 -t clean
pio run -e diy-sx1262
# RAM: [==== ] 37.9% (used 124172 bytes from 327680 bytes)
# Flash: [========= ] 91.5% (used 2219049 bytes from 2424832 bytes)
# [SUCCESS]Flashing
Attempt 1 wrong cable
initially i grabbed any micro-usb cable and tried to flash it, but my laptop didn’t detect the /dev/USBTTY0.
Attempt 2 flashing without correct boot sequence
I didn’t do the correct boot sequence you need to do:
- hold boot
- press and release ed
- release boot
then you can flash it
Hard resetting via RTS pin...
========================================================= [SUCCESS] Took 57.58 seconds =========================================================
Environment Status Duration
------------- -------- ------------
diy-sx1262 SUCCESS 00:00:57.578
========================================================== 1 succeeded in 00:00:57.578 =========Now i’m able to connect to it with bluetooth on my phone!
Rewiring
You thought this log was over, but you’re wrong it was I DIO…
nope I just need to rewire the pins from the gpio of the esp32 to sx1262 to use HSPI on the esp32 instead of VSPI.
New pinout
| SX1262 Signal | Old (VSPI) | New (HSPI) |
|---|---|---|
| NSS (CS) GP3 | GPIO 5 | GPIO 15 |
| SCK | GPIO 18 | GPIO 14 |
| MISO | GPIO 19 | GPIO 12 |
| MOSI | GPIO 23 | GPIO 13 |
| BUSY | GPIO 26 | GPIO 26 (keep) |
| DIO1 | GPIO 35 | GPIO 35 (keep) |
| RESET | GPIO 14 | GPIO 32 |
![]() | ||
![]() |
- 3v and ground are the same
updating varients.h
#define SX126X_CS 15
#define SX126X_SCK 14
#define SX126X_MISO 12
#define SX126X_MOSI 13
#define SX126X_RESET 32
#define SX126X_DIO1 35
#define SX126X_BUSY 26
now it works!

