☀️ Solar for IoT

Solar for IoT: Worked Designs

September 2026

What this is

This is a design guide by example. It starts with five rules that size and protect the power system of any small solar-powered outdoor device, then applies them end to end to two real designs:

  1. A MeshCore LoRa repeater — a low-power Xiao nRF52840 board with a Wio-SX1262 LoRa radio, sitting on a hilltop or rooftop forwarding mesh packets around the clock. Draws about 10 mA on average. The simple case: one small panel, one charger module, a couple of protected cells.
  2. A drone-detector node — a Xiao ESP32-C5 runs WiFi and BLE in monitor mode to catch FAA Remote ID beacons from nearby drones, and a second Xiao nRF52840 + Wio-SX1262 relays detections over MeshCore to a home base station. Draws roughly 70 mA on average. The harder case: seven times the load, a partly shaded site, two panels, and a firmware-managed battery.

Both designs are real — real parts, 2026 prices, wiring, and the reasoning behind every choice — but they’re here to show the method, not as kits to copy. Your device’s load, your site, and your climate will be different, and the goal is for you to be able to redo each decision for your own hardware. Design 2 in particular depends on firmware and a carrier board from an unreleased fork of the drone-mesh-mapper project, so it can’t be reproduced as-is; read it as a study of what changes when the load and the site get harder.

Both designs live outdoors year-round, charge from a solar panel during the day, and ride out cloudy stretches on lithium cells — the standard cylindrical 18650 cell (18 mm × 65 mm) in Design 1, the slightly larger 21700 (21 mm × 70 mm) in Design 2. Neither talks to the grid and neither needs a big charge controller: each fits in a small junction box with a panel, a few cells, and a postage-stamp charger chip.

Who this is for

You’re comfortable with Arduino-level electronics and have built something with a battery before. You haven’t designed a power supply, and you don’t want to become an expert — you want to power your own outdoor device from the sun, and to see the method applied on real hardware with enough context that you can make each choice differently when your situation differs. Links like Solar for IoT — “Sizing from a power budget” point to the physics-first companion reference for anyone who wants the why.

How to use this guide

  1. Read the five rules below. They’re the whole method on a couple of pages.
  2. Read both designs, watching where each rule gets applied and where a design deliberately goes past it. Each design ends with Adapting this design: which numbers to swap for your own device.
  3. Use Designing your own device as your checklist. The sections after it — enclosures, buying cells and protection boards, pitfalls, troubleshooting — apply to whatever you build.

If this is your first solar build, Design 1 is the pattern to start from: one panel, one off-the-shelf charger module, and a dozen or so solder joints. Design 2 shows what changes as the load, the site, and the part count grow — up to a custom carrier PCB ordered from a fab.

What building your own will take

Whatever you end up designing, a build along these lines needs nothing exotic:

The five rules

Five rules do most of the work. Each one is a line of math or a single choice, with a one-sentence reason. The reference has the full derivations.

Rule 1: size the panel from the worst month

\[\text{Panel watts at STC} = \frac{\text{average load (W)} \times 24 \text{ h}}{\text{peak sun hours} \times 0.40}\]

STC (Standard Test Conditions) is the lab benchmark every solar panel is rated against — 1000 W/m² of sunlight, 25 °C (77 °F) cell temperature, and a specific reference spectrum. Real outdoor light and temperatures are almost never that. Peak sun hours is the number of hours per day equivalent to full noon sun under those lab conditions. At mid-latitudes (~35° N), December’s number is about 2.5 — plug that in, because if the panel keeps up in December it keeps up all year. The 0.40 is the “all-losses” derate (heat, dust, angle, aging, chip efficiency) that turns the lab-condition nameplate rating into what you’ll actually harvest.

Get the average load by measuring average current where it leaves the battery and multiplying by the battery’s nominal voltage — 3.7 V for Li-ion, not the board’s 3.3 V rail. The small linear regulator on most boards passes the same current through, so the battery really is supplying current × 3.7 V.

See Solar for IoT — “Sizing from a power budget” for the full derivation and the list of derating factors.

Rule 2: size the battery for the worst dark stretch

\[\text{Battery Wh (nameplate)} = \frac{\text{daily energy} \times N_{\text{dark days}} \times 1.3}{\text{usable fraction}}\]

\(N_{\text{dark days}}\) is how many days of near-zero harvest you need to survive on battery alone; 3 for a forgiving climate, 5–7 for a gloomy one. The 1.3 is a safety margin (cold weather, end-of-life capacity, partial recharge after each bad day). The usable fraction depends on where your low-voltage cutoff (Rule 3) sits: about 0.8 if the cell may run down to about 3.3 V, about 0.7 if the effective floor at the cell is about 3.5 V. Lithium cells deliver most of their energy above 3.5 V, so a conservative cutoff costs less capacity than you’d guess.

See Solar for IoT — “Sizing from a power budget” (Step 5) for the formula worked through on an example.

Rule 3: protect the cell with a cutoff and a higher reconnect

A Li-ion cell drained below about 3.0 V is being damaged, and below about 2.5 V the damage is severe. The fix is a low-voltage cutoff (LVC) that disconnects the load, paired with a reconnect threshold (LVR) well above it — at least 400 mV higher for Li-ion. Without that gap you get a “brown-in loop”: the device boots, the load sags the battery, it shuts down, the voltage recovers, and it boots again, over and over — worse than a clean shutdown.

