To allow our LED matrix to synchronize the animations to music, we need to interface it to an audio source. The ATmega328 MCU conveniently contains A/D converters which we can use for this purpose. Although there are various designs for color organs, which work with various frequency bands, I prefer syncing with the bass track.
We could use an analog pin to sample music, and then do frequency analysis on the Arduino, but this would introduce a delay, and still require us to build an antialiasing filter. Since we need to build a filter, we might as well keep things simple. I built an analog low pass filter, fed its output into an analog input in, and then simply tested the amplitude against a threshold. I started with a the simplest possible filter, a first order low pass RC filter. Much to my surprise, it worked fairly well. To design the filter, I first needed to figure out what cutoff frequency to use. The cutoff frequency, Fc, of a filter is the frequency where the power is cut in half. After playing around with graphic equalizers in Winamp while playing music with thumpy bass tracks, I settled on Fc = 100Hz. I didn't have the proper resistor handy, so I used the closest value I had, which resulted in Fc = 133Hz. Here is the circuit:
(1) 10uF electrolytic capacitor
(1) 120 ohm resistor
(1) 1/8" TRS jack
The output connects to analog pin 0 on the Arduino. Connect its input to an audio source, such as the headphone jack of a stereo, or an MP3 player. DO NOT CONNECT IT TO SPEAKER LEVEL OUTPUTS FROM AN AMPLIFIER UNLESS YOU'RE SURE IT OUTPUTS <= 5V. Any audio source designed to drive headphones should be safe. Since I use the headphone jack on a stereo, I can still hear the music even when the circuit is plugged in. If you're using something with only one output, such as an MP3 player, you can hook up two TRS jacks in parallel, and then feed the audio from the 2nd jack to a set of powered speakers or headphones.
Note that the circuit above only monitors one channel of audio, which works with most songs, since the bass is generally approximately equal amplitude in both channels. It works OK, but I found that in order to get a high enough input for the Arduino to respond nicely, I have to turn the volume up a bit too high for my tastes. Therefore, I also built the alternate circuit below:
(1) 10uF electrolytic capacitor
(1) 120 ohm resistor
(3) 10K ohm resistor
(1) 100K ohm resistor
(1) 1/8" stereo TRS jack
(1) TLC272CP op amp IC
UPDATE: Sorry, the schematic diagram above is wrong. There should be a third 10K resistor, R5, which connects between pin 2 (- input of opamp) and GND. The gain of the amp is R4 / R5.
You can substitute any suitable op amp. I used the TLC272CP because that happens to be what I had on hand, and it has the particularly nice characteristic that it doesn't mind running on a single-ended power supply of only 5V, so I could just hook it up to the Arduino's power. The circuit above mixes the left and right audio channels, and has a gain of 10. Just hook it up to your stereo audio source, and connect the output to analog pin 0, as before. The 5V and GND also connect to your Arduino.
If you prefer to use a microphone rather than direct wiring, pepehdes has posted an alternate circuit using an electret mic in Step 1's comments, which he says works well. Note that it is an all-pass design so it will trigger on all frequencies, not just bass. I didn't use a microphone, because my design tracks the bass which might not be picked up very well via small speakers and a microphone.
Next, we need to modify the sketch to read the audio input, and trigger the next animation frame when a threshold is exceeded. The new sketch, daftPunkSyncV2.zip, is attached below. You can switch the sketch between music sync and free-running by modifying
You will need to manually tune the threshold variable:
// trigger next frame when music amplitude > threshold
// increase threshold to decrease sensitivity
// decrease threshold to increase sensitivity
int threshold = 5;
The next frame will be triggered when the input read from analog pin 0 exceeds threshold. If you're running the sketch on a real arduino that has an LED on digital pin 13, it is helpful to uncomment the following line:
#define BLINKY // blink LED on pin 13
by removing the leading // characters. This will cause the LED to blink when threshold is exceeded. I have it turned off in the sketch by default, because I'm using my tiny breadboard instead of an Arduino now, and it doesn't have an LED. Finally, you may want to experiment a bit with minBeatInterval:
// debouncing - filter out consecutive triggers that are too close
// together to slow down the animation. decrease this value
// to make it more sensitive to shorter beat intervals
int minBeatInterval = 1000;
Note that this variable is unit-less. It simply defines how many consecutive loops after the input exceeds our threshold before the sketch is allowed to trigger the next frame. I found that in many songs, bass beats are actually composed of several very closely spaced peaks. If we don't filter them out, then the display will advance several frames for each beat. You might actually like this effect, because it makes the display more lively. Play around with it, and see what setting you prefer.