Skip to content

Latest commit

 

History

History
348 lines (267 loc) · 14.1 KB

File metadata and controls

348 lines (267 loc) · 14.1 KB

DefCon 34 Washer/Dryer Badge

DefCon 34 washer/dryer badge

Arduino-compatible firmware for the DefCon 34 FirstBuild / GE Appliances washer/dryer badge. A 3-axis accelerometer drives an infinity-mirror LED ring so the illuminated "water" follows gravity with a damped circular response.

The current production target is an STM32G031F8P6 with an MXC6655XA accelerometer and eight SK6805 side-emitting RGB LEDs. The repository also keeps some of the earlier Adafruit KB2040 prototype profile and drivers.

Features

  • Gravity-responsive blue/cyan water effect with configurable lag and damping.
  • Six button-selectable modes, including a power-saving Off mode.
  • One-third-brightness dim mode.
  • Motion wake, inactivity fallback, and LED sleep behavior.
  • Sensor fault indication, periodic recovery, and a hardware watchdog.
  • Production factory-test firmware for LEDs, orientation, and shake sensing.
  • Build-time hardware profiles for the MCU, sensor, pins, axes, and LED ring.

Supported Builds

PlatformIO environment Purpose Status
stm32g031f8_mxc6655xa Normal production firmware Supported
stm32g031f8_mxc6655xa_demo Demo firmware with a 3-hour inactivity timeout Supported
stm32g031f8_mxc6655xa_factory Production factory-test firmware Supported

The KB2040 environments in platformio.ini are currently commented out. The prototype profile remains available for Arduino CLI/IDE use or for developers who intentionally re-enable those environments. Running pio run -e adafruit_kb2040_lsm6dsox as the repository stands will report an unknown environment.

Production Hardware

Component Configuration
MCU STM32G031F8P6, Cortex-M0+, 64 MHz, 64 KB flash, 8 KB SRAM
Accelerometer MXC6655XA, I2C, +/-2 g, fixed 100 Hz output
Sensor address 0x15 with ADDR low; driver also tries 0x21
LEDs 8 x SK6805SIDE-G-003, GRB order, 800 kHz
LED backend Adafruit NeoPixel
Programming SWD with ST-Link or CMSIS-DAP
Native USB None

Production Pinout

MCU pin Function
PB6 I2C1 SCL
PB7 I2C1 SDA
PA6 LED data through the board's logic-level buffer
PA8 MXC6655XA DRDY interrupt, reserved; firmware currently polls DRDY over I2C
PA11 Active-low mode button and boot-time factory-test input
PA13 SWDIO
PA14 SWCLK
NRST Reset/programming

The production profile is firmware/defcon34_washer_badge/hardware_profiles/stm32g031f8_mxc6655xa.h. The custom PlatformIO board definition is boards/genericSTM32G031F8.json.

Build And Flash

Requirements

  • Python 3 and PlatformIO Core, or the PlatformIO IDE extension for VS Code.
  • An ST-Link or CMSIS-DAP SWD probe for production hardware.
  • SWDIO, SWCLK, NRST, target ground, and an appropriate target supply connected according to the board schematic and probe documentation.

Install PlatformIO Core if it is not already available:

python3 -m pip install --user platformio
pio --version

PlatformIO downloads the STM32 platform, Arduino core, and Adafruit NeoPixel dependency on the first build.

Production Firmware

# Build normal firmware
pio run -e stm32g031f8_mxc6655xa

# Upload normal firmware using the environment's default ST-Link protocol
pio run -e stm32g031f8_mxc6655xa -t upload

# Build or upload demo firmware
pio run -e stm32g031f8_mxc6655xa_demo
pio run -e stm32g031f8_mxc6655xa_demo -t upload

# Build or upload factory-test firmware
pio run -e stm32g031f8_mxc6655xa_factory
pio run -e stm32g031f8_mxc6655xa_factory -t upload

# Build every supported configuration
pio run -e stm32g031f8_mxc6655xa \
  -e stm32g031f8_mxc6655xa_demo \
  -e stm32g031f8_mxc6655xa_factory

To use CMSIS-DAP, set upload_protocol = cmsis-dap in the selected environment or its shared STM32 base before uploading.

Build artifacts are written below .pio/build/<environment>/, including firmware.elf and firmware.bin.

Continuous Production Programming

To repeatedly program badges as they are connected to the SWD probe, run:

./scripts/program-badges.sh

The script retries immediately when programming fails, such as when no badge is connected. After a successful upload, it waits 10 seconds before trying the next badge. Stop it with Ctrl-C.

Set a different post-success delay with --delay, and select another supported build with --environment:

