Files
Flipdot-display/src/nano/README.md
T
mangavalkandClaude Opus 5.5 683a47c055 Restructure ESP32 firmware into modules, fix bugs, add tests
Structure (src/esp32/):
- logic/: DisplayController, schedule, power timer, LED pattern; pure C++
- display/: FlipdotFrames and bitmaps
- nano_link/: NanoLink (relay, serial, READY, bootloader) and flash bridge
- net/: WiFi/OTA/panic window, Home Assistant
- config.h with all settings; libs.h (globals in a header) removed

Bug fixes:
- Home Assistant switches now report their state back and start as ON
- loop() no longer blocks: WiFi.waitForConnectResult() (up to 60 s
  without WiFi) and getLocalTime() (5 s before NTP sync) were called
  every iteration
- Power switch off now powers off after 1 s even when a 30 s countdown
  is already running
- millis() overflow safe power-off timer; no frame catch-up bursts
- No garbage time string before NTP sync; 'Connecting...' stays instead
- Frames are only sent when the screen changes instead of every second
- Reset reasons are logged once instead of every 100 ms
- Removed dead code (unused fonts, WiFiMulti, rotated bitmap, ...)

Tests: new test_esp32 environment (26 tests); native renamed to test_nano

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:56:32 +02:00

4.2 KiB
Raw Blame History

Arduino Nano: flipdot driver

PlatformIO environment: nano

The Nano is connected directly to the Brose panel electronics. It keeps an 84 × 19 frame buffer and takes drawing commands over serial (115200 baud). It has no clock or network logic.

Files

File Contents
main.cpp setup() / loop(), feeds serial bytes to the parser, periodic full redraw
config.h All settings: debug options, display size, flip time limits, timings
command_parser.h/.cpp CommandParser: the serial protocol, one method per command
settings.h/.cpp Flip time stored in EEPROM

The display driver itself is in lib/BROSE9323.

Tests

pio test -e test_nano runs the unit tests in test/test_nano on the PC. They feed serial data to the firmware and check what it asks the display to do: every command, bitmaps, bad input, flip time storage and the full-redraw timing. The Arduino core, EEPROM and the display driver are replaced by fakes in test/mocks.

Behaviour

  • Boot: the Nano loads the flip time from EEPROM, sets up the pins and sends READY. It doesn't flip any dots at boot. The relay powers the Nano, so it boots every time the display is switched on.
  • First display() after boot redraws every dot, because the Nano doesn't know which state the dots were left in.
  • display(): compares the new buffer with the last one that was shown and strobes only the dots that changed.
  • Every 2 minutes (REFRESH_TIME) it does a full redraw to fix dots that got stuck. A full redraw blocks for about half a second, which is long enough to overflow the 64-byte serial buffer. So it only runs right after a D (the end of a frame, when the ESP is quiet) or when no serial data has arrived for 2 seconds.
  • Flip pulse length (µs, 50–2000) is set with the T command and stored in EEPROM, so it is kept after a reboot. The default is 200 µs.

Debug options

Uncomment these in config.h:

Define Effect
DEBUG Print unknown command bytes on the serial port
MEASURE_REFRESH At boot, time a full redraw and print the duration in ms

Serial protocol

Each command is one ASCII line that ends with \n (\r is ignored). The Nano collects a whole line before it runs the command. If a line is broken or unknown, it is skipped and the next line starts clean. Coordinates are 2-digit hex. Color is 0 (black) or 1 (yellow). The ESP32 driver (ESPSERIAL) only uses s, S, F, D and T.

Cmd Format Meaning
s sXXYYc Set pixel in the buffer
S SXXYYc Set pixel and flip it right away (direct mode)
F Fc Fill the whole buffer
D D Push the buffer to the display (changed dots only)
P PXXYYcsTEXT Print text at (XX,YY), color c, size s. A literal \n (backslash, n) in TEXT starts a new line. The whole line can be at most 64 characters.
B BXXYYWWHHcHEX... Draw a bitmap. WW must be a multiple of 4. Pixel data is one hex digit per 4 pixels, row by row. The data is drawn while it arrives, so it is not limited to 64 characters.
R R Print the buffer as ASCII art on the serial port
T Tnnn Set the flip pulse length in µs (decimal, 50–2000), stored in EEPROM

Replies on the Nano's TX pin:

  • READY after booting. The ESP waits for it before sending the first frame.
  • ERR: ... for invalid commands.

Example (what the ESP32 sends for one pixel and a refresh):

s0a051
D

Wiring (default pinout)

The pins are defined in lib/BROSE9323/BROSE9323.h. If you use the PLCC adapter board, build with -D FLIPDOT_PLCC_ADAPTER to switch to its pinout.

Signal Nano pin
ENABLE D7
ADDR_0 / 1 / 2 (panel select) D3 / D5 / D6
COL_DATA D4
COL_0 … COL_4 D8, D10, D9, D11, D12
ROW_0 … ROW_4 A3, A4, A2, A0, A1
ROW_RESET D13
ROW_SET A5
Serial RX D0 (from ESP32 GPIO 17, TX2)
Serial TX D1 (to ESP32 GPIO 16, RX2, through a 5 V → 3.3 V voltage divider). Optional: needed for READY. Without it, the ESP waits the full 3 s timeout.