Saturday, January 11, 2014

Trinket - Color by Sound RGB NeoPixels

I wanted to experiment with the NeoPixels and the Trinket so I decided to make sound reactive lights. The Adafruit NeoPixels are nice. They can be chained together and require only one IO pin to stream data to a chained strand. I chained 4 of them together for this project I also used an microphone breakout available from Adafruit.

Here is the full parts list:

  1.  Adafruit Trinket 3V Logic   ( $7.95)
  2. Max 4466 Mic Amp  ($6.95)
  3. Some wire that I had on hand to make the connections (~$3.00) 
  4. (optional) Small Breadboard for prototyping I had on hand  ($5.00)
  5. (optional) An Arduino Micro Board I used for collecting data and prototyping ($22.95) 

The total cost to make the project is about $20 + taxes and shipping.


 Get the Trinket code for this project here..

The Project

 I wanted to set the color of the lights based on the frequency of the sound detected, or something close to that using the Trinket. To do real frequency detection I was thinking I'd need to do FFT  (Fast Fourier Transform) processing in real time. This seemed like it might be too much calculation for the little trinket so I decided to do something a little less intensive,  I took a look at the Mic data to see what might be possible. I used the Arduino Micro to do data collection from the Mic because it has something the Trinket doesn't have, USB Serial communications.

Data Collection

First, I collected Mic sample data using the Arduino Micro's USB Serial to see what the data looked like. I wrote some code  in the setup method to output data collections of 2048 samples of the Mic data collected directly from analog input on pin 8 of the Micro. I collected data for three situations: quiet ambient noise, Heavy Metal music playing, and some rather average music playing. The sample data is shown below.
Quiet Noise (2046 Samples)
Heavy Metal (2048 Samples)
Average Music (2048 Samples)
The data showed that the baseline Mic noise level was always about the same, roughly just above 500. Of course, there was a lot of variation in the heavy metal data and a less variation in the average music data with the quiet ambient data being pretty predictable. The samples were polled every 5 ms.

A look at the Slope

The following graph shows the slope calculation from the data collected for average music shown above.

Average Music Slope (2048 Samples)

The nice thing about the slope over the raw data is that it is centered around 0. So no offset level prediction is needed. However, if I change the color of the lights too often, the lights may not update quickly enough nor will my eyes be able to perceive the intended color.

To ensure the lights will be OFF when there is no interesting sound, I exclude slope changes below 100 to make sure it would be above the value typically seen by quiet noise.  To keep the lights from changing color too much or too often, I choose to fade the LEDs in and out.


The Period Dependency

The final variable in this project is the Period between the slope level detection. The get a loose frequency dependency, I track the period of time between slope calculations that exceed 100. Each time the Period changes, the Period is mapped to the colors on the color wheel (0-255) with some scaling to make things more interesting.

Of course, this is not an exact frequency mapping to the sound  but it does provides interesting color variation that depends on the sound playing.