ZephCore
CustomA ground-up port of MeshCore from Arduino to the Zephyr RTOS. Replaces the Arduino loop with Zephyr's event-driven primitives so the CPU sleeps between events, while aiming for full protocol compatibility with stock MeshCore firmware and the MeshCore mobile apps.
Reimplementation of MeshCore (Official)
- Maintainer
- liquidraver ↗
- Status
- active
- Maturity
- beta
- Lifecycle
- active
- Latest version
- 20260619.094253
- Released
- 2026-06-19
- Runtime
- Zephyr · C++
- Distribution
- community
- License
- MIT
Capabilities
Transports
- ✓ BLE
- ✓ USB serial
- ✓ Native TCP
- ✓ Wi-Fi AP
Operations
- ✕ Web flasher
- ✓ OTA updates
- ✓ BLE DFU
Networking
- ✓ Repeater
- ✓ Room server
- ✓ Observer
- ✓ MQTT
- ✕ KISS modem
Hardware
- ✓ GPS
- ✓ Display
- ✓ Sensors
- ✓ Low-power RX
Protocol
- ✓ MeshCore compatible
- ✓ Raw packet send
- ✓ Raw packet observe
Node roles
Features
- Zephyr RTOS event-driven architecture
- CAD-based RX power saving
- Adaptive contention window
- Adaptive Power Control
- DFU / OTA update support
- Listen-only observer (WiFi + MQTT)
- Protocol-compatible with MeshCore apps
Releases
from GitHub · updated 2026-06-21v20260619.094253 # Latest 2 days ago · 2026-06-19 09:43 UTC
ZephCore v1.16.3-zephyr
(re-re-re-release(last time I swear) with the "smearing fix on eink after the full update" and "automount error on a freshly formatted node")
[!IMPORTANT]
Before you upgrade
Updating from v1.16.2 — clean flash, no re-bond required, bonds survive.
Updating from v1.16.1 or older — flash the firmware; the firmware detects the old installation on first boot and clears the BLE bond storage automatically. Your identity, contacts, channels, and prefs are preserved. You will need to re-bond your phone/desktop once (old pairings were stored in a different location that v1.16.2 moved away from). No formatter tool required.
Coming from Arduino MeshCore — flash the firmware; it detects the incompatible filesystem on first boot and formats automatically. Everything starts fresh (new identity, clean storage). No formatter tool required.
Take this with a grain of salt tho… try the formatters if anything anomalous happens with your node.
This is a GPS-focused release: it stops a battery-killing bug on GPS trackers, puts the GPS duty cycle under your control, and follows up the v1.16.2 ESP32 pairing work with a fix for recent Android phones.
Highlights
Fixed: ThinkNode M1 draining its battery in a day
On the ThinkNode M1, the GPS module was never actually powered down between fixes — the reset line was mislabeled in the board definition and held permanently released, so the receiver kept drawing current even when the firmware thought it was asleep. A full battery could disappear in roughly a day with GPS enabled.
The M1 now asserts the GPS hardware reset on standby, so the GPS genuinely stops between fixes. If you run an M1 with GPS on, this is the fix you want.
New: configurable GPS duty cycle —
set gps duty <seconds>You can now decide how your node handles GPS, instead of it being baked in:
set gps duty <seconds>— how long the GPS sleeps between fixes. Persists to flash and applies immediately.set gps duty 0— always-on: the GPS never sleeps. It streams fresh fixes (so telemetry is always current) and stays on long enough to download a full almanac.set gps duty default— reset to the role default.get gps duty— show the now-effective interval.
This unifies repeaters and companions behind one knob. Repeaters default to 48 h (GPS wakes only for periodic time-sync) and companions to 5 minutes — both now adjustable. Existing repeaters are migrated automatically; nothing to do.
Bad input is rejected with a usage hint, and the value is clamped to a sane range (10 s … 1 week, or 0 for always-on).
Fixed: GPS no longer pins itself on waiting for a first fix
Previously, after enabling GPS a companion would keep the receiver powered indefinitely until it got its first fix — so a node left somewhere without sky view (indoors, in a bag) could quietly drain its battery forever. The first cold-start acquisition is now bounded (5 minutes by default, enough for a genuine cold start), after which the node drops into its normal duty cycle whether or not it got a fix.
Fixed: ESP32 Secure Connections pairing (Pixel 7 / recent Android)
Following the v1.16.2 ESP32 pairing fix, SC-capable centrals — notably recent Android phones like the Pixel 7 — still failed to bond: the controller's encryption table was left uninitialized because the relevant code was guarded on an ESP-IDF symbol that never exists in a Zephyr build, so the link dropped with a MIC failure at encryption start. The guard is corrected (carried as a managed
hal_espressifpatch), and SC pairing now completes. Legacy-pairing devices were unaffected and continue to work. Thanks @seagull9000.Other fixes and improvements
- Fixed: GPS always-on on a freshly flashed companion — a new install would default
gps_intervalto 0 (always-on) instead of the intended 5-minute duty cycle, causing the …
v20260616.202853 # 5 days ago · 2026-06-16 20:29 UTC
ZephCore v1.16.2-zephyr
[!IMPORTANT]
Before you upgrade — please read
This release changes where devices store their BLE pairing data. The change affects all platforms, but the upgrade steps differ:
All boards (nRF52 and ESP32): you must re-bond. Existing phone/desktop pairings will not carry over. After flashing, remove the old pairing from your device's Bluetooth settings (and from the ZephCore app), then pair again from scratch.
nRF should update cleanly, but I recommend doing a flash erase + flash fw + import backup to be absolutely sure. Formatters can be found in the repo's formatter folder. Check your softdevice version before using one.
Highlights
Critical fix: ESP32 Bluetooth pairing restored
On the updated Zephyr 4.4.1 base, ESP32 boards could advertise but never completed pairing — the Espressif Bluetooth controller would assert the moment a phone began to pair. This release restores the controller's link-layer encryption so pairing works again. If you have an ESP32-based node (Heltec, XIAO, Station G2, T-Beam, etc.), this is the fix you've been waiting for.
Additionally, Android "connect from app" now works on ESP32. Advertising now always exposes the stable identity address, so the Android companion app's in-app connect flow succeeds while iOS pairing continues to work.
BLE pairing data moved to its own storage area
Bluetooth bonds previously shared the same filesystem as your identity, preferences, and contacts. They now live in a dedicated, isolated storage partition (NVS) on both nRF52 and ESP32. This means a busy pairing store can no longer corrupt your contacts or settings, and pairing writes never touch your user data.
A factory reset (
erase) now also clears stored BLE bonds, then reboots automatically so everything comes back up clean — previously bonds could survive an erase.New board: Heltec Wireless Tracker V1.1 (ESP32-S3 + SX1262), thanks to @seagull9000
Full support for the Heltec Wireless Tracker V1.1 companion (ESP32-S3 + SX1262 radio + ST7735R TFT + UC6580 GPS), including:
- Correct battery ADC routing (avoids a wiring conflict in the upstream board definition that otherwise broke all LoRa SPI reads)
- Battery voltage/percentage readings
- Onboard GNSS
- Status-LED heartbeat
- OLED/TFT display and BLE companion transport
New board: LilyGo T-Beam v1.2 (SX1262)
Full support for the classic-ESP32 LilyGo T-Beam v1.2 with the SX1262 radio, including:
- AXP2101 power management (LoRa + GPS rails brought up automatically at boot)
- Battery fuel-gauge readings over I2C — accurate battery voltage and percentage, even though this board has no battery ADC
- Onboard GNSS (NEO-6M / NEO-M8N)
- The user button wired up (short press = page/select, long press = action)
- OLED display, BLE companion transport, and CLI-based repeater mode
Note: classic-ESP32 repeaters (e.g. T-Beam) run CLI-only and do not include WiFi-AP OTA — the WiFi driver buffers plus OTA heap don't fit the classic ESP32's RAM. ESP32-S3 / C-series repeaters keep WiFi OTA.
E-paper anti-ghosting
E-paper displays now perform a periodic full refresh (every 8 partial updates by default) to clear the faint "ghost" images that build up where text changes most often, like the status bar. The interval is configurable build-time, and the feature is automatically ignored on OLED/TFT screens that don't ghost.
More reliable companion connection (Linux / native transport)
The native TCP transport now applies the same congestion control already used over Bluetooth. Instead of silently dropping data when the connection is briefly saturated (for example, an incoming message arriving during a large contact/channel import), it now back-pressures and retries, and important protocol responses are never dropped. A stalled peer that stops reading is cleanly dis …
v20260613.205222 # 8 days ago · 2026-06-13 20:52 UTC
DO NOT DOWNLOAD THIS RELEASE JUST TO UPDATE, YOU NEED A FLASH ERASE FOR IT TO WORK PROPERLY. I'LL RE-RELEASE IT SOON AS I CATCH THE BUG! (it seems devices with multiple bondings are affected only)
So if something is broken: delete bond, erase flash and try again.
What's New
- RX duty cycle (power saving) reworked — now properly tested against the datasheet, gives ~40-55% radio-off time with no packet loss on up-to-date nodes. Toggle with
set rxduty on/off. (Mixed old/new meshes: keep it off on infra nodes for now. Needs preamble 32 on adjacent nodes) - Joystick UI now shows accented characters (Hungarian/Slovak/Czech/Polish/etc. names display correctly), emojis are stripped instead of showing garbage. Unlock gesture changed to Left -> OK -> Right (easier/faster than the old Back-OK-Back).
set rxduty/set radio.rxgainnow also accepton/off, not just1/0.
Fixes
- WisMesh Tag battery percentage was reading high — calibration corrected.
- RTC clock could get permanently stuck blank after battery loss — now recovers and re-syncs.
- Clock source indicator (GPS/App/Local) and display now update correctly/immediately.
- Auto-shutdown no longer triggers on a brief voltage dip during transmit (needs 3 low readings in a row now).
- Fixed a race in MQTT "online" status reporting on repeaters/observers.
- Several small crash/overflow hardening fixes from ongoing code audit (no user-visible behavior change).
- RX duty cycle (power saving) reworked — now properly tested against the datasheet, gives ~40-55% radio-off time with no packet loss on up-to-date nodes. Toggle with
Device compatibility (30)
| Device | MCU | Radio | Status | Notes |
|---|---|---|---|---|
| RAK WisBlock / WisMesh (RAK 4631) | nrf52840 | Semtech SX1262 | ✓ Supported | |
| μArt.cz Solar Node Station | nrf52840 | Semtech SX1262 | ✓ Supported | |
| LilyGo T-Echo | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Wio Tracker L1 | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Wio Tracker L1 Pro | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Heltec V3 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Heltec WSL3 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Heltec V4 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Heltec V4 + Expansion Kit (Touch) | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Heltec T114 | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Heltec Wireless Tracker v3 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| LilyGo T-Beam (SX1262) | esp32 | Semtech SX1262 | ✓ Supported | |
| LilyGo T-LoRa C6 | esp32-c6 | Semtech SX1262 | ✓ Supported | |
| RAK WisMesh 1W Booster (3401 + 13302) | nrf52 | Semtech SX1262 | ✓ Supported | |
| RAK WisMesh Tag | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio SenseCAP Solar Node P1 | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio SenseCAP Solar Node P1-Pro | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio SenseCAP T1000-E | nrf52840 | Semtech LR1110 | ✓ Supported | |
| UnitEng Station G2 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Elecrow ThinkNode M1 | nrf52840 | Semtech SX1262 | ✓ Supported | |
| Elecrow ThinkNode M3 | nrf52840 | Semtech LR1110 | ✓ Supported | |
| Elecrow ThinkNode M6 | nrf52840 | Semtech SX1262 | ✓ Supported | |
| ProMicro nrf52 (faketec) | nrf52 | Unknown | ✓ Supported | |
| GAT-IoT GAT562 30s | nrf52 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Xiao C3 | esp32-c3 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Xiao C6 | esp32-c6 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Xiao S3 WIO | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio XIAO ESP32S3 | esp32-s3 | Semtech SX1262 | ✓ Supported | |
| Seeed Studio Xiao nRF52 WIO | nrf52840 | Unknown | ✓ Supported | |
| Nordic nRF54L15 DK | nrf54l15 | Unknown | ◑ Partial | Early bring-up; not all peripherals wired. |