ThinkNode M6: give the status LED something to indicate - #3289
Open
andyhoobing wants to merge 2 commits into
Open
ThinkNode M6: give the status LED something to indicate#3289andyhoobing wants to merge 2 commits into
andyhoobing wants to merge 2 commits into
Conversation
The M6 has two LEDs on the bottom face of the enclosure, next to the USB-C port. Only the blue one was driven (LoRa TX activity). The red one -- the enclosure's power LED -- was configured as an output in initVariant() and then never touched again. It now indicates state: solid through boot, a three-flash signature at onBootComplete(), then a low-duty heartbeat -- one blink per 5s while running, two once the GNSS has a fix. That makes a deployed node diagnosable through a sealed case without attaching a laptop. powerOff() clears it too. Blink length is 150ms: 40ms was tried first and is genuinely easy to miss at arm's length in daylight. Duty cycle is still ~3%, which is nothing on a 6W solar panel. The heartbeat is driven from a small EnvironmentSensorManager subclass -- the same pattern thinknode_m1 already uses -- because its loop() already runs every iteration in every example sketch and it is the one place holding the live GNSS state. No core or shared example changes are needed, and the repeater, room server and companion builds all pick it up automatically. Verified: ThinkNode_M6_repeater and ThinkNode_M6_room_server build, and the behaviour was confirmed on real M6 hardware. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7b3E6KcBEGZ2zr2jZMrBL
ThinkNodeM6Board.cpp is one of the few files in the tree that already matches .clang-format exactly, and the lines I added regressed that with double spaces before trailing comments. Reformat just those lines so the file stays clean. The other files this branch touches are left alone deliberately: they are a long way from clang-format clean upstream (ThinkNodeM6Board.h differs by 20 lines before any change of mine), so matching the surrounding style is the right call per CONTRIBUTING.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7b3E6KcBEGZ2zr2jZMrBL
andyhoobing
marked this pull request as ready for review
August 24, 2026 02:35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Split out of #3287 as one self-contained fix, per the one-fix-per-PR guideline.
The companion PR (#3288) covers the M6 GPS defaults and shares no files with
this one — the two are independent and can be reviewed or merged in any order.
Problem
The ThinkNode M6 has two LEDs on the bottom face of the enclosure, next to the
USB-C port. Only the blue one was driven (LoRa TX activity). The red one — the
enclosure's power LED — was configured as an output in
initVariant()and thennever touched again, so half the board's user-visible indication was dead.
Change
The red LED now indicates state:
onBootComplete(),the GNSS has a fix.
powerOff()clears it too. This makes a deployed node diagnosable through asealed outdoor case without attaching a laptop, which is the whole point on a
device with no screen or button.
Blink length is 150ms. I tried 40ms first and it is genuinely easy to miss at
arm's length in daylight. Duty cycle is still ~3%, which is nothing against a
6W solar panel.
Implementation note
The heartbeat is driven from a small
EnvironmentSensorManagersubclass — thesame pattern
thinknode_m1already uses — because itsloop()already runsevery iteration in every example sketch, and it is the one place holding the
live GNSS state.
That means no core changes and no shared example changes: the repeater, room
server and companion builds all pick the behaviour up automatically.
Testing
ThinkNode_M6_repeaterandThinkNode_M6_room_serverboth build againstdev.Confirmed on real ThinkNode M6 hardware: with the GNSS holding a fix (11 sats),
the red LED double-blinks as intended, visually verified by the device owner.
To be precise about what that does and does not cover: the no-fix single-blink
and the boot flash run through the same
updateStatusLed()path and the samegps_fixargument, but were not separately observed — only the fix-acquireddouble blink was.
Authored with assistance from Claude (see
Co-Authored-Bytrailers).