Christmas Carols

I know Christmas songs have been playing everywhere for the last 3 months, but I reckon there hasn’t been much singing on 300 LEDs. So, to add 19 LEDs to our counter today, I’m going to make a Christmas song player with spectrum analyser.

carols_hero

You’ll need:

  • 19 mixed LEDs + resitors
  • Arduino UNO
  • Breadboard + wires
  • 2 shift registers

For the carolers:

  • Empty toilet rolls
  • Paint

1) Sound analyser in Processing
First of all, make sure you’ve got a .MP3 (or .WAV) of your favourite Christmas songs. Then, we’re going to use the Minim library in Processing again; but for audio output this time.

import ddf.minim.*;
import ddf.minim.analysis.*;
 
Minim minim;
AudioPlayer song;
FFT fft;
 
void setup()
{
  size(512, 200);

  minim = new Minim(this);
 
  // specify 512 for the length of the sample buffers
  // the default buffer size is 1024
  song = minim.loadFile("Christmas_Carols.mp3", 512);
  song.play();

  fft = new FFT(song.bufferSize(), song.sampleRate());
}
 
void draw()
{
  background(0);
  fft.forward(song.mix);
 
  for(int i = 0; i < 19; i++)
  {
    if(i%3 == 0) {
        stroke(255, 0, 0, 128);
        fill(255,0,0,128);
    } else if(i%3 == 1) {
        stroke(255);
        fill(255);
    } else {
      stroke(0,255,0, 150);
      fill(0,255,0,100);
    }
    ellipse(50+i*19, height/2,fft.getBand(i), fft.getBand(i));
  }
}

void stop()
{
  // always close Minim audio classes when you are done with them
  song.close();
  minim.stop();
 
  super.stop();
}

In the code above, we declare and play our sound file (note that it has to be saved in the data folder of your Processing sketch), and draw the 19 first bands of the sample rate. We draw circles of different sizes for each band (proportionate to their value), and alternate the colours : red, white, green.

If you run this Processing sketch as is, you’ll see a visualisation of your soundtrack.

2) Craft the carol singers
carols1
Paint 3 empty toilet rolls in different colours. Let them dry.

carols2
Once dry, put the hats on (I’ve re-used hats from the Innocent Big Knit, but you can knit your own, or make them out of felt). Paint a face right under the hat. Draw some sheet music for your singers.

carols3

3) Add some lights
So, now we’ve got a song playing and some singers; let there be light! To get Arduino and Processing talking we are going to use Serial communication again (see the project from the 4th of December for more details). And to manage the LEDs, I referred to the Arduino ShiftOut page and this other example. That’s 16 LEDs sorted, with only 3 pins used on the Arduino! (Be careful, though, wiring gets tricky!). And the 3 remaining LEDs will be declared as digital outputs in Arduino.

carols4

Let’s have a closer look, shall we?

First we’ve got to determine what value to send from our Processing sketch. I’ve decided to send the biggest value from our sample rate, therefore, at the end of the loop in the draw function, we have:

 bandValues[i] = fft.getBand(i);
    
    if(i == 18) {
      maxBand = max(bandValues);
      sendAndResetBand();
    }


We fill an array with the nineteen values, once the array is full, we determine which value is the biggest using max(), and we get ready to send the data over Serial.

void sendAndResetBand() {
 for(int i = 0; i< bandValues.length; i++){
  if(bandValues[i] == maxBand) {
   mainLight = i; 
  }
 }

 port.write(""+mainLight);
 port.write('\n');
 bandValues = new float[19];
 maxBand = 0;
}

We find out the index of the max value by looping through the array, and then send the number as a string over Serial (Serial port has been declared in the setup function). Once the value has been sent, we clear the array of values and the maximum value, that will be overridden in the next iteration of the draw function. That’s it for Processing, now let’s write code for Arduino:

String light = "";

//Pin connected to Pin 12 of 74HC595 (Latch)
int latchPin = 8;
//Pin connected to Pin 11 of 74HC595 (Clock)
int clockPin = 12;
//Pin connected to Pin 14 of 74HC595 (Data)
int dataPin = 11;

int whitePin = 9;
int greenPin = 10;
int redPin = 13;


int ledOn1[] = {1,2,4,8,16,32,64,128,0,0,0,0,0,0,0,0,0,0,0};
int ledOn2[] = {0,0,0,0, 0, 0, 0, 0,1,2,4,8,16,32,64,128,0,0,0};

int index = 0;
char charbuffer[20];

Declare the string (that will be incremented when reading the serial port), all the pins for the shift registers and LEDs, the arrays that correspond to the values to parse to the shift registers to light up an LED at a particular index, and some extra items that will help with serial communication.

void setup()
{
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  pinMode(whitePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(redPin, OUTPUT);
  
  while(!Serial) {
   return; 
  }
}


Open Serial and set all the light pins as outputs.

void loop()
{    
    checkSerial();
    delay(100);
    resetLights();
}


We need to check what comes through the Serial port and switch the LEDs that aren’t attached to the shift registers off (otherwise they’ll stay on).

void checkSerial() {
  while(Serial.available() > 0) {
    char inChar = Serial.read();
    
    if(inChar == '\n'){
      
      light.toCharArray(charbuffer, 20);
      index = atoi(charbuffer);
      
      if(index>=0 && index <19){
        registerWrite(index);
        if(index == 16){
          digitalWrite(whitePin, HIGH);
        }
       
        if(index ==17){
          digitalWrite(greenPin, HIGH);
         
        }
       
       if(index== 18) {
        digitalWrite(redPin, HIGH);
       } 
      }
      

      Serial.println(light);
      //command.toCharArray(inData, 20); 
      
      light = "";
    }
    
    else if(inChar !='\r'){
      light += inChar;
    }
    
  }
}


We read the string coming through the serial port and convert it to an integer. We then tell the shift register which light to switch on, and deal with the LEDs that aren’t on the shift register.

void registerWrite(int index) {
  digitalWrite(latchPin, LOW);
  // shift out the bits:
  shiftOut(dataPin, clockPin, MSBFIRST, ledOn2[index]); 
  shiftOut(dataPin, clockPin, MSBFIRST, ledOn1[index]);  

  //take the latch pin high so the LEDs will light up:
  digitalWrite(latchPin, HIGH);
}


Tell the shift register which LED to light on.

void resetLights() {
  digitalWrite(whitePin, LOW);
  digitalWrite(greenPin, LOW);
  digitalWrite(redPin, LOW);
}


Finally, reset the 3 LEDs that don’t belong to the shift registers (called in the loop function).

Enjoy a light an sound display! Christmas is getting closer!

Advertisements

One thought on “Christmas Carols

  1. Pingback: #NaughtyOrNice | 300 LEDs before Xmas

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s