A replacement PCB for the Solar Buoy available on Taobao, inspired by the Meshtastic Solar Buoy Instructables project.
Designed as a 1:1 drop-in replacement for the original buoy PCB, adding Meshtastic LoRa capability.
The weatherproof enclosure with built-in fixing points makes it easy to attach a rope and sling the node onto a tree branch, giving it a convenient second life as an outdoor Meshtastic node.
The battery and solar panels are also re-used, making it a relatively low-waste project, though the original PCB will be discarded; hopefully you will find a second life for the many LEDs it comes with.
| Front | Back |
|---|---|
![]() |
![]() |
- RAK3172 (STM32WLE5CC with integrated SX1262 LoRa)
- Bosch Sensortec BME280 environmental sensor (optional - marked DNP)
- Torex XC6206 3.3V LDO regulator
- TP4057 Li-ion battery charger
- JST PH connector (plug-and-play with factory battery)
- Solder pins (for factory solar panel)
- Charge indicator LEDs disconnected by default via solder bridge (saves ~1mA quiescent)
Note
You will need to supply a few extra parts yourself — see Additional items to source below.
Note
If you're using Bouni's JLCPCB Tools to order PCBA from JLCPCB (see Ordering PCBs below), all components are already specified — using JLCPCB basic/extended basic parts where possible — so no manual BOM work is needed.
- Interactive BOM — click-to-highlight component placement, cross-referenced with the PCB layout
These aren't in the KiCad project and need to be bought separately:
| Item | Notes |
|---|---|
| Solar Buoy (Taobao) | Donor unit — its enclosure, battery, and solar panel are re-used; the JST PH connector can also be harvested from its PCB |
| U.FL/IPEX to waterproof SMA pigtail | <5cm if the SMA bulkhead exits through the top of the enclosure, >15cm if it exits through the bottom — length depends on the internal routing path to the mounting hole |
| LoRa antenna with SMA connector | Match to your region's Meshtastic frequency band (e.g. 868MHz EU, 915MHz US/AU) |
| 7mm drill bit | For the SMA bulkhead hole in the enclosure — a brad point bit is ideal for precisely locating the hole |
| 5-pin 2.54mm male pin header (Dupont style) | Generic header, soldered onto the PCB during assembly |
Important
If ordering PCBA (assembly), double check the per-component rotations shown in the Component Placements step of JLCPCB's PCBA order flow — the plugin's default rotation for a footprint doesn't always match the rotation JLCPCB has on file for that specific LCSC part.
Gerbers, BOM, and CPL (component placement) files are generated with Bouni's JLCPCB Tools plugin for KiCad:
- Install it via Tools → Plugin and Content Manager in KiCad, searching for "JLCPCB Tools" (or install manually per the plugin's README).
- Open
jungle-buoy.kicad_pcbin the PCB Editor and launch the plugin from its toolbar icon. - Assign/verify an LCSC part number for each footprint (already populated for this project in
jlcpcb/project.db). - Use the plugin's Fabrication tab to export Gerbers, BOM, and CPL in one pass — output lands in
jlcpcb/gerber/andjlcpcb/production_files/. - Upload the generated Gerber zip (and BOM/CPL if ordering assembly) at jlcpcb.com/quote.
Default JLCPCB order settings work fine. If ordering PCBA (assembly), set Tooling holes → By JLCPCB.
panelize.sh uses KiKit to generate a 2×2 panel optimised for JLCPCB PCBA ordering:
- Layout — 2×2 grid with 2mm board spacing, yielding a ~94×88mm panel
- Tabs — single 6mm fixed tab per board side for clean separation
- Mouse bites — 0.6mm drill, 1mm spacing, 0.3mm protrusion per JLCPCB's panelisation guide
- Frame — 5mm tight frame with copper fill and 1mm fillet
- Tooling holes — 3× 1.152mm holes (JLCPCB standard) at 2.5mm offsets
- Fiducials — 3× fiducials with 1mm copper, 2mm opening
Run with:
./panelize.shOutput is written to jungle-buoy-panelized.kicad_pcb.
Follow the same Bouni's JLCPCB Tools export steps above, but on jungle-buoy-panelized.kicad_pcb. When ordering, set:
- Delivery Format → Panel by Customer
- Panel Format → Column: 2, Row: 2
If ordering PCBA, also set Tooling holes → By Customer.
- The JST
S2B-PH-SM4-TBconnector (J1) can be omitted from the PCBA order if you're comfortable desoldering it from the original solar buoy PCB and re-soldering it onto the Jungle Buoy PCB — this saves the ~US$3 JLCPCB PnP loading fee plus the component cost. It's possible but fiddly to hand-solder, best done with a fine- or chisel-tipped iron, or a hotplate. - The RAK3172 module (U1) can also be hand-assembled — I assembled it with an MHP30 mini hotplate, partly to use the RAK3172-T variant, which isn't stocked on JLCPCB and is only available from RAK's official stores (I got mine on AliExpress). It's fine to have JLCPCB assemble a JLCPCB-stocked RAK3172 variant instead if you'd rather not hand-solder.
- Bring a pot of water to a boil and immerse the lamp side of the buoy shell in it to soften the silicone sealant — this makes the shell easier to open without cracking it.
Warning
The shell will be close to boiling hot afterwards — don't grip it directly. Only handle it through a towel or mat to avoid scalding yourself.
- Using a towel or a car dashboard mat for maximum grip, twist the buoy head hard anti-clockwise — it will release.
- Clean off the old silicone; it will have been damaged by the unscrewing anyway.
- The rubber gasket should be sufficient waterproofing on its own, but you can replenish the silicone later during reassembly — after you've confirmed the firmware is properly configured, especially with a remote admin key.
- Disconnect the battery, unscrew the PCB, and carefully pull out the components.
- Don't pull too hard on the wires — slowly ease the bundle of solar panel wires and the battery out.
- It's possible to solder without pulling everything out, but it's ergonomically more challenging.
- Desolder the solar panel wires from the old PCB.
- Harvest the JST PH connector if you plan to re-use it on the new PCB.
- Solder on any remaining components — such as the harvested JST PH connector if you're re-using it — plus anything else you didn't have JLCPCB assemble.
- Solder on a 5-pin 2.54mm male pin header.
- Solder the solar panel wires.
- The wire should enter from the top of the PCB to match the original design; bottom entry also works, but the wire bundle may get squashed against the sponge behind the PCB.
- The solder pads next to the connector can be bridged with a blob of solder to re-enable the charge/done LEDs, at the cost of some solar power. Firmware detection of charging works fine either way, whether or not the pads are bridged.
- Do a final visual inspection for shorts or damage, then plug in the battery.
- Build the firmware from mesh-malaysia/meshtastic-firmware on the
feature/jungle-buoy-variantbranch — be sure to select the jungle-buoy variant when building. - Find the built hex file at
.pio/build/jungle-buoy/*.hex.
- Open STM32CubeProgrammer.
- Connect GND, TX, and RX to a USB-TTL serial adapter.
- Optionally also connect 3.3V (to power the MCU if the battery isn't connected) or 5V (to charge the battery while flashing).
Caution
Do not connect 5V to the 3.3V pin — this will permanently damage the STM32WL.
- Put the RAK3172 into bootloader mode: hold down BOOT, tap RESET, then release BOOT — the BOOT button must remain held while the board is reset.
- Select the UART protocol in STM32CubeProgrammer.
- Select the correct port for your USB-TTL serial adapter.
- Click Connect.
Note
The board can also be flashed via SWD using the Tag-Connect header, instead of steps 1–6 above.
- Switch to the Option Bytes tab → BOR Level → set BOR_LEV to 4 (reset threshold ~2.8V).
- This protects the lithium battery by shutting the node down at a conservatively high voltage before over-discharge.
- Hold BOOT, then click Apply to save the option bytes.
- The board will re-launch into bootloader — release BOOT once STM32CubeProgrammer reconnects and reports the option bytes were programmed successfully.
- If you forget to hold BOOT, don't worry — the option bytes are still saved. Just repeat the bootloader-entry sequence from the Connect step above to re-enter and reconnect.
- Switch back to the Memory & File editing tab → Open file → select the hex file.
- Click Download.
Now is a good time to test solar charge detection. Shine a bright light across at least 2 panels — either the charge LED (amber) will light up if the pads were bridged, or the blink pattern will change from rapid flashing to a slow blink in Meshtastic, since it detected charging.
Note
The charging indication may already be in effect if the node is in a bright enough place.
- Make sure STM32CubeProgrammer and any other serial terminal that may be holding the port are disconnected.
- Open the Meshtastic desktop app (macOS) or web client and connect to the same UART port as before.
- Temporarily connect the SMA pigtail and an antenna to the RAK3172.
Caution
Don't let the node transmit without an antenna connected — it can damage the LoRa frontend.
- Perform the basic configuration of the node.
- Load a remote admin key into the Security settings.
- This is important: it's the only way to configure the node from another node's client app. The STM32WL has no Bluetooth or Wi-Fi, so without remote admin set up, the node is impossible to configure except physically.
- Make sure you're fully satisfied with the node configuration and have confirmed remote admin is accessible, then disconnect the programming/charging wires.
- Insert the components back into the enclosure.
- Tidy up the wiring.
- Re-insert the triangular foam that packs the battery and solar panels in place.
- It has a notched side, which needs to face where the wires travel up to the PCB.
- Screw down the PCB.
Tip
Back the screwdriver off anti-clockwise a bit first, to let the screw naturally drop into the existing thread, then tighten as usual. This avoids cutting new threads each time, which would eventually wear the plastic down.
- Decide where to drill the SMA connector hole.
- The cap end (where the buoy lights up) is ideal — the other end has a hook in the way that needs to be sawed or drilled off to mount the SMA jack there, and you'd also lose one of the points to hang the node from.
- Drill the hole.
- Disconnect the battery, to prevent the RAK3172 from transmitting RF without an antenna attached.
- Disconnect the pigtail from the U.FL socket — pull it straight upwards rather than at an angle, to avoid damaging the U.FL connector.
- Feed the pigtail through the drilled hole and reconnect it to the U.FL socket.
- Mount it loosely.
- If mounting it on the cap, leave it loose enough to spin — the SMA connector can only be tightened once the cap is fully tightened, otherwise the coaxial cable will twist and get ripped off the RAK3172.
- Reconnect the battery.
- Tighten the cap on, being careful to maintain the orientation of the SMA pigtail, and not to crush the pigtail in the threads or accidentally disconnect it from the U.FL socket.
- Only once the cap is fully tightened, tighten the nut of the SMA connector.
- Hold the SMA connector while tightening so it doesn't spin — this can be done with an antenna, gently pulling it so the O-ring engages and prevents the connector from rotating.
Tip
You can generally get the connector quite tight without it spinning — the O-ring on these waterproof SMA connectors helps hold the connector body in position.
| Pin | Name | Use | Notes |
|---|---|---|---|
| 1 | PA3 | USART2_RX* | Firmware update & Meshtastic console (2.54mm header) |
| 2 | PA2 | USART2_TX* | Firmware update & Meshtastic console (2.54mm header, Tag-connect) |
| 3 | PA15 | LED | Green LED |
| 4 | PB6 | — | Unused |
| 5 | PB7 | — | Unused |
| 6 | PA1 | — | Unused |
| 7 | PA13 | SWD (SWDIO) | SWD (Tag-Connect) |
| 8 | PA14 | SWD (SWCLK) | SWD (Tag-Connect) |
| 9 | PA12 | — | I2C SCL for BME280 (DNP) |
| 10 | PA11 | — | I2C SDA for BME280 (DNP) |
| 13 | PA7 | SPI1_MOSI* | Unused |
| 14 | PA6 | SPI1_MISO* | Unused |
| 15 | PA5 | SPI1_CLK* | Unused |
| 16 | PA4 | SPI1_NSS* | Unused |
| 19 | PA8 | — | Unused |
| 20 | PA9 | USART1_TX* | Unused |
| 25 | PA10 | USART1_RX* | Unused |
| 26 | PB2 | BATT_ADC | Battery voltage divider input |
| 27 | PB12 | SPI2_NSS* | 10kΩ pull-up (HF) or pull-down (LF) on module |
| 29 | PA0 | CHRG | TP4057 charge indicator (open-drain, active-low) |
| 30 | PB5 | DONE | TP4057 charge complete (open-drain, active-low) |
| 31 | PB4 | DIVIDER_CTRL | Divider ground enable (output LOW = on, float = off) |
| 32 | PB3 | SOLAR_ADC | Solar voltage divider input |
* Peripheral is used by bootloader so pin should be avoided as GPIO
Two resistor dividers measure battery (PB2) and solar panel (PB3) voltage. PB4 drives the common ground rail of both dividers — floating it between measurements cuts quiescent current to zero.
| Channel | ADC pin | Rtop | Rbottom | Multiplier | Filter cap | Settle |
|---|---|---|---|---|---|---|
| Battery | PB2 | 100kΩ | 200kΩ | 1.5× | 100nF | 34ms |
| Solar | PB3 | 100kΩ | 100kΩ | 2.0× | 100nF | 25ms |
Wait at least 40ms after asserting PB4 before sampling either channel.
Got ideas for improvements, feedback, or run into an issue? Feel free to open an issue and/or raise a PR against this repo.
This project is a sister project to russell, a balloon-borne tracker board.