Put the protection in two layers:

Both designs follow this pattern. MeshCore’s firmware bootlock puts the board to sleep below 3.3 V and wakes it once the cell recovers to about 3.7 V — roughly 400 mV of hysteresis. The check also runs before the radio starts, so even a marginal wake costs a few milliseconds of microcontroller time rather than a full boot surge. A firmware cutoff only works if the firmware can see the battery, though: on the Xiao, the cell has to connect to the battery pads, not the 5 V pin (see Design 1’s wiring). The hardware backstop is a protected cell in Design 1 and a BMS board in Design 2.

See Solar for IoT — “Protecting against over-discharge” for the three places protection can live and how to layer them.

Rule 4: keep the charge rate gentle, especially in the cold

Charge rate in “C” is charge current divided by battery capacity: 1 A into a 2 Ah cell is 0.5C. Check the peak rate, in full sun: panel watts ÷ battery volts ÷ battery amp-hours.

So if your device will charge below freezing, either keep the peak rate under about 0.1C, or use a charger with a temperature input and a thermistor so charging pauses below 0 °C. Both designs take the first route: Design 1 at 0.08C, Design 2 at about 0.07C. The CN3791 they use has no temperature input, so the thermistor route means a different charger, such as the CN3722 or LT3652.

See Solar for IoT — “Charging in the cold” for the cold-charge nuance and the Canadian field data.

Rule 5: block reverse current

At night the panel is a diode in the wrong direction and will slowly drain the battery. A charger chip keeps this small: the CN3791 both designs use goes to sleep when the panel goes dark, and on a typical module still draws about 30 µA from the battery — about 21 µA of it trickling back toward the panel through the charger’s inductor and switching transistor. That’s negligible next to these loads (0.3% of Design 1’s), so no extra part is needed. If you were wiring a raw panel to the battery without a charger chip, you’d put a Schottky diode (a one-way valve for current — lets electrons flow panel-to-battery, blocks the reverse) in series.

See Solar for IoT — “Reverse-leakage protection” for the full discussion of reverse-current options.


Design 1: Xiao nRF52 MeshCore repeater

A standalone MeshCore LoRa repeater meant to sit on a rooftop or pole for a year untouched, forwarding mesh packets continuously. No detector role, no ESP32 — just the LoRa radio and its mesh-routing firmware. It’s the simplest complete solar design: if your device is a low-power, always-on node, this is the one to adapt.

Power budget

Item Value
Average current (listen mode, at the battery) ~10 mA
Average power (× 3.7 V battery nominal) ~37 mW
Daily energy ~0.9 Wh
Winter sun hours (35° N) 2.5
Required panel rating (Rule 1) 0.9 Wh / (2.5 × 0.40) \(\approx\) 0.9 W
Panel pick 2 W
Battery needed for 5 dark days (Rule 2) 0.9 Wh × 5 × 1.3 / 0.8 \(\approx\) 7.3 Wh nameplate
Battery pick 2× protected 18650, 3500 mAh each (~26 Wh nominal, ~21 Wh usable down to the 3.3 V bootlock)
Days of autonomy on battery alone ~23 days (far exceeds the 5-day target)
Peak charge rate (Rule 4) 2 W / 3.7 V / 7 Ah \(\approx\) 0.08C

Repeaters are always on — they have to be reachable. That’s why the average power is so much higher than a battery sensor that wakes briefly to send a reading and sleeps the rest of the time, even though the Xiao nRF52 itself is a modest chip.

Two choices here go past what the rules strictly require, and both are deliberate:

Bill of materials

Part Qty Approx price (2026)
Seeed XIAO nRF52840 & Wio-SX1262 Kit for Meshtastic (SKU 102010710, both boards) 1 $13.49
Adafruit 6 V 2 W ETFE-laminated monocrystalline solar panel (~136×112 mm) 1 $21
CN3791 6 V-input solar charger breakout (AliExpress generic) 1 $5
Protected 18650, 3500 mAh (Samsung INR18650-35E or Panasonic NCR18650GA) 2 $20
2-cell 18650 holder, parallel-wired, PCB pins 1 $3
JST-PH 2-pin pigtail, 20 AWG silicone 2 $2
IP65 junction box (ABS plastic, ~100×70×40 mm) 1 $8
PG7 cable glands 2 $2
Pole/wall mounting bracket 1 $5
Total about $80

Substitutes that work:

Why an external charger?

