-
Notifications
You must be signed in to change notification settings - Fork 1
WLED and HCR Audio
Two device families a NaviCore button, switch, or knob action can drive: WLED LED controllers and the HCR (Human‑Cyborg Relations) vocalizer. Both share one design — the action carries only the command; the physical destination is a global setting — and both get their wire bytes from the shared WcbCmd library, so a device behaves identically whether NaviCore drives it out a local UART or a WCB drives it off the mesh.
This page covers the WLED routing table, the HCR destination, and the two newest HCR features: non‑blocking audio fades and per‑channel volume. For how you attach these commands to a control, see Action Editor and Command Library; for the full action‑type list, Actions Reference.
For both device families the action holds only what to do:
-
WLED — an
RA_WLEDaction stores a;L<id>,<verb>string. Where WLED id physically lives is a per‑id table (wledSlots) edited in the WLED tab. -
HCR — an
RA_HCRaction stores a numericfn/chan/track. Where the vocalizer physically lives is one global setting (hcrDest) edited in the Audio tab.
The Audio tab holds every sound destination together: the HCR vocalizer, the MP3 Trigger, and the DFPlayer Mini. Each is one setting you make once. For the two sound boards see Actions Reference — and note their volume scales are opposite: an MP3 Trigger runs 0 = loudest … 64 = inaudible, a DFPlayer 0 = silent … 30 = loudest.
The actual device bytes come from the WcbCmd library (currently v0.8.0), compiled by both NaviCore and the WCB firmware. It ships WcbWled, WcbHcr, WcbHcrFade, WcbMaestro, WcbMp3, and WcbDfPlayer. Because the same translator runs on both ends, one saved command produces the exact same bytes at the device whether it went out a NaviCore aux port or rode the ESP‑NOW mesh to a WCB. CI installs the library straight from the greghulette/WcbCmd GitHub repo.
NaviCore holds 4 WLED slots (RC_NUM_WLED = 4) even though ids 1–9 are addressable — one physical controller per id, a few is plenty. Each slot in the WLED tab has:
| Field | Values | Meaning |
|---|---|---|
| ID |
1–9 (0 = unused) |
The id your ;L<id>,VERB actions address |
| Mode | Off / Local port / Remote WCB | How this id is reached |
| Local port |
S3 / S4 / S5
|
A WLED wired to one of this board's aux serial ports |
| Remote WCB |
1–20
|
A WLED hosted on another board; the ;L string is forwarded over ESP‑NOW |
⚠️ Baud caveat. WLED wants 115200 baud, but only S3 (hardware UART0) is reliable that fast. S4/S5 are bit‑bangedSoftwareSerialand should stay ≤ 57600, so a WLED on those ports may be unreliable at high rates. Baud belongs to the port, not the slot — set it in the Baud Rates tab.
WLED actions are authored from the WLED Lighting board in the Command Library — there is no "Send to" picker. The action shows "Routed by WLED id (WLED tab)" because it auto‑routes on the id you set:
| Command | Template | Result | Args |
|---|---|---|---|
| Lights on | ;L<id>,ON |
{"on":true} |
— |
| Lights off | ;L<id>,OFF |
{"on":false} |
— |
| Toggle | ;L<id>,TOGGLE |
{"on":"t"} |
— |
| Set brightness | ;L<id>,BRI,<n> |
{"bri":N} |
n = 0–255 |
| Recall preset | ;L<id>,PS,<n> |
{"ps":N} |
preset # (the primary workflow) |
| Set color | ;L<id>,COL,<hex> |
segment 0 color |
RRGGBB or RRGGBBWW (RGBW) |
| Set effect | ;L<id>,FX,<n>[,<sx>,<ix>] |
{"seg":[{"fx":N…}]} |
index; optional speed sx 0–255, intensity ix 0–255 |
| Set palette | ;L<id>,PAL,<n> |
{"seg":[{"pal":N}]} |
palette index |
| Raw JSON | ;L<id>,JSON,{…} |
passthrough | any /json/state document (escape hatch) |
An unknown verb or bad arguments emit nothing to the WLED.
How the id is read. The id is the digits immediately after L, no comma — ;L3,PS,2 → id 3. A bare ;L,VERB (no id, id 0) means the lowest‑id local WLED on this board. Valid ids are 1–9; an id greater than 9 is rejected and the action is skipped.
At dispatch NaviCore looks the id up in wledSlots and routes it:
-
Local slot (
remoteWCB == 0,serialPort3/4/5) →WcbWled::emit()builds the WLED JSON and writes it newline‑framed out that aux port. -
Remote slot (
remoteWCB1–20) → the full;L<id>,…string is sent to that WCB over ETM, and the host WCB's own router drives its WLED.
A remote WLED needs its id configured in two places: on NaviCore (WLED tab → Remote WCB, so it knows which board to forward to) and on the remote WCB itself (its own
wledConfigs, so it knows the local port). NaviCore forwards the raw string; the remote WCB looks the id up in its table. A bare;L,VERB(id 0) is local‑only — it is not forwardable to a remote WCB.
Every HCR action shares one global destination, hcrDest, chosen in the Audio tab:
-
Serial (local) — pick
S3/S4/S5. NaviCore formats the vocalizer's native bytes and writes them straight to that port. -
WCB (unicast) — pick a WCB ID 1–20. NaviCore sends a
;H,…command over ETM; the receiving WCB drives its own locally wired vocalizer.
The default is Serial / S3. HCR over WCB is unicast only — broadcast is unsupported, and the command rides ETM (retried until ACK'd) because HCR can't tolerate a dropped frame. On the WCB path the serial port is chosen on the receiving WCB via ?HCR,PORT, not here; the legacy wcbPort field is ignored by current firmware.
An HCR action carries a function (fn), a channel (chan — an emotion or an audio channel depending on the fn), and a track/value:
| fn | Function | chan | track / value |
|---|---|---|---|
| 2 | SetEmotion | emotion 0–3 | level 0–99 |
| 3 | Trigger | emotion 0–3 | level 0–99 |
| 4 | Stimulate | emotion 0–3 | level 0–99 |
| 5 | Overload | — | — |
| 6 | Muse (one shot) | — | — |
| 7 | Muse gap | min gap 0–99 s | max gap 0–99 s |
| 8 | Stop (all audio + emote) | — | — |
| 9 | StopEmote | — | — |
| 10 | Override emotions | 0 = off / 1 = on | — |
| 11 | ResetEmotions | — | — |
| 13 | Auto‑muse | — | 0 = off / 1 = on |
| 14 | PlayWAV | audio 0=V / 1=A / 2=B | track 0–9999 |
| 16 | StopWAV | audio 0=V / 1=A / 2=B | — |
| 17 | SetVolume | audio 0=V / 1=A / 2=B / 3 = All | 0–99 |
| 18 | Volume Up | 0 = All / 1=V / 2=A / 3=B | step (0 = default 5) |
| 19 | Volume Down | 0 = All / 1=V / 2=A / 3=B | step (0 = default 5) |
| 12 | Fade In | A (1) / B (2) | seconds (0 = instant) |
| 15 | Fade Out | A (1) / B (2) | seconds (0 = instant) |
Emotion channel (fn 2/3/4): 0 = Happy, 1 = Sad, 2 = Mad, 3 = Scared.
⚠️ Emotion channel 4 (Overload) isn't valid on Trigger/Stimulate — WcbCmd rejectschan 4and the action is silently dropped. Use fn 5 (Overload) instead.
Audio‑channel enums differ by fn. For PlayWAV/StopWAV/SetVolume (fn 14/16/17) it's
0=V, 1=A, 2=B(and3 = Allfor SetVolume). For Volume Up/Down (fn 18/19) the encoding is deliberately offset:0 = All, then V/A/B =1/2/3. Legacy Volume actions carrychan 0meaning All, so don't "fix" one to match the other.
Fades (fn 12 = Fade In, fn 15 = Fade Out) are non‑blocking: NaviCore ramps the volume over time in the background instead of blocking loop(). They are handled by the shared HcrFade ramp, not by the normal HCR codec.
- Channels A or B only — the Vocalizer channel V is never faded (matching the WCB).
-
track= duration in seconds.0seconds is an instant jump, not a fade. -
Fade In ramps
0 → the channel's current volume. Fade Out rampscurrent → 0, then issues StopWAV and restores the pre‑fade level. - The ramp is 150 ms per step, linear interpolation. Every step writes through a
SetVolume, so the volume shadow stays authoritative.
Local vs mesh. A local fade is advanced by loop() and runs only while the HCR destination is a local serial port. If the destination is a WCB (or you move it to a WCB mid‑fade, or the local port becomes unresolvable), the in‑flight local ramp is cancelled rather than frozen. Over WCB, NaviCore instead sends ;H,FADEIN|FADEOUT,<A|B>,<sec> and that WCB runs its own fade.
-
SetVolume (fn 17) sets an absolute level
0–99onV,A,B, or All. -
Volume Up / Down (fn 18/19) nudge relative by
step(blank or0= default 5), clamped0–99. Withchan 0 = Allthey step V+A+B together; withchan 1/2/3NaviCore reads the shadow for that one channel, adds the step, clamps, and emits a single absolute SetVolume.
No volume readback. HCR has no way to report its current volume, so relative steps and Fade In's start level rely on a per‑channel shadow that seeds to 50 and becomes exact only after the first SetVolume on that transport. A relative nudge right after boot assumes 50.
A manual audio command (PlayWAV/StopWAV/SetVolume/Volume Up/Down) cancels any in‑flight fade on the channel(s) it touches — otherwise the next fade tick would overwrite your manual change.
HCR actions use a legacy editor: a Function dropdown plus per‑fn widgets built for each function.
-
Fade In / Fade Out shows an Audio chan select (A / B) and a Seconds number. A new fade action defaults to 2 s, but a stored
0is preserved (a0is an intentional instant jump). - Volume Up / Down shows a 4‑option Audio chan select (All / V / A / B) and Step (0 = 5).
This editor is kept for backward compatibility; new HCR (and MP3) actions are meant to be authored from the Command Library (the vendored DroidNet board). WLED actions are already command‑library only.
Debugging. The debug console has dedicated WLED and HCR chips that surface the [DISPATCH] WLED… / [DISPATCH] HCR… routing lines — including skip reasons like not configured, WCB not ready, or fade chan must be A/B.
- Only 4 WLED controllers can be configured at once, even though ids 1–9 are addressable.
- A remote WLED must have its id set in two places (NaviCore's WLED tab and the remote WCB's own config).
- A bare
;L,VERB(id 0) only drives a local WLED — it can't be forwarded to a remote WCB. - WLED at 115200 is reliable only on S3; S4/S5 (
SoftwareSerial) should stay ≤ 57600. - HCR fades touch A and B only; the Vocalizer channel V is never faded. Fade seconds = 0 = instant, not a fade.
- A local HCR fade only runs on a local serial destination; a WCB destination (or moving to one mid‑fade) cancels the local ramp — the remote WCB runs its own.
- The fn 18/19 volume‑channel encoding (
0 = All) deliberately differs from the fn 14/16/17 audio enum (0 = V, 3 = All). - HCR has no volume readback — the shadow seeds to 50 and is only exact after the first SetVolume.
- HCR over WCB is unicast only; the receiving WCB routes it to its own port, set via
?HCR,PORT. - HCR is fire‑and‑forget: query/poll functions are intentionally not implemented, and NaviCore formats the bytes itself via WcbCmd rather than using the HCRVocalizer library.
-
WcbCmd is a shared library compiled by both NaviCore and the WCB, and it exists as two physical copies. If the versions drift, the same command can emit different device bytes; CI floats the GitHub version (currently
0.7.0).
See also: Actions Reference · Action Editor and Command Library · Config Tool Guide · WCB Network
NaviCore — Astromech Animation Controller · Home · WCB v3.2 / ESP32‑S3
Setup
- Setup Guide — start here
- PCB Assembly and BOM
- Hardware and Wiring
- Flashing the Firmware
- Transmitter Setup
- Connecting
- Config Tool Guide
- Maestro Setup
Reference
- Action Editor and Command Library
- Actions Reference
- WLED and HCR Audio
- Record and Replay
- Cheat Sheet
- Configuration Schema
- WCB Network
- Remote Management over WCB
- Serial JSON Protocol
- CLI Commands
- Failsafe and Signal Loss
- Glossary
Help