Hardware

ComponentDetails
MCUESP32 DOIT DevKitV1
RadioWaveshare Pico-LoRa-SX1262
ConnectionManual SPI wiring (HAT not used as intended)

Pin Mapping

SX1262 SignalESP32 GPIO
NSS (CS)GPIO 5
SCKGPIO 18
MISOGPIO 19
MOSIGPIO 23
BUSYGPIO 26
DIO1GPIO 35
RESETGPIO 14
3.3V3.3V
GNDGND

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 platformio

Clone Firmware

git clone https://github.com/meshtastic/firmware meshtastic_firmware
cd meshtastic_firmware
git submodule update --init --recursive

Creating 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_HW

Errors 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 HIGH

variants/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_sx1262

Do NOT add a [env:diy-sx1262] block to the root platformio.ini — this causes the RadioLibHal does not name a type error 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 pip

Fix:

python3 -m venv ~/.venv/pio
source ~/.venv/pio/bin/activate
pip install platformio

Attempt 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 scope

Fix: 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:

  1. Remove [env:diy-sx1262] from root platformio.ini
  2. Create variants/esp32/diy_sx1262/platformio.ini with the env block instead
  3. Add #define SX126X_DIO3_TCXO_VOLTAGE 1.8f to variant.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 SignalOld (VSPI)New (HSPI)
NSS (CS) GP3GPIO 5GPIO 15
SCKGPIO 18GPIO 14
MISOGPIO 19GPIO 12
MOSIGPIO 23GPIO 13
BUSYGPIO 26GPIO 26 (keep)
DIO1GPIO 35GPIO 35 (keep)
RESETGPIO 14GPIO 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!