The Xiao nRF52840 has a TI BQ25101 Li-ion charger on board — it’s what charges the cell when you plug USB-C into the Xiao. You could skip the CN3791 and wire the panel to the Xiao’s 5V pin — the on-board charger’s input — saving $5 and one module. Three issues make this a bad trade for outdoor solar:

  1. No maximum-power-point tracking. The BQ25101 is a basic linear charger — it pours current into the cell at a fixed limit until the cell is full, but it doesn’t try to hold the panel at the voltage where it delivers peak power. The CN3791 does, and recovers 20–35 % more energy on cloudy or cold days.
  2. ~6.5 V over-voltage protection. The BQ25101’s input over-voltage cutoff sits at about 6.7 V typical (6.5 V min; TI datasheet SLUSBV8C). A 6 V nominal panel’s open-circuit voltage is ~7.7 V at the lab nameplate temperature and climbs past 8 V on a cold morning before the cells warm in the sun — well above the cutoff. Once tripped, the charger disconnects its input; you lose the morning’s harvest until the cells warm enough for Voc to drop back below the threshold on its own. The CN3791 tolerates input up to ~28 V.
  3. 100 mA charge cap on the Seeed board. The BQ25101 chip can charge at up to 250 mA, but Seeed’s board is wired for 100 mA max (and defaults to 50 mA — flipping to 100 mA needs a one-line firmware change to drive a board pin low). Either way, that throws away most of the midday harvest from a 2 W panel.

For $5, the CN3791 earns its keep. If you’re building an indoor or USB-fed companion node (no solar), the Xiao’s built-in charger is fine — skip the CN3791 entirely.

If you want a simpler parts count and can accept 10–20 % lower harvest, the CN3065 (~$2.50) is a sibling without MPPT — just constant-input-current regulation with reverse-current blocking. Mind its input range, though: the CN3065 tops out at 6 V, so a 6 V panel (open-circuit ~7.7 V on a cold morning) can over-volt it — it’s only safe here if your panel’s cold Voc stays under 6 V. Avoid bare TP4056 modules: no MPPT and no reverse-current blocking to the panel at night — and while the chip itself tolerates 4–8 V, a cold 6 V panel’s open-circuit voltage (~8 V) sits right at that ceiling.

Wiring

MeshCore repeater: panel, charger, battery, and board. The CN3791 handles MPPT and the Li-ion charge profile; the cells connect to the Xiao’s BAT+/BAT− pads, so MeshCore’s 3.3 V bootlock can measure them and act as the primary low-voltage cutoff, and each protected 18650’s built-in protection circuit is the 2.5 V backstop.

A quick glossary for the wire paths below: JST-PH is the small 2 mm-pitch keyed connector that’s standard for hobbyist battery leads; AWG is American Wire Gauge (smaller number = thicker wire, so 20 AWG is moderately thick); u.FL is the tiny coax snap-on connector for board-level RF antennas.

Wire paths, in order:

  1. Panel → CN3791 VIN/GND. 20 AWG silicone wire, JST-PH pigtail, through a cable gland.
  2. CN3791 BAT output → 2-cell 18650 holder B+/B−. Short leads inside the enclosure.
  3. 18650 holder → Xiao nRF52840 BAT+ / BAT− pads. These are two small solder pads on the underside of the Xiao, near the USB-C connector; solder short leads to them. The board regulates its own 3.3 V rail from there.
  4. Xiao nRF52840 ← → Wio-SX1262. The Wio-SX1262 plugs into the Xiao’s stack connector — no separate wiring needed.
  5. Antenna (915 MHz for US, 868 for EU) → u.FL on the Wio-SX1262.

Why the battery pads and not the 5V pin? The Xiao’s 5V pin (pin 14) is the input of its on-board USB charger. A cell wired there does power the board — through a diode into the 3.3 V regulator — but the Xiao measures battery voltage on the charger’s output, the BAT pads, which then have no cell on them. MeshCore would be reading the idle charger instead of the battery, and at exactly the voltage where the bootlock should act, that charger shuts itself off and the reading drops to zero, which the firmware ignores as invalid. The same lesson applies to any board with a built-in charger: the battery goes on the battery terminals, so the board can see it.

With the cell on the BAT pads, the Xiao’s own charger simply sits idle unless you plug in USB, in which case it tops the cell up at 50–100 mA alongside the CN3791 — harmless.

The CN3791 handles MPPT and charge termination at 4.2 V, and goes to sleep (drawing about 30 µA) when the panel is dark. The protected 18650 cells handle their own over-discharge / over-charge / short-circuit backstop — each cell has a small BMS PCB built into the positive cap. Apart from the bootlock check at startup and battery-voltage reporting, the nRF52840 has no role in power management — it just draws from the battery rail and talks to the LoRa radio (LoRa stands for “Long Range” — it’s the low-power, long-range radio standard that MeshCore uses for the mesh).

Enclosure and mounting

A 100×70×40 mm IP65 (dust-tight, splash-resistant — fine for rain and snowmelt) junction box fits everything with room to route wires. Panel mounts on the outside, facing true south (or north in the southern hemisphere), tilted 5–15° steeper than your latitude (see Orientation and tilt). Two quick wins: leave a few millimeters of air gap between panel and enclosure so the panel can dump heat (a hot panel loses 20% of its output), and use a light-colored enclosure so the interior — where the battery lives — stays cooler in summer.

Mount higher than snow line if you get snow. Don’t mount where a tree branch or building corner will shadow the panel for part of the day — shadow on even 20% of a single-string panel can drop output by much more than 20%.

See Solar for IoT — “Temperature, placement, and mounting” for the hot-enclosure math and the right way to get air flow behind the panel.

Adapting this design


Design 2: Drone-detector node

