# Flipdot Display Firmware for an 84 × 19 Brose flipdot display (three 28 × 19 panels) that runs as a Home Assistant–controlled clock. The system uses two microcontrollers: ``` ┌──────────────┐ WiFi / MQTT ┌────────────────┐ UART 115200 ┌──────────────┐ GPIO ┌──────────────┐ │ Home │ ◄─────────────► │ ESP32 │ ──────────────► │ Arduino Nano │ ───────► │ Brose │ │ Assistant │ │ (controller) │ text commands │ (driver) │ │ flipdot │ └──────────────┘ └───────┬────────┘ └──────────────┘ │ panels 84x19 │ │ GPIO 13 └──────▲───────┘ ▼ │ ┌─────────────┐ display power │ │ Relay │ ───────────────────────────────────────────────────┘ └─────────────┘ ``` | Part | Folder | What it does | |------|--------|--------------| | **Arduino Nano** | [src/nano](src/nano/README.md) | Drives the panel's row and column electronics directly. Keeps a frame buffer and flips only the dots that changed. Takes simple text commands over serial. | | **ESP32** | [src/esp32](src/esp32/README.md) | Connects to WiFi, gets the time over NTP, shows a clock with Pikachu bitmaps, exposes switches to Home Assistant over MQTT, switches display power with a relay and supports OTA updates. | | **BROSE9323 driver** | [lib/BROSE9323](lib/BROSE9323/README.md) | Shared `Adafruit_GFX` display driver. On the Nano it toggles GPIO pins. On the ESP32 (`-D ESPSERIAL`) it turns every drawing call into a serial command for the Nano. | Because the driver is an `Adafruit_GFX` subclass on both boards, the ESP32 can use the normal GFX API (`print`, `drawBitmap`, `fillScreen`, ...). Each call is sent to the Nano and drawn there. ## Repository layout ``` platformio.ini one PlatformIO project, multiple environments lib/BROSE9323/ shared flipdot driver (used by both targets) src/nano/ Arduino Nano firmware src/esp32/ ESP32 firmware secrets.example.h template for WiFi / MQTT credentials archive/ old, unused sketches kept for reference CLAUDE.md project notes for Claude Code ``` ## Building and flashing Install [PlatformIO](https://platformio.org/) (the VS Code extension is easiest) and open this folder. 1. Copy `src/esp32/secrets.example.h` to `src/esp32/secrets.h` and fill in your WiFi and MQTT details. `secrets.h` is gitignored. 2. Check the COM ports and the OTA IP in `platformio.ini`. 3. Build or upload: | Environment | Board | Upload method | |-------------|-------|---------------| | `nano` | Arduino Nano (ATmega328P) | USB (`COM10`) | | `esp32` | ESP32 DevKit v1 | OTA over WiFi (`10.1.1.198`) | | `esp32_usb` | ESP32 DevKit v1 | USB (`COM11`). Use it for the first flash or for recovery. | ```sh pio run # build nano + esp32 pio run -e nano -t upload # flash the Nano pio run -e esp32 -t upload # flash the ESP32 over the air pio run -e esp32_usb -t upload # flash the ESP32 over USB pio device monitor -e nano # serial monitor ``` In VS Code you can also pick the environment in the PlatformIO status bar. > **Tip:** The Nano and the ESP32 share a serial line. Disconnect the ESP32 TX → Nano RX > wire before you flash the Nano over USB, or the upload may fail. ## How it works 1. **ESP32 boot.** The ESP32 connects to WiFi and starts ArduinoOTA. After a crash or unexpected reset it stays in an *OTA panic window* for 15 seconds, so you can flash a fix before the main code runs again. It then switches the display relay on, starts NTP and connects to MQTT. 2. **Clock loop (every second).** - **07:00–22:00:** Pikachu with a thought bubble showing `HH:MM`. A yawning Pikachu is shown from 17:00. - **22:00–23:30:** the clock is only drawn on the quarter hour. In between, the relay turns the display off. - **Night:** the screen is cleared and power is cut after 30 seconds. 3. **Home Assistant switches** (MQTT discovery): - `FlipDot Display Clock`: off shows a Nintendo logo instead of the clock. - `FlipDot Display Power`: off clears the display and cuts power through the relay. 4. **Nano.** The Nano reads commands from the serial line and updates its frame buffer. On `D` it flips only the dots that changed. Every 2 minutes it redraws the whole screen to fix dots that did not flip. The serial protocol is described in [src/nano/README.md](src/nano/README.md).