./scripts/program-badges.sh --delay 5
./scripts/program-badges.sh --environment stm32g031f8_mxc6655xa_factory

The defaults can also be set with PROGRAM_SUCCESS_DELAY and PROGRAM_ENVIRONMENT.

Prototype With Arduino CLI

The prototype uses an Adafruit KB2040, an LSM6DSOX over STEMMA QT/I2C, and 12 WS2812B LEDs on GPIO 10. It uses FastLED and the Earle Philhower RP2040 core.

# Add and install the RP2040 Arduino core
arduino-cli config add board_manager.additional_urls \
  https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
arduino-cli core update-index
arduino-cli core install rp2040:rp2040

# Install prototype libraries
arduino-cli lib install "FastLED"

# Build
arduino-cli compile \
  --fqbn rp2040:rp2040:adafruit_kb2040 \
  --build-property "build.extra_flags=-DPROFILE_ADAFRUIT_KB2040_LSM6DSOX=1 -DDEBUG_SERIAL_ENABLED=1" \
  firmware/defcon34_washer_badge

# Upload after replacing <port> with the KB2040 serial device
arduino-cli upload \
  --fqbn rp2040:rp2040:adafruit_kb2040 \
  -p <port> \
  firmware/defcon34_washer_badge

The sketch folder can also be opened directly in Arduino IDE after installing the same core and libraries.

Using The Badge

The active-low button is ignored for mode changes during the first second after boot so a boot-held button does not also change modes.

Action Result
Short press and release Advance to the next LED mode
Hold for at least 3 seconds Toggle one-third-brightness dim mode
Hold low while powering on Request factory-test mode

Modes cycle in this order:

  1. Water: gravity-following blue/cyan water; this is the default.
  2. RainbowSpin: a rainbow rotates around the ring at 0.25 revolution/second.
  3. ColorFade: the full ring fades through hues at 0.2 cycle/second.
  4. OpposingSpin: two evenly spaced white spots rotate at 1 revolution/second.
  5. WhiteTest: all LEDs show white at the active brightness cap.
  6. Off: LEDs and accelerometer are shut down and the MCU sleeps between button checks. Press the button to wake directly into Water.

WhiteTest can draw substantially more current than the water effect. Use a power source and wiring suitable for all eight LEDs at the configured maximum brightness.

Runtime And Power Behavior

  • The application polls at 125 Hz. The production sensor produces data at 100 Hz, and gravity estimation advances only when a fresh sample is available.
  • When the ring-plane gravity projection is too small, such as when the badge lies face-up, Water mode holds its last reliable direction instead of following sensor noise.
  • Clear motion wakes sleeping LEDs and resets the inactivity timer.
  • In the normal production build, a non-Water mode returns to Water after 30 seconds without activity. That transition restarts the inactivity timer.
  • Water mode turns the ring off after 3 minutes without activity. Sensor polling continues at the normal cadence so movement can wake it.
  • In the demo build, the selected mode is retained and the ring turns off after 3 hours without activity; the 30-second Water fallback is disabled.
  • Off mode clears the LED ring, drives its data line low, powers down the accelerometer, and skips normal application work. The MCU sleeps between 20 ms button polls so the 2-second watchdog remains serviced; a button press resumes the sensor and returns directly to Water mode.
  • The optional battery monitor would cap brightness at 30/255 below 3.3 V, but battery measurement is disabled in the current production and prototype profiles because no battery ADC input is configured.
  • A 2-second watchdog resets the MCU after a runtime hang.

The stationary detector enters the IdleCycle state after approximately 12 seconds of stable, near-1 g readings. The controller calculates fill, agitate, tumble, and pause phases, but the current SimpleWater renderer still uses the measured gravity vector in both interactive and idle states. Automatic virtual drum motion is therefore not currently visible in normal Water mode.

Factory Test

The recommended production path is to flash stm32g031f8_mxc6655xa_factory, which defines both FACTORY_TEST and DEBUG_SERIAL_ENABLED.

Factory test can be requested in three ways:

  1. Flash the factory-test environment; it enters the test automatically.
  2. Hold PA11 low while powering on any build.
  3. On a debug-serial build, send test followed by a newline during the first 3 seconds after boot.

The sequence performs:

  1. Full-ring red, green, blue, and production-brightness blue checks.
  2. A single-LED white chase to verify order and soldering.
  3. A blue marker at the configured physical-bottom index.
  4. Five seconds of live gravity-follow orientation checking.
  5. Five seconds of shake detection; detected motion lights the ring cyan.
  6. Five seconds of sinusoidal idle-motion preview.

The test clears the ring when complete and returns to interactive operation.