A remote node for a MeshCore-based drone detection system. Two Xiao modules share a carrier PCB: an ESP32-C5 runs WiFi monitor mode on both 2.4 and 5 GHz to catch FAA Remote ID broadcasts (the FAA-required identification beacons every drone has to transmit), plus BLE for the Bluetooth variant of Remote ID; an nRF52840 with Wio-SX1262 relays each detection over MeshCore to a base station where it can be analyzed.

The design comes from an unreleased fork of the drone-mesh-mapper project. The public upstream repository has the original drone-detection and mapping code, but not the MeshCore firmware or the carrier board described here. Read it as a design study: the power-system reasoning carries over to any node with a load this size.

Target deployment: North Carolina tree-canopy sites with meaningful partial shade during parts of the day — which drives the 2-panel parallel-OR topology below.

Power budget

Item Value
ESP32-C5 in default low-power scan mode ~50 mA avg @ 3.3 V
nRF52 MeshCore relay (listen) ~10 mA avg @ 3.3 V
Carrier board / linear-regulator overhead ~10 mA
Total average current (at the battery) ~70 mA
Average power (× 3.7 V battery nominal) ~260 mW
Daily energy ~6.2 Wh
Winter sun hours (35° N) with partial-shade derate 2.5 × 0.75 = 1.9
Required panel rating (Rule 1) 6.2 Wh / (1.9 × 0.40) = 8.2 W
Panel pick 2× 10 W “12 V-class” panels, parallel-OR’d (why 20 W: see below)
Battery needed for 5 dark days (Rule 2) 6.2 Wh × 5 × 1.3 / 0.7 \(\approx\) 58 Wh nameplate
Battery pick 3× unprotected 21700, 5000 mAh each in a 4-bay holder (~55 Wh nominal, ~40 Wh usable to the ~3.5 V cell floor)
Days of autonomy on battery alone ~3.5–6 days (modeled from ~40 Wh usable and a ~70–130 mA average draw — the C5 dual-band scan is the big unknown; confirm with a PPK2 once built). Populating the 4th bay → ~4.5–8 days.
Peak charge rate (Rule 4) 1 A (charger setting) / 15 Ah (3 cells in parallel) \(\approx\) 0.07C — under 0.1C, so it can charge below freezing like Design 1

Three cells land just under Rule 2’s answer for 5 dark days at the modeled 70 mA, and the real draw may be higher. That’s what the empty fourth bay is for: measure the node’s actual current once it’s built, then populate the fourth cell if the numbers call for it. It’s the general lesson of this design — the power budget is only as good as the current measurement under it.

The remote_meshcore_node firmware in use has three power modes that it switches between automatically: a low-power scan mode by default, a high-power mode when a drone is being tracked, and a near-sleep mode at night, when a detection is unlikely. That’s what keeps the ESP32-C5’s average current down. A plain continuous-scan ESP32-C5 would draw 180–200 mA average and need a much bigger battery.

Why 21700 and not 18650? The drone-detector node draws much more current than the repeater (70 mA average vs 10 mA), so the pack has to store substantially more energy for the same off-grid runtime. A 21700 cell at 5000 mAh holds ~43 % more energy than a 3500 mAh 18650 in only slightly more physical space (21×70 mm vs 18×65 mm). Three 21700s in a 4-bay holder give margin and leave one bay open for later expansion.

Why 20 W of panel for an 8 W requirement?

Rule 1 asks for 8.2 W, and the design fits 20 W. The reason is the site: under a moving tree canopy, one panel is often in shade while the other is in sun, so each panel is sized to carry close to the whole requirement on its own.

Most of that capacity can’t be used at noon in full sun anyway. The CN3791 module’s charge current — set by a sense resistor on the board; this design assumes 1 A, and many modules ship set for 1–2 A — caps what reaches the battery at roughly 4–8 W. The surplus earns its keep in dim winter light and partial shade, which is exactly when the node needs it.

This is also near the upper edge of what chip-level chargers are for. The load is only a quarter of a watt, but the panel array is 20 W. Much beyond this — a load of several watts, or more than a few amps of charge current — and a dedicated solar charge controller is the better tool.

Why two panels? The parallel-OR topology

The battery and a single charger chip are shared, just like Design 1 — what’s different here is the panel side. The node uses two separate 10 W panels, each with its own Schottky diode in series, wired to the same charger input. Picture it this way:

 Panel A --> SS34 --+
                    |
                    +--> CN3791 --> BMS P+/P- --> pack + carrier board
                    |
 Panel B --> SS34 --+

When both panels see similar light their diodes conduct simultaneously and the currents sum at the charger input — in the easy case the topology behaves like ordinary parallel panels. The diodes earn their keep when illumination diverges: as one panel falls into partial shade, its loaded voltage drops, its diode reverse-biases, and the brighter panel keeps feeding the charger without being dragged down by its sibling.

Why bother? At a tree-canopy site, each panel spends parts of the day under a moving shade pattern. A traditional panel-in-parallel (no diode) would let the shaded panel sink current from the sunlit one. A panel-in-series would fail catastrophically when one cell is shaded — shading just 20% of a single-string panel typically drops output by more than half. The dual-Schottky diode-OR keeps most of the combined output and avoids the catastrophic loss modes of both plain-parallel wiring (a shaded panel sinking current from its neighbor) and series wiring (one shaded cell collapsing the string). It’s not a substitute for true per-panel MPPT, though — both panels that are still conducting are pinned to the charger’s single input voltage, so a panel whose ideal operating point has drifted gives up a little; with same-model, similarly-aimed panels under moving canopy shade that compromise is small.

