3D n-Body Simulator
There is an unsolved problem in physics: predicting the motion of n-bodies interacting with each other through a force.
I first learned about this in a wonderful science-fiction book series called Remembrance of Earth’s Past, in which the physics of the problem have eminence repercussions. I was inspired to bring the dance-like motion of celestial bodies to a tangible form. There are simulations online, but I build an LED cube to display the movements in 3D.
The hardest part was the i/o
The LED cube is 8x8x8, which means I need to control 512 LEDs. Most microcontrollers only have 30 pins that can control LEDs, so I had to arrange the LEDs in the cube to minimize the number of pins I needed to operate them. By taking advantage of shared cathode and anode buses, I was able to get the pin count down to a more manageable 72. That was still out of reach for just one microcontroller, so I designed a PCB to hold a cluster of 3 Raspberry Pi Picos.
I tried for a while to get the three Picos to communicate over I2C, but ultimately, some issues with the PCB meant this path was a dead end. Even if the board was perfect, the core idea of using a cluster was too complicated for what I really needed.
I switched gears and looked into using I2C-driven i/o expanders. A single, central microcontroller sent I2C commands to expander ICs that turned on and off each pin of the cube. I ran some tests with this method, but there were problems with how fast it could cycle the LEDs. The baud rate of the expander chips were too slow, which killed any chance of making it work.
I had to go even simpler, even lower level. By using several dozen ‘and’ gates, it was possible to reduce the needed i/o pins to the upper limit of what a single Pico could handle. I used 16 ‘and’ ICs (each containing 4 gates), silicon wire, and a whole lot of patience to create my expander board.
Initial Pico-based expander circuit board
Backside of logic gate expander board
Physics Program
The program that controls the 8x8x8 LED display uses (x, y, z) coordinates to identify each ‘pixel’. Each body within the simulation is an object with a position, velocity and acceleration vector. By iteration over each body and applying gravitational interactions for small time steps, the kinetic vectors can be updated and the new positions for the bodies can be displayed.