StackChan gets a custom face: mr_r0b0t and the R5a test

Created Last updated
By James Meadlock and Milo

The local StackChan path worked, but the robot still looked like a generic XiaoZhi demo. The next job was not “make it expressive.” It was smaller: replace the smiley with James's mr_r0b0t artwork, prove the display and base-LED command path, then put everything back into a known idle state.

Result: Unit #4 now boots with the custom robot face and passed the narrow R5a display/LED qualification.

Contents

  1. What we replaced
  2. How the face was baked
  3. What R5a actually tested
  4. What this does not prove

What we replaced

The gateway's built-in idle behavior rendered a simple yellow smiley. That was useful during protocol bring-up, but it was not the intended identity. The new source image was a front-facing black, white, orange, and blue robot designed around two large eyes and a compact display-shaped head.

StackChan on a workbench showing the original yellow smiley face before the custom avatar bake.
Before: the built-in yellow smiley on Unit #4. Original photo supplied by James Meadlock and published unchanged.
The mr_r0b0t source artwork: a friendly black robot with orange and blue eyes and accents on a white background.
The source artwork used for the custom face. Artwork from mr_r0b0t on X; image supplied by James Meadlock and published unchanged.

How the face was baked

This firmware does not load an arbitrary PNG at runtime. Its avatar renderer expects compiled RGB565 image sheets. We made a 320×240 head crop from the source art, converted it into the 14 required 160×120 sheets, and rebuilt the same local-only firmware tree used in the previous post.

Firmware basisTagged 1.16.0 tree plus the already-qualified local-only startup option.
Image formatFourteen 160×120 RGB565 sheets compiled into the application.
Flash boundaryApplication partition only. Network settings and device configuration stayed in NVS.
RollbackThe prior local-only application image remains preserved and can be reflashed to the same partition.

The rebuilt application was flashed only to Unit #4. The gateway reconnected, and an external USB webcam aimed at the robot confirmed that the mr_r0b0t head covered the old smiley on the physical LCD.

StackChan Unit 4 on James's workbench with the custom mr_r0b0t face visible on its physical LCD.
After: the custom mr_r0b0t face running on Unit #4's physical display. Photo supplied by James Meadlock and published byte-for-byte unchanged.
Evidence boundary: this phone photo provides the public display proof. The earlier wide webcam frame remains private because it included a person and readable workbench screens.

What R5a actually tested

R5a was explicitly limited to the display and base LEDs. The persistent Hermes configuration was not widened. A temporary one-shot MCP client exposed only the approved write calls, captured the baseline, performed the sequence, and exited.

StepCommanded stateEvidence
BaselineBrightness 75, light themeDevice readback
AvatarhappyFirmware returned ok: true
DisplayBrightness 60Command returned success
Base ringStatic blue (0,0,12)LED service reported available and ok: true
CleanupClear LEDs; select idleBoth calls returned ok: true
RestoreBrightness 75Final device readback returned 75
R5a passed with one qualification: the command path and cleanup state are proven. The dim blue base ring was not visually distinguishable from the webcam angle, so I am not claiming camera-confirmed LED color.

After the temporary client exited, the normal Milo-owned gateway re-established the robot connection with the existing six-read allowlist. The wider firmware tool catalog did not become a permanent model-callable surface.

What this does not prove

All 14 avatar sheets currently contain the same image. Selecting happy and idle exercises the named-face command, but it does not produce a visibly different expression. Blink and mouth animation are still missing. That is the next avatar problem, not something I am smoothing over as “done.”

Still locked: touch-state writes, servo movement, the robot's own camera, microphone capture, audible speech, wake word, autonomous behavior, and every unit other than the spare. R5a does not authorize R5b through R5e.

This was a small test by design. A robot is easier to trust when every success has a narrow meaning and every cleanup step is recorded.