Christopher Sheehan

Christopher Sheehan

This has been my most challenging project to date. It is a 7200-pixel LED grid on my ceiling made with 48 LED strips, each with 150 LEDs. These are all powered by an esp32 on a custom PCB. The PCB uses 6 shift registers to split 6 of the esp32’s pins into 48 output channels. The code running on the esp32 uses a heavily modified version of the FastLED library. It pulls data from an SD card for the animations and connects to a custom-built iPad app over a web socket for drawing functionality.

The hardware:

These photos show the final version of the PCB that controls the 48 LED strips. This board was designed with the knowledge gained from 2 prototype boards that came before it. It has a redundant 5-volt buck converter power supply, 6 shift registers, and two level shifters for the data, clock, and latch lines. The PCB was designed in EasyEDA and ordered through JLCPCB. 

The Software:

The esp32 was programmed in the Arduino IDE. It uses a highly modified version of the FastLED library to control the shift registers, splitting each LED output pin on the esp32 into 8 channels. 

To play animations a python script converts a video from its original format to a 155×48 grid of pixels and then to a series of 8-bit RGB values stored in .bin files. Each file contains one frames worth of data. The esp32 then reads and parses these files, playing back the animation at 30 frames per second. Optimizing this function was a challenge. Originally, each frame took over 1000 microseconds to be read, parsed, and displayed. Over the course of a week, this was reduced to less than 33 microseconds, enabling playback at the 30 FPS target.

To draw on the pixel array I built an iPad app. This uses a WebSocket to communicate to the esp23. Every time a setting is changed in the app, for example paint brush radius or color, a command is sent to the esp32 to update the corresponding variable in the microcontroller. When drawing, your finger location on the iPad screen is sent to the esp32. The microcontroller will draw a dot at each location. Every “line” you draw is really a just long series of dots!