Design a Custom Meshtastic LoRa Node PCB
Design and manufacture a custom PCB for a Meshtastic LoRa mesh networking node using an ESP32-S3 module and SX1262 LoRa transceiver. This advanced tutorial covers schematic design with RF-optimized SPI connections, PCB layout with proper ground plane management and antenna matching, 18650 battery power with USB-C charging, JLCPCB manufacturing, and flashing Meshtastic firmware on the finished board.
What You Need
Step-by-Step Instructions
-
Step 1 Choose the ESP32-S3 Module and SX1262 LoRa Transceiver
The ESP32-S3-WROOM-1 module is the standard choice for custom Meshtastic nodes. It provides dual-core Xtensa LX7 at 240MHz, 512KB SRAM, 8MB flash (N8 variant), WiFi 802.11b/g/n, and Bluetooth 5.0 LE — all pre-certified for FCC and CE. The module includes an on-board PCB antenna or u.FL connector (choose the U variant for an external antenna). For a Meshtastic node, the u.FL variant is preferred because you will use the module's WiFi/BLE for configuration while the LoRa radio uses a separate antenna.
For the LoRa transceiver, the Semtech SX1262 is the current standard. It supports LoRa modulation on 150MHz to 960MHz bands with up to +22dBm transmit power, -148dBm receive sensitivity at SF12/125kHz, and built-in PA (power amplifier) and LNA (low noise amplifier). The SX1262 communicates with the ESP32-S3 over SPI at up to 16MHz clock speed. It comes in a 4x4mm QFN-24 package — machine assembly is strongly recommended for this part.
Alternatively, use the Ebyte E22-900M30S module, which integrates the SX1262 with a 30dBm PA, LNA, antenna matching network, and RF switch in a castellated module. This costs more ($4-6 vs $2-3 for bare SX1262) but eliminates the need to design your own RF front-end — a significant simplification for your first custom LoRa board. The Heltec V3 uses a bare SX1262 with custom matching network; the LilyGO T-Beam Supreme uses an Ebyte module.
Select your frequency band based on your region: 915MHz for North America (FCC Part 15), 868MHz for Europe (ETSI EN 300 220), or 433MHz for Asia. Meshtastic firmware handles regional frequency selection automatically, but your hardware (antenna and matching network) must be designed for the correct band.
Tip: If this is your first custom RF design, use the Ebyte E22 module instead of a bare SX1262. The castellated module pads are easier to route and the integrated matching network eliminates the highest-risk part of the design. You can always move to a bare SX1262 in revision 2. -
Step 2 Design the Schematic: Module Pinout and SPI Connection
Create a new KiCad project and start with the ESP32-S3-WROOM-1 schematic symbol. Connect the standard power pins: 3V3 to your regulated supply, GND to ground, and EN (enable) to 3V3 through a 10K pull-up resistor with a 100nF decoupling cap to ground (this creates an RC delay for clean boot-up).
Route the SPI bus between the ESP32-S3 and SX1262. Meshtastic firmware expects specific GPIO assignments that vary by board definition, but a common mapping is: GPIO10 (SCK), GPIO11 (MOSI), GPIO12 (MISO), GPIO13 (NSS/chip select), GPIO14 (RESET), GPIO15 (BUSY), and GPIO16 (DIO1 — the interrupt line). The SX1262's DIO1 output fires on TX done, RX done, and timeout events — it must connect to a GPIO with interrupt capability, which is every GPIO on the ESP32-S3.
Add the SX1262's required passive components: a 32MHz TCXO crystal (the SX1262 can use either a TCXO or XTAL — TCXO gives better frequency stability for LoRa, costing $0.30-0.80), 15pF DC-blocking capacitor on the RF output, and the impedance matching network. For a 50-ohm antenna at 915MHz, the matching network is typically a pi-network with two capacitors (1.8pF and 3.3pF) and one inductor (3.9nH), though exact values depend on your PCB stackup and layout. The SX1262 datasheet (Semtech DS_SX1261-2_V2.1) provides reference designs for each frequency band.
Add a USB-C connector for programming and charging. Connect USB D+ and D- to the ESP32-S3's native USB pins (GPIO19 and GPIO20). Add 5.1K pull-down resistors on the CC1 and CC2 pins for USB-C compliance. The ESP32-S3's built-in USB-JTAG interface means you do not need a separate USB-UART bridge chip — this simplifies the design and saves $1-2 in BOM cost.
Tip: Download the Meshtastic firmware source and check the board definition file (variants/[board]/variant.h) for the exact GPIO mapping. If no existing board definition matches your pinout, you will need to create a custom variant — which is straightforward but requires compiling the firmware from source. -
Step 3 Design the Power System: 18650 Battery and USB-C Charging
A Meshtastic node needs to run for days on battery power. An 18650 lithium cell (3000-3500mAh) provides 12-72 hours of runtime depending on transmit power and duty cycle. At Meshtastic's default settings (long-fast mode, 915MHz, +22dBm TX power), expect roughly 24-36 hours from a single 3000mAh 18650.
Use the TP4056 (or its modern equivalent, the TP4054) for USB-C charging. This IC handles constant-current/constant-voltage charging of single-cell lithium batteries with programmable charge current set by a single resistor. A 2K resistor sets the charge current to 580mA; 1.2K sets it to 1000mA. The TP4056 costs $0.05-0.10 and comes in a tiny SOT-23-6 package. Connect the TP4056's input to VBUS (5V from USB-C) and its output to the battery terminals through a protection circuit.
Add a DW01A + FS8205A battery protection circuit (combined cost: $0.08). The DW01A monitors cell voltage and disconnects the load below 2.4V (over-discharge) and above 4.28V (over-charge). The FS8205A is a dual MOSFET that acts as the disconnect switch. Many 18650 holders include built-in protection circuits, but adding board-level protection is defense in depth.
Regulate the battery voltage (3.0-4.2V) down to 3.3V for the ESP32-S3 and SX1262 using a low-dropout (LDO) regulator. The ME6211C33 (or AP2112K-3.3) provides 500mA output current with only 100-200mV dropout, meaning it works down to 3.4V battery voltage. The ESP32-S3 draws 40-240mA depending on WiFi/BLE activity, and the SX1262 draws 120mA during TX at +22dBm. Total peak current is roughly 360mA — well within the ME6211's 500mA limit. Add 10uF input and output ceramic capacitors for stability.
Include a voltage divider (100K + 100K resistors) from the battery to an ESP32-S3 ADC pin for battery voltage monitoring. Meshtastic displays battery percentage in the app — it reads this ADC value. The 200K total resistance draws only 17uA from the battery, negligible compared to the radio's sleep current of 2.5uA.
Tip: Place a Schottky diode (SS14 or equivalent) between USB VBUS and the TP4056 input to prevent backfeeding power from the battery to USB when the charger is not connected. Without this diode, voltage from the battery can appear on the USB port's VBUS line. -
Step 4 PCB Layout: RF Considerations, Ground Plane, and Antenna Placement
Create a 2-layer PCB with a solid ground plane on the bottom layer. Route all signal traces on the top layer. The ground plane provides the RF return path for both the ESP32-S3's WiFi antenna and the SX1262's LoRa antenna — gaps in the ground plane under RF traces cause impedance mismatches and radiated emissions.
Place the SX1262 (or Ebyte module) as close to the board edge as possible, with the antenna connector or trace antenna at the very edge. The RF trace from the SX1262's RF output to the antenna connector must be a 50-ohm controlled impedance trace. On standard 1.6mm FR-4 with 1oz copper, a 50-ohm microstrip trace is approximately 2.8-3.0mm wide on the top layer over a continuous ground plane on the bottom layer. Keep this trace as short as possible — every millimeter adds insertion loss at 915MHz. Use no vias in the RF path.
The antenna matching network components must be placed directly adjacent to the SX1262's RF pin, before the 50-ohm trace to the antenna. Route the matching network with short, wide traces — these components handle the transition from the SX1262's output impedance to 50 ohms. Surround the RF section with ground vias spaced 1-2mm apart (lambda/20 at 915MHz is about 16mm, so 2mm spacing provides excellent shielding).
Separate the power section (TP4056, battery connector, LDO) from the RF section. Place power components on the opposite end of the board from the antenna. Route power traces on the top layer with 0.5mm or wider widths for current-carrying paths. The 18650 battery holder dominates the physical layout — it measures 77mm x 20mm, so plan your board dimensions around it. A practical board size is 85mm x 30mm, fitting the battery holder lengthwise with electronics on one end.
Add stitching vias around the board perimeter connecting top and bottom ground pours. Space them 3-5mm apart. This creates a Faraday cage effect that reduces edge radiation. Place at least 4-6 ground vias directly under the ESP32-S3-WROOM module's ground pad — the module's exposed pad is its primary thermal and electrical ground connection.
Tip: Run KiCad's impedance calculator (Calculators > Transmission Line) to verify your 50-ohm trace width for your exact PCB stackup. The 2.8-3.0mm estimate assumes 1.6mm FR-4 with Er=4.5 — your actual stackup from JLCPCB may differ slightly. A 10% impedance error at 915MHz is usually tolerable for short traces under 15mm. -
Step 5 Generate Manufacturing Files and Order from JLCPCB
Run DRC in KiCad and resolve all errors. Pay special attention to clearance violations near the RF matching network — the small component pads and short traces in this area often trigger spacing errors. JLCPCB's minimum clearance for 2-layer boards is 0.127mm (5 mil).
Generate Gerber files using the standard JLCPCB settings: Protel filename extensions, 4.6 coordinate format, millimeter units. Include layers F.Cu, B.Cu, F.Paste, B.Paste, F.SilkS, B.SilkS, F.Mask, B.Mask, and Edge.Cuts. Generate Excellon drill files in the same coordinate system.
Export the BOM in JLCPCB format with LCSC part numbers. Key components and approximate LCSC costs: ESP32-S3-WROOM-1-N8 ($2.80), SX1262 QFN-24 ($2.20) or Ebyte E22-900M30S ($5.50), TP4056 SOT-23-6 ($0.05), ME6211C33 SOT-23-5 ($0.08), 32MHz TCXO ($0.50), USB-C receptacle ($0.10), 18650 holder ($0.30). Total BOM cost for one unit is approximately $8-12 depending on module choice.
Generate the CPL file and verify component rotations, especially for the SX1262 QFN package — pin 1 orientation is the most common placement error for QFN parts. Upload all files to JLCPCB and select Economic PCBA for top-side assembly. The SX1262's QFN-24 package has a 0.5mm pad pitch — verify it is within Economic PCBA's capability (minimum 0.5mm pitch QFN is supported).
For 5 assembled boards (excluding the 18650 holder and any through-hole parts), expect approximately $45-65 total: $4-5 PCB fabrication, $8 assembly setup, $15-25 component costs, $9-12 extended part surcharges, and $7-12 shipping. The 18650 holder is a through-hole part — hand-solder it after the boards arrive.
Tip: Order a stencil with your PCB if you plan to assemble any boards yourself for debugging. Having a spare unassembled board with a stencil lets you rework or modify the design quickly without waiting for a new JLCPCB order. -
Step 6 Assemble the Board and Flash Meshtastic Firmware
When the boards arrive from JLCPCB, the SMD components will be pre-assembled. Hand-solder the through-hole components: 18650 battery holder, SMA antenna connector (if using an external antenna), and any pin headers for programming or debugging.
Before inserting a battery, verify power supply voltages with a multimeter. Connect USB-C power and measure 3.3V at the LDO output. Check that the TP4056 charge indicator LED behaves correctly — it should illuminate when USB power is connected without a battery, indicating the charger is active. Insert an 18650 cell and verify the battery voltage appears on the ADC pin through the voltage divider (should read approximately half the battery voltage due to the 100K/100K divider).
Flash Meshtastic firmware using the ESP32-S3's native USB interface. Connect USB-C to your computer, hold the BOOT button (GPIO0 to ground), press RESET, then release BOOT. The ESP32-S3 enters download mode and appears as a USB serial device. If your design matches an existing Meshtastic board definition (like the Heltec V3 or T-Beam Supreme pinout), use the Meshtastic web flasher at flasher.meshtastic.org and select the corresponding board. If your GPIO mapping is custom, you will need to compile Meshtastic from source with a custom variant.h file that defines your pin assignments for LORA_SCK, LORA_MOSI, LORA_MISO, LORA_CS, LORA_RESET, LORA_DIO1, and LORA_BUSY.
After flashing, the node should boot and begin transmitting LoRa beacon packets. Connect to it via the Meshtastic app (iOS or Android) over Bluetooth LE to configure the region (US, EU, etc.), channel, and node name. Use another Meshtastic node (a Heltec V3 or T-Beam works well) to verify two-way mesh communication. At +22dBm TX power with a quarter-wave whip antenna, expect 1-5km range in urban environments and 10-30km with line of sight.
If the LoRa radio does not initialize, check the SPI connections with an oscilloscope or logic analyzer. The most common issues are: SCK and MOSI swapped, incorrect chip select GPIO, or a cold solder joint on the SX1262's QFN ground pad. If using the Ebyte module, verify the TXEN and RXEN control pins are connected correctly — some Ebyte modules require explicit TX/RX switching that bare SX1262 designs do not.
Tip: Flash a simple LoRa ping-pong test sketch before Meshtastic firmware to verify the radio hardware works independently. The RadioLib library has an SX1262 example that transmits a packet and waits for a response — this isolates radio hardware issues from Meshtastic firmware configuration problems.
Frequently Asked Questions
Why use an ESP32-S3 instead of an ESP32-C3 for a Meshtastic node?
Meshtastic benefits from the ESP32-S3's Bluetooth 5.0 LE for phone connectivity and its larger 512KB SRAM for handling mesh routing tables. The ESP32-S3's dual-core 240MHz processor also handles simultaneous WiFi configuration and LoRa packet processing without timing conflicts. The ESP32-C3 works but has limited RAM (400KB) that constrains mesh network size to roughly 50 nodes.
Can I use a bare SX1262 chip instead of the Ebyte module?
Yes, but it adds significant design complexity. A bare SX1262 requires a custom impedance matching network (3-4 passive components tuned for your frequency band), a 32MHz TCXO, and careful PCB layout with 50-ohm controlled impedance traces. The Ebyte E22 module integrates all of this in a pre-certified, castellated package. Use bare SX1262 only if you need the smallest possible form factor or are producing 100+ units where the $3 per-unit cost savings justifies the engineering effort.
What range can I expect from a custom Meshtastic node?
At +22dBm TX power with a quarter-wave whip antenna on 915MHz: 1-5km in dense urban areas, 5-15km in suburban/rural areas, and 10-30km+ with line of sight (hilltop to hilltop). Range depends heavily on antenna quality, height above ground, and terrain. A custom PCB with a properly matched antenna performs identically to commercial nodes like the Heltec V3 or T-Beam Supreme — the radio physics are the same.
Do I need FCC certification for a custom Meshtastic PCB?
If you use a pre-certified RF module (ESP32-S3-WROOM for WiFi/BLE and Ebyte E22 for LoRa), your board inherits their certifications under FCC Part 15 modular approval — no additional certification needed for personal use or small-scale sales. Using a bare SX1262 with a custom antenna requires intentional radiator testing ($5,000-15,000) for commercial sale. Personal and experimental use is exempt under Part 15.1(b).
How long will an 18650 battery last in a Meshtastic node?
A 3000mAh 18650 cell lasts 24-72 hours depending on configuration. In long-fast mode with +22dBm TX power and Bluetooth active, expect 24-36 hours. Switching to long-slow mode, reducing TX power to +14dBm, and disabling Bluetooth when not configuring extends runtime to 48-72 hours. The ESP32-S3's deep sleep current is 7uA and the SX1262's sleep current is 0.16uA — standby power is negligible compared to TX energy.
What is the total cost to build 5 custom Meshtastic node PCBs?
Using JLCPCB Economic PCBA with an Ebyte E22-900M30S module: approximately $65-85 for 5 assembled boards (excluding 18650 cells and antennas). Add $15-25 for 5 quality 18650 cells and $10-15 for 5 SMA whip antennas. Total all-in cost: approximately $90-125 for 5 complete nodes, or $18-25 per node. A comparable commercial Heltec V3 costs $18-22 per unit but lacks a battery holder and GPS.
Can I add a GPS module to this design?
Yes. Add a u-blox NEO-6M or NEO-M8N GPS module connected to the ESP32-S3 via UART (TX/RX on any available GPIOs). The module needs its own 3.3V supply (10-25mA continuous) and a ceramic patch antenna or u.FL connector for an external antenna. GPS adds approximately $3-5 to the BOM and increases battery drain by 20-30%. Meshtastic uses GPS for position reporting and range estimation between nodes.