Each SS34 drops about 0.3–0.4 V at the panel’s ~0.5 A operating current — roughly 2% of a 10 W panel’s output — and that’s well worth the harvest you recover when the two panels diverge in shade. Using half-cell panels (a modern construction where the module is wired as two parallel half-strings of half-height cells) compounds the benefit — when shade falls on one half-string, only that half drops out, not the whole panel. Most current product listings call this out as “half-cell PERC” — a high-efficiency cell architecture; either keyword in a product title is a good sign.

See Solar for IoT — “Shading and partial light” for the full shading-loss geometry and why half-cell matters.

Bill of materials

Part Qty Approx price (2026)
Seeed XIAO ESP32-C5 (scanner) 1 $8
Seeed XIAO nRF52840 & Wio-SX1262 Kit for Meshtastic (SKU 102010710) 1 $13.49
2-XIAO carrier PCB (from the fork’s hardware/node-carrier/, JLCPCB factory-assembled) 1 $5 (at 10-qty)
10 W “12 V-class” half-cell glass panel, Vmp \(\approx\) 18 V (Newpowa 10W 12V Mono 10BB on Amazon, or xxrsolarpv bulk) 2 $26 ea / $8 ea bulk
SS34 Schottky diode (SMA package, 40 V 3 A) 2 $0.20 ea
CN3791 solar charger breakout, 18 V-class set point, 1 A charge current (see note below) 1 $5
Molicel M50A / Samsung 50E 5000 mAh, unprotected (authenticated) 3 $27 ($9 each)
4-bay 21700 parallel-wired holder with JST-PH lead 1 $5
DW01A + FS8205A 1S BMS board (hardware backstop to the firmware cutoff) 1 $0.30 (bulk)
JST-PH 2-pin pigtail 2 $2
2.4 / 5 GHz dual-band RP-SMA whip antenna + u.FL-to-RP-SMA bulkhead pigtail (C5) 1 $7
915 MHz u.FL antenna (Wio-SX1262) 1 $4
IP65 enclosure (ABS plastic, ~158×90×65 mm to fit the 4-bay holder) 1 $15
PG7 cable glands 3 $3
Pole mount bracket 1 $8
Total (single node, Amazon panels) about $155
Total (10-unit batch, xxrsolarpv panels via Alibaba — duty-paid shipping, tariffs included) about $120/node

“10BB” in a panel listing means ten busbars — the thin silver lines across each cell that carry its current; more busbars lose a little less to resistance.

The 2-XIAO carrier design lives in hardware/node-carrier/ in the unreleased fork. It’s a 65×40 mm 2-layer board written in atopile (a tool that describes circuit boards in code rather than drawing them); PCB (printed circuit board) placement and routing are scripted. It’s ordered fabbed and assembled from JLCPCB (the bare surface-mount components are populated at the fab), then 4× 1×7 through-hole female headers are hand-soldered for the two XIAO module sockets.

Checking the charger’s set point

The CN3791 comes in “6V / 9V / 12V / 18V” variants on AliExpress, and the numbers are confusing. They follow an old solar-industry convention: a panel with a maximum-power-point voltage around 18 V (like the ones in this BOM) has historically been sold as a “12-volt panel” because it’s designed to charge 12-volt lead-acid batteries. But vendors don’t agree on what the module labels mean — one lists its “12V” module’s divider as “set to 12V.” Hold an 18 V-Vmp panel at 12 V and it delivers only about 70% of its power.

So don’t trust the label; check the set point. The CN3791 holds its MPPT pin at 1.205 V through a two-resistor divider from the panel input, so the panel operating voltage is

\[V_{\text{MPPT}} = 1.205 \times \left(1 + \frac{R_{\text{top}}}{R_{\text{bottom}}}\right)\]

Read the two resistors on the MPPT pin (their SMD codes, or measure them out of circuit), or simply measure the panel voltage at the module’s input while it charges in full sun. You want it within about a volt of your panel’s Vmp — about 18 V here, about 6 V for Design 1. If a module is off, buy the next variant up, or swap the top resistor to move the set point.

Check two more things before ordering a 10-unit batch:

Wiring

Drone-detector node: two panels diode-OR’d into the CN3791. The charger and the carrier both connect on the BMS’s pack side (P+/P−), so the BMS backstops over-charge as well as over-discharge. The carrier feeds the ESP32-C5 XIAO through a polyfuse and Schottky to its 5V pin, and the nRF52840 XIAO through flying leads to its battery pads, so both firmware bootlocks can see the pack and act as the primary 3.3 V cutoff.

