Files
nixie-clock/CLAUDE.md
T
mangavalkandClaude Opus 5.5 9a7061383c Add Home Assistant controls over MQTT
Upgrade ArduinoHA from 1.3.0 to 2.1.0 and rewrite mqtt.ino for it.
The clock now shows up in Home Assistant (discovery prefix
"homeassistant") with:
- switches Tubes (blank the display, runtime only) and Auto dim
- numbers Day/Night brightness
- light Backlight (on/off, brightness, RGB mapped to the colour wheel)
- select LED effect, button Cathode protect
- sensors Light (LDR) and WiFi signal, plus the upstream sensors when
  the clock has them; master-clock subscriptions are kept

Settings changed from HA are saved to EEPROM 3 s after the last change.
Fixes the unbounded memcpy in the MQTT message handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:37:25 +01:00

5.8 KiB

Nixie clock: notes for Claude

An AliExpress WiFi nixie clock (4x IN-12 + 2x IN-3 neon dots, 8x WS2812) that is being moved from its closed stock firmware to ESP_UniClock (https://github.com/gpeter62/ESP_UniClock) with ArduinoOTA and Home Assistant (MQTT) support.

The device

  • On the network at 10.1.1.97 (WiFi dlink-iot). Since 2026-10-25 it runs ESP_UniClock (firmware/uniclock/, CLOCK_90): web UI on port 80 (JSON at /getConfiguration, /getCurrentInfos), ArduinoOTA on UDP 8266 (hostname nixie-in12, no password yet).
  • Board: RetroModding (Konstantin Repnikov) "NixieIN12v2 HV2.0", stock firmware SV1.3 (©2020). ESP-12 (ESP8266, MAC 30:83:98:99:BF:DE, Espressif).
  • Powered by USB-C 5 V only (no DC jack). Most likely the maker's "v2.0L lightweight 5 volt version". The user says the PCB looks different from the 12 V v2 board.
  • No buttons fitted, only the light sensor.
  • Stock settings (2026-10-25): time zone +01:00, EU DST on, NTP time.euro.apple.com, brightness auto, 24 h. Stock DST might not work: check in late March.

Stock firmware (from the flash dump)

  • firmware/stock/nixie_stock_SV1.3_full_4MB.bin (gitignored), SHA-256 b069f4eb93cf1e9063a30374db4d70508211f07b0a17049bcf9ebdeda65f2985, verified against the chip with verify-flash. Flash: 4 MB, DIO, 40 MHz.
  • Arduino ESP8266 core 2.x (NONOS SDK 2.2.2-dev), built for board ESP8266_NODEMCU. App at 0x1000 (~1 MB slot), SPIFFS at 0x200000. Settings live in SPIFFS as JSON (/config.json, /wifi.json, /light.json, /leds.json, /alerts.json, /hardware.json).
  • Hidden pages: /d = "Hardware setting" (hidden from the menu by default). It has checkboxes to hide/show menu items and a Debug mode (dev) checkbox. With Debug mode on, /u serves the standard ESP8266HTTPUpdateServer upload form, which is web OTA for .bin/.bin.gz. /r reboots on a plain GET; don't GET unknown paths blindly.
  • No pin numbers are visible as strings; confirming the pinout needs disassembly or the bit-stepping test sketch.

Pinout

From the 12 V v2 schematic (docs/schematic_v2_12V.jpg), checked against the stock firmware by disassembly (docs/stock-firmware-pins.md, tools in tools/). "Hardware" = also works on the clock with UniClock; "Binary" = only confirmed in the stock SV1.3 code.

Function GPIO Source
74HC595 DATA / CLOCK (OE tied to GND) 13 / 14 = HSPI MOSI / SCK (hardware SPI, MSB first) Hardware
74HC595 LATCH 15, plain digitalWrite (has 1k pull-down) Hardware
WS2812 data 12 (NeoPixel bit-bang, GRB 800 kHz; 8 fitted, stock assumes 12). SPI.begin() turns GPIO12 into MISO: set it back to OUTPUT afterwards Hardware
Photoresistor (LDR, 10k to GND) ADC (A0) Hardware
BTN1 / BTN2 (not fitted) 0 / 2, INPUT_PULLUP. Stock: GPIO0 is a button, GPIO2 a motion/presence input that wakes the display Binary
DFPlayer Mini (stock feature) UART0: GPIO1 TX / GPIO3 RX, 9600 Bd Binary
DS3231M RTC SDA / SCL 4 / 5: no I2C device answers (UniClock scan), so no RTC on this board; NTP only Hardware

Two chained 74HC595s make one 16-bit word, all bits active-high (confirmed from the binary; the high byte is sent first and goes to U2):

  • U1 QA..QH = cathodes 0..7 (bits 0..7), U2 QA = cathode 8 (bit 8), QB = cathode 9 (bit 9) (via 2x ULN2003, shared by all tubes)
  • U2 QC = P1 (bit 10) drives both IN-3 neon dots. QD..QG = anodes A1..A4 (bits 11..14, MMBTA42/92). QH = P2 (bit 15) drives the IN-12B decimal points on this board (JP2 closed), not a neon.
  • The display is multiplexed: one anode on at a time. A1 = leftmost tube (hour tens), A4 = rightmost (minute ones) (verified on the tubes). The dots are lit in the minute-tens slot only, as on stock.

Programming header

Header on the PCB: GND, GPIO0, RST, RXD, TXD, 3.3V. The USB-C port only supplies power. Flashing is done with a CH340C board on COM7 (COM3 is another device; leave it alone). Wiring: GND-GND, adapter TXD -> clock RXD, adapter RXD -> clock TXD, adapter 3.3V not connected (the clock is powered from its own USB-C). No auto-reset: to enter flash mode, hold GPIO0 to GND, tap RST to GND, then release GPIO0.

  • esptool is installed for the user (python -m esptool, v5.6.0). After --after no-reset the stub keeps running at the new baud rate and the next esptool call can't connect: do everything in one call, or re-enter flash mode.
  • Normal updates go over WiFi: pio run -e nixie_in12_ota -t upload in firmware/uniclock/. ArduinoOTA does not answer after the clock switched from AP mode to WiFi without a reboot (first setup); a power cycle fixes it.
  • firmware/stock/ holds the stock flash dump. Never overwrite or delete it; it is the only way back to SV1.3 (write-flash 0 <dump>). Dumps are gitignored because the flash holds the WiFi password; never commit them.

Constraints

  • The 170 V tube supply is live whenever USB-C is connected.
  • Hardware is only reachable via the user: anything that needs RST/GPIO0 or looking at the tubes must be asked of them. Builds can be checked here, but runtime behaviour can't.
  • Show the exact plan before making changes to the device (flashing, saving settings).

Plan

  1. Done: dump and inspect the stock firmware.
  2. Skipped (the disassembly was enough): bit-stepping test sketch.
  3. Done: 74HC595-multiplex driver (nixie595.ino) + CLOCK_90 in ESP_UniClock, ArduinoOTA, EU DST fix. Runs on the clock.
  4. Done: Home Assistant over MQTT (broker 10.1.1.175, discovery prefix homeassistant). mqtt.ino rewritten for ArduinoHA 2.1.0: switches Tubes/Auto dim, numbers Day/Night brightness, light Backlight (on/off, brightness, RGB -> UniClock colour wheel), select LED effect, button Cathode protect, sensors Light/WiFi signal. Broker settings are read at boot.
  5. Open: OTA password via secrets.h; ArduinoOTA after the AP -> WiFi switch.