In the “completely-useless-but-fun-to-build” category, here’s a project that lights 64 out of 256 LEDs on a 32×8 LED matrix, and then simulates the effect of gravity on these LEDs in any position of the matrix.
This is the hardware I used:
A Max7219 driven LED matrix . Only 64 LEDs will be lit on lowest brightness level; well within the UNO’s 5V capacity.
A BNO055 absolute orientation sensor. Attached to the matrix module, it will send its 3-D orientation to Arduino about twice per second.
A piezo buzzer to simulate the sound of colliding pellets. I noticed that using Arduino’s tone() function to produce beeps interferes with UNO’s pin 11, so I didn’t use that pin for the matrix.
Apart from some jumper wires, a power supply and a breadboard, that’s all I used for this project. Wiring is straightforward, so almost all of the effort went into coding the sketch.
The algorithm uses the following approach:
- At startup, 64 positions on the matrix are randomly selected and the corresponding LEDs are turned on (the rest is turned off).
- The ledControl library for Arduino is used to drive the LEDs. Since it treats the 32×8 matrix as four separate 8×8 modules, I wrote a small function to translate row-column pairs used in the status array to module-row-column triplets used by the library.
- A two dimensional boolean array keeps track of the on/off status of all 256 LEDs.
- The loop() function will start by reading the BNO055 sensor data. Then it calculates the ‘attraction’ under gravity’s law of each of the 8 (possible) neighbors a LED can have (positions outside the matrix will be ignored when processing a specific LED). Neighbors of an LED are identified by the position they hold relative to that LED when the matrix is in horizontal start position: neighbor #0 is the position vertically below, further numbering increases clockwise.
- Note that the calculated ‘attraction’ of the 8 numbered neighbor positions is valid for every LED (for the current orientation of the matrix). It only depends on the current orientation of the matrix!
- The identifying numbers of neighbor positions with positive attraction are stored in an array, in order of descending attraction.
- Now the algorithm will loop through the status array and select the most attractive neighbor for all 64 positions of LEDs that are currently on. The check order follows the array from the previous step, so the first neighbor position that is both valid (on the matrix) and available (LED is off) is also the most attractive one (gravity agrees).
- Once an attractive and free position is found for an LED, the LED is turned off and the LED at the found position is turned on.
- Whenever a LED ‘moves’, the algorithm will update the status array.
- At the end of the loop() function, the algorithm will produce a short beep if at least one LED ‘moved’ during the loop cycle (a beep after every move would result in a continuous tone because of the processor speed).
- To make the effect more realistic, a short delay was added at the end of the loop() function.
Video and sketch will follow.