Wire paths:

  1. Each panel’s positive lead → through its own SS34 diode (forward direction: panel → CN3791) → both diode outputs join → CN3791 VIN. The two SS34s can live on the carrier PCB or on a small adapter board in the enclosure.
  2. Panel GNDs → CN3791 GND.
  3. Cell pack B+ / B− → DW01A+FS8205A BMS board B+ / B− pads. Keep leads short and use 22 AWG or thicker wire.
  4. BMS P+ / P− → one shared junction (a solder joint or lever connector) that feeds both the CN3791 BAT+ / BAT− and a JST-PH pigtail to carrier J1 (battery input). Putting the charger on the BMS’s pack side lets the BMS catch a charger that fails to stop at 4.2 V, not just a flat battery. The carrier distributes this rail through its polyfuse (a self-resetting current fuse — pops if something shorts, and re-conducts after the short clears).
  5. Carrier rail → the two XIAOs. The ESP32-C5 takes it through the carrier’s reverse-blocking Schottky diode to its pin 14 (5V); its scanner firmware reads the pack through the carrier’s own voltage divider, so that works. The nRF52840 XIAO takes it on its BAT+ / BAT− pads through two short flying leads from the carrier, for the reason explained under Design 1’s wiring: MeshCore measures battery voltage on those pads and can’t see a pack fed in through pin 14.
  6. ESP32-C5 D6 / D7 \(\leftrightarrow\) nRF52 D7 / D6 (a serial cross-link — the same 2-wire serial bus that’s the default on every Arduino, also called UART). Wired on the carrier PCB; no external wires.
  7. ESP32-C5 u.FL → pigtail → RP-SMA bulkhead → dual-band whip antenna. The C5 ships with a small flexible flat antenna (a thin printed circuit on a sticker) — fine indoors, but outdoors the bulkhead and a screw-on whip do much better; RP-SMA is the standard connector you see on WiFi routers. Mount it on the opposite side of the enclosure from the LoRa antenna — coupling between 2.4 GHz and 915 MHz antennas at close range costs gain on both.
  8. Wio-SX1262 u.FL → 915 MHz antenna.

Carrier revision needed. The fork’s current carrier feeds both XIAOs through pin 14. That powers them fine, but leaves the nRF52840’s bootlock and battery reporting reading the XIAO’s idle charger instead of the pack. The flying-lead feed above (or pogo pins reaching the BAT pads) is the fix; until then, count only the ESP32-C5 bootlock and the BMS as the pack’s protection.

Keeping the battery alive: two layers of protection

This is Rule 3’s two-layer pattern with the hardware layer built from separate parts, because the cells are unprotected.

Layer 1 — Firmware bootlock at 3.3 V (primary)

Both Xiao modules check the battery voltage when they start up. If the cell is below 3.3 V, they go into a deep sleep that pulls only a few microamps — much less than the cell’s own self-discharge. They wake up automatically when the sun recharges the cell, or when you plug in USB. No user intervention, no reset button.

Bootlocking the ESP32-C5 — the big load — at 3.3 V (~3.5 V at the cell, once the carrier’s series diode and the XIAO’s LDO, the low-dropout linear regulator that makes its 3.3 V, are counted) leaves the cell resting well above the 2.4 V hardware-BMS floor, at a cost of only about 30% of the pack’s capacity — not the ~50% you might guess from the voltage, since Li-ion delivers most of its energy on the flat part of the curve above 3.5 V. The long service life (years, not months) comes from shallow daily cycling — in normal solar operation the pack tops up every day and only sips a little overnight, reaching the 3.3–3.5 V bootlock floor (a deep ~70–85% discharge) only during rare multi-day dark spells. The third 21700 cell is there for that dark-stretch autonomy margin.

Layer 2 — Hardware BMS board (backstop)

Firmware is the primary defense, but a bad flash or a firmware bug could disable it. A tiny ~$0.25 DW01A + FS8205A BMS board sits between the cell pack and everything else as a safety net — if the cells ever actually reach about 2.4 V, the BMS physically disconnects them (reconnecting at 3.0 V), and if the charger ever fails to stop at 4.2 V, it disconnects at about 4.3 V. In normal operation the BMS does nothing; the firmware cut off hours earlier at 3.3 V.

The BMS also protects against a short-circuit across the battery output (e.g., a wiring mistake during assembly), which the firmware can’t help with.

Summary

Cell voltage What happens
4.3 V (charging) Hardware BMS disconnects — only if the CN3791 fails to terminate at 4.2 V.
3.3 V Firmware bootlock on both Xiao modules; both enter deep sleep and wake on voltage recovery or USB.
2.4 V Hardware BMS physically disconnects the pack — should never happen in practice because the firmware cut off hours earlier, but catches firmware failures and wiring mistakes.

Design 1’s repeater doesn’t have a separate BMS board in its BOM because the protected 18650 cells have one built into the cell’s positive cap — same DW01A-class protection, just packaged inside the cell. MeshCore’s firmware bootlock is the primary layer there too. Both designs layer a software cutoff over a hardware cutoff; they just package the hardware side differently.

Enclosure and mounting

Panels mount on top of the enclosure or on a separate bracket above it; the node sits inside with a cable gland for each antenna and one for the panel pigtail. The two panels want to be roughly co-planar but not touching — a small air gap between them (and between panels and the enclosure) helps both heat dissipation and makes the diode-OR useful, since they’ll see slightly different shade patterns through the day.

NC tree-canopy context: favor higher-up mounting where afternoon sun reaches through a gap even in leaf-out season, and plan to revisit the site once after leaf-out to check whether panel orientation still makes sense. A daily budget of about 6 Wh at 70 mA average is thin enough that a site that looked fine in winter can go dark in June.

