From c969b2fca3a08eeb2bc5a07f5f6e87f5b3f9ac59 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Thu, 10 Sep 2026 22:40:15 +0200 Subject: [PATCH] promicro fixes --- releasenotes/RELEASE_NOTES_1.17.5-zephcore.md | 104 ++++++++---------- .../nrf52840/promicro_sx1262/board.conf | 67 ++++++++--- .../promicro_sx1262/promicro_sx1262.dts | 23 +++- 3 files changed, 120 insertions(+), 74 deletions(-) diff --git a/releasenotes/RELEASE_NOTES_1.17.5-zephcore.md b/releasenotes/RELEASE_NOTES_1.17.5-zephcore.md index 46d1426..d78a305 100644 --- a/releasenotes/RELEASE_NOTES_1.17.5-zephcore.md +++ b/releasenotes/RELEASE_NOTES_1.17.5-zephcore.md @@ -1,65 +1,41 @@ # ZephCore 1.17.5-zephcore > [!NOTE] -> **Draft — release in progress.** Covers what is on `dev` so far. More entries will land before this ships. - -A Bluetooth range fix that affects every ESP32 board, GPS support on the two Heltec V4 boards, and the -single-button confirmation prompt now works on the eight boards where it never could. +> **Draft — release in progress.** Covers what is on `dev` so far. --- ## Bluetooth range on ESP32 boards was 9 dB down -Every ESP32 board — S3, C-series and classic alike — has been advertising and connecting at 0 dBm. -Stock Arduino MeshCore runs the same radios at +9 dBm. That is the reported "ZephCore has worse -Bluetooth range than the official firmware" on Heltec V4, and the gap is real: 9 dB is roughly 2.8 -times the distance in free space. - -Nothing was misconfigured. The setting was deliberately left alone, on the understanding that the -Espressif controller blob picked its own transmit power. It does not. Zephyr's driver hands the -controller a default built from a chain of `CONFIG_BT_CTLR_TX_PWR_*` options, and with none of them -set the chain fell through to its `use 0dB TX power as default` arm. Silently, with no warning at -build time and nothing visible on the node. - -ESP32 boards now transmit at +9 dBm, matching stock MeshCore. That is comfortably inside the EU -2.4 GHz 100 mW limit, and it is the one level every Espressif chip family in the tree supports, so it -applies everywhere without per-board overrides. +Every ESP32 board has been advertising and connecting at 0 dBm; stock MeshCore runs the same radios +at +9 dBm. Zephyr's driver builds its default from the `CONFIG_BT_CTLR_TX_PWR_*` chain, and with none +of them set it fell through to the 0 dB arm — silently, with nothing visible at build time or on the +node. ESP32 boards now transmit at +9 dBm. > [!NOTE] -> **Nothing to change on your side.** No setting, no re-pairing. Flash and the range is there. -> nRF52, nRF54L and MG24 boards were never affected — they set their own transmit power already. +> **Nothing to change on your side.** No setting, no re-pairing. nRF52, nRF54L and MG24 were never +> affected — they set their own transmit power. --- ## GPS on Heltec WiFi LoRa 32 V4 and V4.3 -Both boards bring a GPS UART and its power-control pins out to the header, and ZephCore had no -wiring for either. Attaching a module did nothing. - -They are now described the same way every other GPS board is: NMEA on UART1 at 9600 baud, with the -enable and reset lines driven properly rather than left floating into the module. `set gps on` and -the GPS pages behave as they do elsewhere. +Both boards bring a GPS UART and its power pins out to the header, and ZephCore described neither, so +attaching a module did nothing. They now match every other GPS board: NMEA on UART1 at 9600 baud, with +enable and reset driven rather than left floating. > [!NOTE] -> **This is for an external module.** Neither board ships with a GPS receiver — the pins are there for -> one you add yourself. Boards with nothing attached are unaffected. +> **For an external module.** Neither board ships with a receiver; boards with nothing attached are +> unaffected. --- ## The confirmation prompt now works on single-button boards -Shutdown, DFU and off-grid all ask you to confirm by pressing ENTER twice. On boards with one button, -ENTER is not a tap — it is a one-second hold, produced by a long-press filter. - -Two one-second holds cannot fit inside a half-second window, and half a second is what the window -was. The second hold always arrived after it had closed, so instead of confirming, it re-armed the -prompt. Pressing again did the same thing. On these boards the three actions simply could not be -confirmed from the screen, however many times you tried. - -The window is now three seconds on every board that emits ENTER through a long-press filter, which is -what the setting's own documentation had been recommending all along. Six boards had it; eight did not. - -Newly fixed: +Shutdown, DFU and off-grid confirm with two ENTER presses. On single-button boards ENTER is a +one-second hold, and the window was half a second — so the second hold always landed too late and +re-armed the prompt instead of confirming. The window is now three seconds on every board that emits +ENTER through a long-press filter. Six had it; eight did not: | | | |---|---| @@ -68,9 +44,7 @@ Newly fixed: | Heltec WiFi LoRa 32 V4.3 | LilyGo T3-S3 | | Meshnology W12 | TTGO T-Beam | -> [!NOTE] -> **Boards with a joystick were never affected.** The Wio Tracker L1 and GAT562 use a different menu, -> which has always allowed three seconds. Nothing changes for them. +Joystick boards (Wio Tracker L1, GAT562) use a different menu and were never affected. Thanks to **bisbille** for finding this and fixing the first two boards. @@ -78,28 +52,42 @@ Thanks to **bisbille** for finding this and fixing the first two boards. ## Changing frequency or spreading factor now resets adaptive CAD -Adaptive CAD learns a listen-before-talk threshold as an offset from a base value the chip family -publishes per spreading factor and per bandwidth. Change SF or bandwidth and that base moves under -the offset — but the node kept the old offset and, at the next boot, shifted it further to preserve -the absolute threshold it used to name. Correct after a firmware table change, wrong after a preset -change, where the base table's own step is the physics. On an LR1110 the SF7-to-SF12 step alone is -16 counts, enough to slam the offset to its rail: too sensitive and the node defers transmitting on -noise, or too deaf and it transmits over live receptions. - -`set radio`, `set freq` and the app's radio settings now perform a full `set cad.reset` whenever they -move frequency, bandwidth or spreading factor — the learned offset and the probe statistics behind it -both belong to the preset you just left. Coding rate is excluded; it changes airtime, not the -threshold. `tempradio` visits its preset at that preset's own base and hands the learned offset back -on revert, without ever writing it to flash; `get cad` shows `a:tmp` while a window is open. +The learned CAD threshold is an offset from a per-SF, per-bandwidth base. Change the preset and the +base moves, but the node kept the old offset — leaving it too sensitive to transmit or too deaf to +defer. `set radio`, `set freq` and the app's radio settings now perform a full `set cad.reset` when +frequency, bandwidth or spreading factor changes. Coding rate is excluded: it changes airtime, not the +threshold. `tempradio` uses its preset's own base and hands the offset back on revert without writing +flash; `get cad` shows `a:tmp` while a window is open. > [!NOTE] -> **Nothing to change on your side.** The reset is automatic, and the node re-converges in an hour or -> two. Reaching for `set cad.reset` by hand after a preset change is no longer necessary. +> **Nothing to change on your side.** The reset is automatic and the node re-converges in an hour or +> two. `set cad.reset` by hand is no longer needed after a preset change. Thanks to **Codes** for reporting it. --- +## ProMicro SX1262: Bluetooth dropped every few seconds, and the screen never worked + +The nRF52840 SuperMini has no 32.768 kHz crystal, but the board was configured as though it did — so +the Bluetooth controller and the kernel tick ran off a floating oscillator while claiming 50 ppm +accuracy, and the link dropped every few seconds. It now uses the calibrated internal RC at 250 ppm, +matching stock MeshCore's settings for the same silicon. Timing that hangs off the same clock steadies +with it, including the return to receive after a transmission — so repeats of your own message, and +zero-hop ping replies, are no longer missed. + +The OLED was never described for this board at all. It is now an SSD1306 on the same I2C pins stock +MeshCore uses, optional at runtime. + +> [!NOTE] +> **Check transmit power if your module has no amplifier.** The 10 dBm default is the safe drive level +> for an E22-900M30S. On a bare module (HT-RA62, E22-900M22S) that is your antenna power — 12 dB under +> stock — which reads as no repeats and failed zero-hop pings. `set tx 22` once and it sticks. + +Thanks to **Mike's Allotment** for the report. + +--- + ## Also in this release *To be filled in as further changes land.* diff --git a/zephcore/boards/nrf52840/promicro_sx1262/board.conf b/zephcore/boards/nrf52840/promicro_sx1262/board.conf index f453a90..5af5c5a 100644 --- a/zephcore/boards/nrf52840/promicro_sx1262/board.conf +++ b/zephcore/boards/nrf52840/promicro_sx1262/board.conf @@ -1,14 +1,53 @@ -# ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S -# SoftDevice v6 (S140 v6) — NiceNano/SuperMini bootloader uses S140 6.1.1 -# 0x00B6 = S140 v6 firmware ID; app partition starts at 0x26000 - -CONFIG_ZEPHCORE_BOARD_NAME="ProMicro SX1262" -CONFIG_BT_DIS_MODEL_NUMBER_STR="ProMicro SX1262 nRF52840-SX1262" -CONFIG_ZEPHCORE_SD_FWID=0x00B6 - -# Native Zephyr SX1262 driver (Ebyte E22-900M30S) -CONFIG_ZEPHCORE_RADIO_NATIVE=y - -# E22-900M30S has 30dB external PA — default SX1262 output at 10 dBm -# to avoid PA damage on TX. Not capped — user can raise at their own risk. -CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10 +# ProMicro SX1262 — nRF52840 SuperMini + an SX1262 module +# Generic target: built both with the Ebyte E22-900M30S (30 dB PA) and with +# bare no-PA modules (HT-RA62, E22-900M22S). See the TX power note below. +# SoftDevice v6 (S140 v6) — NiceNano/SuperMini bootloader uses S140 6.1.1 +# 0x00B6 = S140 v6 firmware ID; app partition starts at 0x26000 + +CONFIG_ZEPHCORE_BOARD_NAME="ProMicro SX1262" +CONFIG_BT_DIS_MODEL_NUMBER_STR="ProMicro SX1262 nRF52840-SX1262" +CONFIG_ZEPHCORE_SD_FWID=0x00B6 + +# Native Zephyr SX1262 driver +CONFIG_ZEPHCORE_RADIO_NATIVE=y + +# TX power defaults to the SAFE value for the E22-900M30S, whose 30 dB external +# PA is damaged by a hot drive: 10 dBm in, ~30 dBm at the antenna. +# +# This target is also built with bare SX1262 modules that have no PA at all +# (HT-RA62, E22-900M22S). On those, 10 dBm IS the antenna power — 12 dB below +# the 22 dBm official MeshCore ships for the same variant (LORA_TX_POWER=22 in +# variants/promicro/platformio.ini). The symptom is a node close neighbours can +# still hear, that gets zero repeats and fails 0-hop pings to repeaters. +# +# The default stays conservative because the failure modes are not symmetric: +# too little power costs range and is fixable in the app, too much destroys a +# PA permanently. With no external PA, use "set tx 22" after the first flash — +# this is a first-boot pref only, so the new value sticks. +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10 + +# 32.768 kHz source: calibrated RC, not a crystal. +# The nRF52840 SuperMini/ProMicro clones do not fit an LFXO — official MeshCore +# says so outright in variants/promicro/variant.h ("//#define USE_LFXO" / +# "#define USE_LFRC"). Zephyr's default is CLOCK_CONTROL_NRF_K32SRC_XTAL with a +# 50 ppm accuracy claim, so without this the node runs the BLE controller and +# RTC1 (the kernel tick source) off a floating LFXO while telling the peer it is +# 50 ppm accurate: the central's receive windows stop landing on our anchor +# points and the link drops every few seconds, and every k_timer — including the +# LoRa RX duty-cycle windows and the post-TX RX restore — skews with it. +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y + +# Accuracy claimed to the BLE peer. Zephyr would pick 500 ppm here (its default +# for RC on nRF52); the Adafruit core that stock MeshCore builds on declares +# NRF_CLOCK_LF_ACCURACY_250_PPM for the same calibrated RC on the same silicon +# (libraries/Bluefruit52Lib/src/bluefruit.cpp, alongside rc_ctiv=16 / +# rc_temp_ctiv=2 — what RC_CALIBRATION above provides). Matched to stock so the +# central sizes its receive windows the same way on both firmwares. +CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y + +# Compile in the UI display stack; the OLED panel is optional at runtime. +# SSD1306 on i2c0 (SDA P1.04 / SCL P0.11) — the same bus and pins official +# MeshCore drives via PIN_BOARD_SDA=8 / PIN_BOARD_SCL=7, and it builds every +# ProMicro env with DISPLAY_CLASS=SSD1306Display. +CONFIG_ZEPHCORE_UI_DISPLAY=y diff --git a/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts index faf030d..31501ee 100644 --- a/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts +++ b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts @@ -1,15 +1,18 @@ /* - * ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S + * ProMicro SX1262 — nRF52840 SuperMini + SX1262 (generic; see board.conf) * Copyright (c) 2025 ZephCore * * SPDX-License-Identifier: MIT * * Hardware: * - nRF52840 (SuperMini/ProMicro form factor) with BLE 5 - * - Ebyte E22-900M30S (SX1262 + 30dB PA), TCXO, DIO2=TXEN, RXEN on P0.17 + * - SX1262 module: E22-900M30S (30dB PA) or a bare HT-RA62 / E22-900M22S; + * TCXO, DIO2=TXEN, RXEN on P0.17. TX power differs — see board.conf * - GPS module on UART0 (9600 baud, P0.22 RX, P0.20 TX) * - Battery ADC on AIN7 (P0.31), 150K+150K divider (2:1) * - User button on P1.00, LED on P0.15 + * - Optional SSD1306 128x64 OLED on I2C0 @ 0x3c (SDA P1.04, SCL P0.11) + * - No 32.768 kHz crystal fitted — see the K32SRC_RC note in board.conf * - 3V3 enable on P0.13 (must be HIGH for SX1262 to function) */ @@ -30,6 +33,7 @@ zephyr,code-partition = &code_partition; zephyr,console = &cdc_acm_uart; zephyr,shell-uart = &cdc_acm_uart; + zephyr,display = &ssd1306; }; aliases { @@ -170,6 +174,21 @@ pinctrl-1 = <&i2c0_sleep>; pinctrl-names = "default", "sleep"; + /* SSD1306 OLED — optional; absent panels fail device_is_ready() and are skipped */ + ssd1306: ssd1306@3c { + compatible = "solomon,ssd1306"; + reg = <0x3c>; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + segment-remap; + com-invdir; + prechargep = <0x22>; + }; + /* All supported environment & power sensors — auto-detected at runtime */ #include "../../common/sensors-i2c.dtsi" };