Serial Diagnostics

Debug builds use 115200 baud and print the I2C scan, detected sensor address, watchdog status, mode changes, and raw/filtered angle data. The production MCU has no native USB CDC, and the current badge PCB does not route MCU UART to the SWD header. An ST-Link VCP connection alone therefore does not provide firmware logs; serial diagnostics require access to a routed MCU UART on the hardware.

Fault Indication

If sensor initialization or an I2C read fails, LED 0 emits a slow red pulse. The firmware retries sensor initialization every 5 seconds and resumes normal operation after recovery.

For a persistent red pulse, check:

  • Sensor power and ground.
  • PB6/PB7 continuity and pull-ups.
  • The MXC6655XA address strap (0x15 or 0x21).
  • The selected hardware profile and sensor axis configuration.

Configuration And Tuning

Hardware-specific values live in firmware/defcon34_washer_badge/hardware_profile.h and its hardware_profiles/ headers. Animation and timing values live in firmware/defcon34_washer_badge/behavior_config.h.

Tune hardware orientation first:

  • SENSOR_AXIS_MAP: map and invert sensor axes into badge coordinates.
  • LED_INDEX_OFFSET: align logical angle zero with the physical ring.
  • LED_CLOCKWISE: match logical rotation to physical LED order.
  • GRAVITY_ANGLE_OFFSET_DEG: correct accelerometer/ring mounting rotation.

Then tune appearance and behavior:

  • MAX_BRIGHTNESS: profile-specific output limit.
  • WATER_WIDTH_FRACTION: illuminated fraction of the ring.
  • WATER_CYAN_AMOUNT and DRY_LED_BRIGHTNESS: water color and background.
  • GRAVITY_LOWPASS_ALPHA: gravity filtering response.
  • WATER_DIRECTION_STIFFNESS and WATER_DIRECTION_DAMPING: tracking lag and overshoot.
  • SHAKE_THRESHOLD_G: motion sensitivity and wake behavior.
  • Mode speeds, sleep timeouts, factory-test timing, I2C timeout, and watchdog timeout are also centralized in behavior_config.h.

Use the factory orientation and bottom-marker steps after changing ring or axis settings. The broader design requirements are documented in docs/software-spec.md.

Adding Hardware

  1. Add a profile under firmware/defcon34_washer_badge/hardware_profiles/.
  2. Add its selector to hardware_profile.h.
  3. Implement the MotionSensor interface if the sensor is new.
  4. Add a PlatformIO environment with the profile build flag and dependencies.
  5. Compile all supported environments and run the factory sequence on hardware.

Core behavior consumes badge-coordinate acceleration in units of g; sensor library types and raw register formats should not cross the MotionSensor interface.

Troubleshooting

Symptom Check
UnknownEnvNamesError for a KB2040 environment The prototype PlatformIO environments are disabled; use Arduino CLI/IDE or intentionally re-enable them.
Upload cannot find the target Check probe selection, target power/ground, SWDIO, SWCLK, NRST, and the configured upload protocol.
Slow red pulse on LED 0 The accelerometer is unavailable; check I2C wiring, pull-ups, power, and address.
Water points to the wrong location Calibrate SENSOR_AXIS_MAP, LED_INDEX_OFFSET, LED_CLOCKWISE, and GRAVITY_ANGLE_OFFSET_DEG.
Water follows rotation in the wrong direction Check axis inversion first, then LED_CLOCKWISE.
Badge does not wake Confirm motion exceeds SHAKE_THRESHOLD_G and that fresh sensor samples are available.
No serial output through ST-Link VCP The production PCB does not route MCU UART to the SWD header.
LEDs flicker or reset the badge in WhiteTest Check supply current capacity, grounding, LED power integrity, and the data-level buffer.

Clean and rebuild after changing profiles or build flags:

pio run -t clean
pio run -e stm32g031f8_mxc6655xa

Repository Layout

boards/                              Custom PlatformIO board definitions
docs/software-spec.md                Product and firmware design specification
firmware/defcon34_washer_badge/      Arduino sketch and application modules
  hardware_profiles/                 Per-board compile-time configuration
  sensors/                           MotionSensor driver implementations
LICENSE                              Project license
THIRD_PARTY_NOTICES.md               Dependency license notices
platformio.ini                       Build environments and dependencies

Dependencies

Production builds use the STM32duino Arduino core and Adafruit NeoPixel. Prototype builds use the Earle Philhower RP2040 Arduino core, FastLED, Adafruit LSM6DS, Adafruit BusIO, and Adafruit Unified Sensor. PlatformIO pins compatible dependency versions in platformio.ini.