Adapting this design


Designing your own device

Both designs follow the same sequence. To design your own:

  1. Measure average current at the battery through a full duty cycle — sleep, wake, transmit, back to sleep — and multiply by 3.7 V. Everything downstream scales with this one number, so measure it rather than guess. (Design 2’s biggest uncertainty is exactly this.)
  2. Size the panel with Rule 1, using your site’s December peak sun hours from NREL PVWatts. Derate further for shade you can’t avoid, as Design 2 does. Round up to a panel you can actually buy.
  3. Read the panel’s datasheet (see Solar for IoT — “Reading a panel datasheet”). Vmp picks the charger variant — then check its actual set point; the cold open-circuit voltage has to stay below the charger’s maximum input.
  4. Pick the charger. For roughly 10 mW to a few watts of load, a CN3791 module matched to your panel’s Vmp; below about 1 mW, a micropower harvester chip; in between, either (see Solar for IoT — “Which chip class to use”).
  5. Size the battery with Rule 2, using the usable fraction that matches your cutoff.
  6. Layer the protection (Rule 3): a firmware or charger cutoff around 3.0–3.3 V with a higher reconnect, over a hardware backstop — a protected cell or a 1S BMS board. If your board has its own charger, wire the cell to its battery terminals so the firmware can measure it.
  7. Check the peak charge rate (Rule 4): panel watts ÷ battery volts ÷ battery amp-hours. Under 0.5C is fine above freezing; if it will charge below freezing, get under about 0.1C (more cells, or a lower charge-current setting, as in both designs) or use a charger with a thermistor input.
  8. Check reverse current (Rule 5) — a charger chip keeps it to microamps; a bare panel needs a series diode. If the site has unavoidable shade, consider two smaller diode-OR’d panels, as in Design 2.
  9. Add a buffer capacitor across the battery rail if the load pulls short bursts: 100–470 µF for LoRa or WiFi transmit, more (up to a few millifarads) for a cellular modem.

This approach covers loads from well under a milliwatt up to a few watts. Once the load itself reaches several watts — enough to need more than a few amps of charge current — you’ve outgrown chip-level chargers and want a dedicated solar charge controller instead.


Enclosure, mounting, weatherproofing

This applies to both designs and to most builds like them.

IP rating

IP65 is plenty for devices like these — it’s dust-tight and rated against low-pressure water jets, which covers rain, snowmelt, and everything short of a pressure washer. Plastic junction boxes from the electrical aisle of any hardware store meet this, and cheap Amazon project enclosures marketed as “IP65 / IP67 waterproof” are fine in practice.

Sealing

Every wire that enters the enclosure is a potential leak path. Two ways to handle this correctly:

Don’t just drill a hole and run a wire through. It’ll leak within a month.

Orientation and tilt

Panel faces the equator (south in the northern hemisphere), tilted at an angle roughly equal to your latitude. For winter-dominated designs like these, tilt 5–15° steeper than latitude — it loses a little summer harvest in exchange for more winter harvest, which is when you need it. At 35° N, that’s 40–50° from horizontal.

A pole mount with a U-bolt bracket is simple and lets you adjust tilt once installed. For rooftop installation, the panel can strap to an existing structure; for pole mount, a 1.5-inch galvanized pipe driven into the ground or clamped to a fence post works.

Heat

A black plastic enclosure in direct sun can hit 60–70 °C (140–160 °F) inside even on a mild day. That bakes the battery. Three easy fixes stacked:

The panel itself loses output when it heats up (about 0.4% per °C / 0.22% per °F above the 25 °C / 77 °F lab nameplate), so even the panel wants air behind it. Two gains for one intervention.

See Solar for IoT — “Temperature, placement, and mounting” for the full heat discussion and the Nominal Operating Cell Temperature rating on datasheets (a more realistic rating than the lab nameplate).

Antenna placement

The MeshCore repeater (Design 1) has a single 915 MHz antenna — just mount it clear of metal, at least a quarter wavelength (about 8 cm at 915 MHz) from any large metal surface or bracket.

The drone-detector node (Design 2) has two antennas (2.4/5 GHz for the ESP32-C5, 915 MHz for the Wio-SX1262). They’re far apart in frequency so they don’t cross-talk much, but you still want them on opposite sides of the enclosure so the metal parts inside (battery, the metal layers on the circuit board) don’t shadow either one.

Antenna and panel also compete for the same spot. A whip beside the panel can shade it at some sun angles, and a metal-framed panel between the antenna and the rest of the mesh blocks signal. Put the antenna above the panel, or on its north (shade) side.

Sourcing lithium cells — buy direct from a specialist

The battery is the easiest part of the build to get wrong. The 18650 and 21700 markets are polluted with counterfeits — no-name cells relabeled as Samsung or Panasonic, or “4000 mAh” cells that actually hold 800 mAh. You can’t eyeball the difference without a battery tester.

Buying a DW01A+FS8205A BMS board (for unprotected cells)

The hardware backstop for a pack of unprotected cells, as in Design 2. You need one 1S board per pack. They’re pennies in bulk.


