Introduction: ThunderVUmeter

About: We are two young makers who develop electronics and robotic systems. We make things which are #LikeNoOther. ⚡

This project was created accidentally by doing some tests with RGB LEDs and and TLC5940s, between various combinations and strange color effects tests, we had the idea to connect the audio jack to the microcontroller to try to synchronize the music with colors. The result immediately seemed great, even without filtering or amplifying the audio signal, and we were surprised by how this project was so easy to make and at the same time very beautiful and interesting.Finally we could publish this tutorial for all the people who in the last two years, after watching our videos on YouTube, have asked us how this object works and how to make it.

Step 1: How Does It Work?

The way our #ThunderVUmeter works is extremely simple: the microcontroller reads the analog values of the two audio channels and turns on a number of LEDs in proportion to the measured value.Actually, in order to beautify it, we also added a color management that complicates a little program, in fact, using the library leOS2 of Leonardo Miliani we added a function that runs in parallel to update the color values of the LEDs.

Step 2: Hardware

You can find the schematic here:

As already mentioned, the hardware is very simple, the only complication is that there are many components to put together. So, let's see what are the parts we used: an ATtiny84; three TLC5940; 64 RGB LEDs common anode; a medium size capacitor to stabilize the voltage which, in our case, comes from an old ATX power supply and that has a little ripple; and five resistors, referring to the diagram below, R1 and R2 are 10k, and R3, R4 and R5 are 1.5k.
Looking at the circuit we see that the audio jack (JP1) is connected in order to have a common ground with the rest of the circuit and the two channels are connected to the first two analog inputs.To control the TLC5940 from ous small ATtiny84 we only need 3 signals, 2 of them are in common to all TLCs while one, the SIN, enter the first TLC which processes it and then sends it to the next TLC, the SOUT.The last important thing to notice is that the resistors R3, R4 and R5 are used to set the maximum current that the TLC5940 will allow to flow on its outputs, for more information about that see the datasheet.

Step 3: Software

So, let's describe the part of the code used to handle as mentioned earlier. First of all we need to have the library leOS2 of Leonardo Miliani (not the leOS because in the ATtiny there isn't the TIMER 2) and the library which allows us to control TLC5940s with ATtiny84 and ATtiny85. This library was originally created by the user of the forum Arduino "Fungus" and modified by us to use it with ATtiny84 and this one can be downloaded from here. Let us now examine some of the key points of the code, starting from the function to send data to the TLC5940 "tlc5940.update()", which we have already explained in the project #HeartThrob, and which has the peculiarity that lasts about a millisecond and that only during this period the LEDs are turned on.Another thing to notice in the code is the code used to do the auto-scale function according to the volume of the music. This process works in a very simple and intuitive: if the read value is higher than the full scale, it increases the full scale value; if, instead, the values read do not come close to the full scale for a long time, in our case two seconds, then the full scale value is reduced.

#include <Arduino.h>
#include <Tiny_TLC5940.h>
#include <leOS2.h>
leOS2 OS;

#define MIN 20     //Minimum value to autoscale
#define K   1365
#define K2 819
#define T   3

unsigned long time=0;
byte ds=0;
unsigned int red=0, green=0, blue=4095, x=MIN;
unsigned int c[8][3]={0};

byte s=0;

void <strong>setup</strong>(){
  tlc5940.init();           //Initialize TLC5940s

  for(byte er=0;er<8;er++)  //Set initial color values

  OS.addTask(colors, T, SCHEDULED_IMMEDIATESTART); //Update color values every T*16 milliseconds

void <strong>loop</strong>(){
  if(millis()-time>2000){            //Auto-scale for lower values function

  byte right = read(1);              //Read values
  byte left = read(0);

  tlc5940.clear();                   //Clear old values

  byte er=8-right;
  for(byte re=8-right;re<8;re++){    //Set the new values for right channel
    tlc5940.set(re*3, c[er][2]);
  for(byte re=8;re<8+left;re++){     //Set the new values for left channel
    tlc5940.set(re*3, c[er][2]);

  tlc5940.update();                  //Send data to TLC5940

byte read(boolean channel){
  unsigned int a=analogRead(channel);//Read the value of a channel

  while(a>x+x/9){                    //Auto-scale for higher values function

  return map(a,0,x,0,8);             //Calculate how many LEDs to turn on and return that value

void colors(){                       //Update color values
  for(byte er=0;er<7;er++){
  case 0: 
    else red+=K2; 
  case 1: 
    else blue-=K2; 
  case 2: 
    else green+=K2; 
  case 3: 
    else red-=K2; 
  case 4: 
    else blue+=K; 
  case 5: 
    else green-=K; 
Summer Fun Contest

Participated in the
Summer Fun Contest