Skip to content

Test: Charlieplexing (104 LEDs from 11 pins)

Charlieplexing

Charlieplexing: 104 LEDs from 11 pins

charlieplex-led-matrix · STM32U585 gpiof 0–10 · 13 × 8 · 3-bit grey · 100 Hz refresh · vanilla Zephyr on the Arduino UNO Q

This is the payoff, so it is where the demo opens. The walkthrough that explains it starts at .

Eleven phases per frame. In each phase one pin sources and up to ten pins sink, so up to ten LEDs light at once. Slow it down to watch the phases step; run it at 1× and persistence of vision does the rest. The default image is the comet from main.c: a full-brightness head on the two centre rows and a tail that fades one duty level per 60 ms frame.

HPF0
ZPF1
ZPF2
ZPF3
ZPF4
ZPF5
ZPF6
ZPF7
ZPF8
ZPF9
ZPF10
Pin states are what the MCU is actually doing at the instant shown.
frame time0 µs
phase0 · PF0 high
grey tick1 / 7 (bit 0)
LEDs on now0
in this phase10 addressable
frames elapsed0
/* one 60 ms frame of main.c */
for (i = 0; i < 104; i++)
    if (fb[i] > 0) fb[i]--;  /* fade one level */
fb[3 * 13 + x] = 7;          /* head, two rows */
fb[4 * 13 + x] = 7;
x += dir;
if (x == 12 || x == 0) dir = -dir;

fb is display_get_framebuffer(): 104 bytes, row-major, in exactly the order of pixel-pairs. The tail is six cells long because the fade is one level per frame and grayscale-bits = 3 only has seven non-zero levels to give away.

The two head pixels look like one bright bar, but they are two unrelated pin pairs: at twelve of the thirteen columns they fall in different scan phases, so the head is never drawn in one go. Row 3 alone spans eight of the eleven phases.

Brightness here is integrated over real time with a ~55 ms eye response, then given 11× exposure gain, the same trick the hardware plays, driving each LED hard for 1/11 of the time. At 1 : 200 you are seeing individual grey ticks; the picture looks wrong because your eye is no longer doing the averaging.

Every value on this page is read from the board’s own devicetree.