Pitfalls checklist

A short, ordered list of the mistakes that actually kill deployments:

  1. Sizing from the nameplate. The panel’s printed rating is a lab number. Multiply by 0.40 before you design.
  2. Skipping the worst-month check. Summer gives you 2× the harvest of winter at mid-latitudes. If December works, the rest of the year works.
  3. Guessing the load instead of measuring it. Average current at the battery drives every other number. Measure it through a full duty cycle.
  4. Panel in a shadow you didn’t notice at install. Walk the site at morning, noon, and afternoon. Mark where the shadow edge falls. Expect worse after leaf-out.
  5. No cutoff, or cutoff with no hysteresis. Always a cutoff with a higher reconnect — at least 400 mV for Li-ion — layered over a hardware backstop (Rule 3).
  6. No buffer capacitor across the battery rail. If your load pulls short bursts (LoRa transmit, WiFi transmit), a small battery alone can sag under the burst. Add a buffer capacitor — 100–470 µF total for LoRa or WiFi bursts (up to a few millifarads for a cellular modem), mixing a ceramic capacitor for fast bursts with an electrolytic capacitor for the bulk — near the board’s power input.
  7. Charger input limit below the panel’s cold open-circuit voltage. A “6 V” panel reaches about 8 V on a cold morning. Check the charger’s maximum input against the cold Voc, not the nameplate.
  8. Wrong CN3791 set point. The 6 V, 9 V, 12 V, and 18 V modules look identical — the only difference is the resistor divider that sets the maximum-power-point voltage, and vendors label it inconsistently. Check it: \(V = 1.205 \times (1 + R_{top}/R_{bottom})\), or measure panel voltage while charging. It should sit near your panel’s Vmp.
  9. Panel wired to battery without a charger. Damages the cell on the first sunny day. Always have a charger chip.
  10. Assumed IP67 enclosure but the cable gland wasn’t tightened. Common. Tighten until the grip ring deforms visibly.
  11. Mounting the panel flush against a black enclosure. 40 °C (~70 °F) above ambient is common. Leave an air gap.
  12. Antenna and panel shading each other. A whip beside the panel shades it at some sun angles; a metal-framed panel in the antenna’s line of sight blocks signal. Antenna above the panel, or on its north side.
  13. Counterfeit cells, even from “reputable” Amazon storefronts. Amazon’s commingled stock from before March 31, 2026 can still ship a fake under a real brand’s listing. Buy direct from a specialist’s own website (not Amazon, not AliExpress). See § Sourcing lithium cells.
  14. (Boards with a built-in charger) Battery wired to the 5 V input instead of the battery pads. The board runs, but its firmware measures the battery on the charger’s output and can’t see the cell — so a firmware cutoff like MeshCore’s bootlock silently stops working. On the Xiao, use the BAT+ / BAT− pads.
  15. (Firmware cutoffs) Treating the firmware bootlock as the whole safety story. A bad flash or bug could disable it. Always layer a hardware backstop — a protected cell, or the ~$0.25 DW01A+FS8205A BMS board. Don’t skip the BMS to save a quarter.
  16. (Unprotected packs) Buying a 2S/3S BMS by mistake. Only 1S boards protect a parallel-only pack correctly. Confirm “1S” in the title before clicking buy.

Troubleshooting

When a node misbehaves it’s almost always one of a handful of things. Work down the list.

Symptom Likely cause What to check
Battery never charges, even in full sun Wrong CN3791 variant, panel voltage outside the charger’s range, or a cold solder joint on the panel lead Measure panel voltage in sun; confirm it exceeds battery voltage and sits inside the module’s input range; reflow (re-melt) the VIN/GND joints
Charges fine on the bench, dead after a week outside Undersized for the worst month, or a shadow you missed at install Recheck Rule 1 with December sun hours and a measured load; walk the site morning, noon, and afternoon and watch where the shadow edge falls
Boots, runs a few seconds, shuts off, repeats Brown-in loop — battery low, cutoff without enough reconnect hysteresis Charge the cell fully and retest; confirm the reconnect threshold sits well above the cutoff (Rule 3)
Won’t boot after a cold, cloudy stretch Cell sat below the firmware bootlock and hasn’t recovered to its ~3.7 V wake point Give it a sunny day or top the cell up over USB
Battery slowly dies over weeks with the panel connected Reverse leakage at night (rare with these chargers), or a parasitic draw you didn’t budget for Measure current out of the battery in the dark; confirm a charger — not a raw panel — is wired in
Poor radio range Antenna too close to metal, sitting in the panel’s shadow, or two antennas coupling (Design 2) Move the antenna a quarter wavelength off metal; keep the 915 MHz and 2.4/5 GHz antennas on opposite sides
Reported battery voltage is wrong, or the bootlock never kicks in Battery wired to the Xiao’s 5V pin instead of its BAT pads Move the cell to the BAT+ / BAT− pads (see Design 1’s wiring)
Charges, but slower than the panel should allow Charger’s MPPT set point far from the panel’s Vmp Measure panel voltage while charging in sun; compare with Vmp (Checking the charger’s set point)

If none of these fit, log battery voltage (measured at the cell itself) and panel voltage over a full day. That trace usually points straight at the problem.


Further reading