How the Shining Mask code drives a Bluetooth LED mask
Development draft. Not tested against our stocked units. This note describes the linked project and source documents. Check the exact board, firmware and hardware before trying it; it does not establish compatibility of a product we sell.
The Shining Mask project connects a Bluetooth LED mask to a CircuitPython board and uses a Nunchuk as a gesture controller. Custom images loaded onto the mask become expressions, and a movement of the controller makes the face blink, speak or react.1 Its code is one file of about 170 lines, and it shows how little it takes to drive the mask from your own hardware.2 It’s an older experiment rather than a maintained product.1
What the code sends
The board scans for a device advertising the Bluetooth LE service 0000fff0-0000-1000-8000-00805f9b34fb, connects to it, and writes to one characteristic, d44bc439-abfd-45a2-b575-925416129600.2
Every command is 16 bytes, encrypted with AES-128 in ECB mode under a fixed key that’s written in the code. The command to show an image is the byte 0x06, the ASCII text PLAY, the byte 0x01 and the image number, padded to 16 bytes with fixed filler bytes. The code builds commands for images 1 to 20 when it starts.2
So the board never sends pixels. It tells the mask which of its stored images to show, which is why the README says to load your own images onto the mask before you try the code.3
On CircuitPython the encryption comes from the built-in aesio module. Where that isn’t available, the code falls back to Crypto.Cipher.AES.2
The controller
The Nunchuk is an I2C device: WiiBrew documents it as 400 kHz “fast” I2C at address 0x52.4 The code reads it through Adafruit’s CircuitPython Nunchuk library on the board’s default I2C bus.25 Adafruit’s breakout adapter puts the controller’s plug on a STEMMA QT cable and does the level shifting and power regulation, so it works with both 3.3 V and 5 V boards.6
The mapping is simple:2
- the joystick’s left–right position picks a face;
- holding Z switches to a second set of faces;
- C picks one at random;
- now and then, at most about once a second, a four-frame sequence plays a blink.
The code polls the controller about ten times a second and resends the current image about 24 times a second. If a write fails, it disconnects and restarts the program, which reconnects.2
What you need to run it
-
A CircuitPython board with Bluetooth LE. The project doesn’t name one.3 On CircuitPython the code needs Bluetooth LE support (the
_bleiomodule) andaesio, and CircuitPython’s support matrix lists both for, among others, the Adafruit Feather nRF52840 Express and the Adafruit QT Py ESP32-S3.7 Module availability is a prerequisite, not evidence that this project has been tested on either board; the original build board is not identified here. -
Libraries:
adafruit_ble,adafruit_nunchuk, andasynccp, which schedules the loops.2 - A Nunchuk or a Nunchuk-compatible controller, and a way to connect it: the adapter above, or wires to the board’s I2C pins.
-
The mask. The code looks for the
FFF0service and the characteristic above. Before you count on a particular mask, check it with any Bluetooth LE scanner app: it should advertiseFFF0. Service advertising alone does not verify command compatibility. No stocked mask is claimed to have passed this check.
Wii and Nunchuk are trademarks of Nintendo. FastGizmo isn’t affiliated with or endorsed by Nintendo.
Sources
Read 10 October 2026.
- Shining Mask: a Nunchuck, a microcontroller, and a face (bricoleur.ai)
- main.py (shawnrancatore/shining-mask on GitHub)
- shining-mask README (shawnrancatore/shining-mask on GitHub)
- Wiimote/Extension Controllers (WiiBrew wiki)
- Adafruit_CircuitPython_Nunchuk (Adafruit on GitHub)
- Adafruit Wii Nunchuck Breakout Adapter, Qwiic / STEMMA QT (Adafruit product 4836)
- Module Support Matrix (CircuitPython documentation, latest)