I glued 100 WS2812 NeoPixels to a hat then mapped them in 3D space
Construction
You will need:
- A hard hat
- A Pi Zero W
- A button shim
- An OLED display
- 2 NeoPixel strings
- A power bank
- Wire
- Hot glue
I hot-glued the lights to the hat, turning in a random(ish) direction after I'd glued-down each one, attempting to move towards empty space each time. I also managed to stick 2 or 3 of them on backwards because I'm an idiot.
I cable-tied the Pi to the power-bank and wired everything up, producing something you absolutely would not want to try to take through an airport:
The data line is connected to pin 21 (physical pin 40).
Installing the software
From a box-fresh install of Raspberry Pi Bullseye:
Set hostname and enable serial port and i2c
sudo raspi-config nonint do_hostname hatlights
sudo raspi-config nonint do_serial 1
sudo raspi-config nonint do_i2c 0
sudo reboot
Install git
sudo apt -y update && sudo apt install -y git
Get this repo
git clone https://github.com/hat-festival/hatlights
Install everything
cd hatlights
./configure
make
Mapping the lights
Once everything is assembled, you need to take lots of photos, and do a load of analysis.
Controls
The five buttons are mapped
in conf/buttons.yaml
:
button | press to cycle | hold to cycle |
---|---|---|
A | modes | |
B | colours | colour-sets |
C | colour-sources | |
D | axes | invert |
E | display modes |
Modes
A mode
needs to inherit from Mode
,
and should expose a run
method, which loops forever and does something with the lights, and a reconfigure
method, which resets the hat to the mode's preferences.
The ordering of the modes is defined in this list, and the modes' preferences are defined in conf/modes.yaml.
Some of the modes involve some pretty intense maths which, if done in
real-time, will slow everything down to a crawl. In these cases, it's sensible
to pre-render the set of states. A mode
named
foo
will attempt to deserialise
a file at renders/foo.pickle
into an instance attribute
called frame_sets
.
Colour-sets
Colour sets are defined in conf/colour-sets.yaml
- pressing the colours
button will step through the colours in a
set, while holding the same button will step through the sets themselves.
It's up to a mode if it actually makes use of these settings.
Colour sources
There are three kinds of colour-source:
- Redis: this (poorly-named) source means "use whatever colour is
currently defined at
hat:colour
in Redis". This is the colour that gets set by thecolour
button - Wheel: the ColourWheel
is running as a daemon, and populating the
hat:hue
key in Redis with a constantly-rotating value between 0 and 1, using a step-size and interval defined in conf/conf.yaml. Callingget("colour")
on theCustodian
(which is mostly a wrapper around Redis) will, if thecolour-source
iswheel
, return an RGB triple based on thathue
value - Random: uses a random hue between 0 and 1 to generate an RGB triple
Axes
If you're looking at the hat square-on from the front, then
x
goes from -1 on the left to +1 on the righty
goes from 0 at the bottom to +1 at the top (this makes sense if you think about the hat as the top half of a sphere)z
goes from -1 at the back to +1 at the front
For most of the modes, it makes sense for them to orient themselves with
respect to an axis, and pressing the axis
button will cycle
through x
, y
and z
. Holding this button
will invert the direction of movement along or around that axis.
Display modes
Pressing the display modes
button cycles through the three modes
for the OLED screen:
- Hat settings: shows the hat mode, and if relevant, the axis/inversion state and the colour and colour-set
- Button config: shows the
abbreviation
fields from the button-mappings. They don't quite line up, but it's good enough - IP address: shows the hat's current IP address