Thursday, 23 June 2016

Beat detection and a Dancing Robot Arm

This project is my personal favourite. For one , I learned something about music and the science used to process it. And also , through this project I was able to revisit and apply a lot of concepts that I had learned during the last semester but thought were useless. I listened to Queen's 'We Will Rock You' , a hundred times or so while working on this project. So much so that I can no longer tolerate it.
That aside , this project used a lot of components that I will each visit separately in this tutorial.

Feeding Audio into the Arduino

1.Sound is an analog signal that is stored and processed digitally in computers. We use an Arduino's  inbuilt ADC ( analog to digital converter) to read an audio signal. The ADC is built for a 0-5V range of values, that is , it can convert analog signals in this range into a corresponding digital value between 0 and 1023.
Music output from an MP3 or smart phones,however, will be in milli-volts. This raises the issue of not being able to use the entire resolution of the ADC. Thus , the input signal will have to be amplified. You can use an operational amplifier IC or use a simple transistor to do this. The circuit is very simple , you will just need a couple of capacitors and resistors. I however was too lazy to do this. I managed by maxing the volume from my laptop but that is not the proper solution.

2. An audio signal can have both positive and negative values of voltage.However , your tiny micro-controller's ADC is made for only positive value. You will have to make an offset circuit for that. What this offsetting circuit does is that it shifts the entire signal such that the bias value become the origin. For example if you provide a bias of 2.5 V , the signal value will oscillate about this value.

Here is how it is made :



The 22uF capacitor with the 10K resistor make a High Pass Filter. A high pass filter allows frequencies only above a certain value to pass.  This cutoff frequency is given by f=1/2*pi*R*C.
For this arrangement we see the value 0.7 Hz. Thus , the DC component is removed from the incoming signal.
The two 10K resistors make a voltage divider, creating a bias of 2.5V. This is connected to a 1K pull up resistor and a coupling capacitor , to reduce noise. This also makes a low pass filter.

3. This is fed into the ADC. At analog pin 0 or whichever you might choose.

Sampling and Processing
 
1.  We need to sample this input signal. Sampling mean recording amplitudes at regular intervals. This is how analog signals are read by computers. The issue is the analogRead() function only allows sampling a 8Khz which is very poor for Audio. Typical sampling rates for audio is 40Khz. However all hope is not lost. There is a way to change the ADC sampling rate by setting values for the four MUX that control the ADC.
Check this another blog post to understand how it is done :
http://yaab-arduino.blogspot.in/2015/02/fast-sampling-from-analog-input.html

2. That done , now we need to compute the FFT (Fast Fourier Transform) on the signal. What this does is that it converts the signal from time domain to frequency domain. What this means is that you can get amplitudes of different frequency ranges in your sound signal. Typical Bass frequency ranges from 50-200Hz. It is this that we are interested in. All drum kicks , snares and rhythm information is contained here. There are various optimizations of the FFT available for the arduino. The one I used is developed by Open Music Labs and can be downloaded from the link below :
http://wiki.openmusiclabs.com/wiki/ArduinoFFT
You will have to read a bit from their website to get a better grasp of using this library.


3.Now with the FFT done , we look for peaks/ increase in amplitudes in the lower frequency ranges. that is when a beat happens.Once we have that , rest is easy. Control Lights or Motors.

These might be useful :

http://dpeckett.com/beat-detection-on-the-arduino

http://www.arduinoos.com/2010/10/fast-fourier-transform-fft/

Finally here is the Video of my project in action :




The code :


#define LIN_OUT8 1 // use the Lin_OUT8 output function
#define FFT_N 16
#include <Servo.h>
#include <FFT.h> // include the library
int led=13;
Servo servo;
Servo servo1;// create servo object to control a servo
int j=1,l=1; //for changing direction
int sel=1; //variable to select one of the two servos
int pos =0;
int pos1=0;// variable to store the servo position
int k=0;
int flag=1;
int sum=0;
int sam=60;
void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01;
  pinMode(led, OUTPUT);  // turn off the digital input for adc0
  servo.attach(6);
  servo1.attach(10);
 
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 32 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i+1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_lin8(); // take the output of the fft
    sei();
   
    //for(int i=0;i<7;i++) // print FFT results
    //{
      //Serial.print(fft_lin_out8[i]);
      //Serial.print("   ");
    //}
    //Serial.println();
    k++;
    sum=sum+fft_lin_out8[0];
    servo.write(pos); // tell servo to go to position in variable 'pos'
    servo1.write(pos1);
    if(k==sam)
    {
       k=0;
       sum=sum/sam;
       Serial.println(sum);
     
       if (sum>10)
       {
                   
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    
         sel=-sel;
      
         if(flag==1) //  Dance sequencce
         { if(sel==1)
           {
                pos=pos+ (j*60);
                j=(-j);
             }
        
                 pos1=pos1+(l*40);
                 l=-l;
            
          }
        flag=0;
      
        }
        else
        {
          digitalWrite(led, LOW);
          flag=1;
        }
       sum=0;
    }
  

  }
}

Sunday, 19 June 2016

Raspberry Pi powered Smart Dustbin

Recently , with a team of students from Delhi University , DTU and IP , I was involved in building a raspberry pi based smart dustbin. This post has been long overdue.  We had built our first prototype in the month March. Since then, I have not been able to find time to update my blog.

This smart dustbin is an initiative to incentivize proper recycling practices.We, in India are at a break-point of a looming waste management crisis. This project is our small attempt to address the cause of Solid Waste Management.
  
When you put some waste object into this dustbin , it tries to determine what that object is. This is done through image processing algorithms. The machine has been programmed to accept only cans and PET bottles. If the object you put in was either of these , the machine will accept it and confirm with a detected message on the screen. This message is followed by a USSD code that can be used to recharge your phone or get a discount coupon on you mobile phone. We partnered with Favcy to handle our reward system. Favcy helps  brands gamify social market engagements and provide real world rewards against those engagements.


Here is a video of the prototype (it is a little slow , but we made it quick and awesome finally) :





The machine ready to be tested at metro station , malls and other public places.



We tested the machine at a few locations ,  to gauge the response of users.





                                                                   Check out:

                                                           http://weconvert.org/

Currently , we are in the process of building a second prototype, using the feedback we collected during the trial runs of the first machine.