Hello, My name is Turner. I am a rising senior at Colorado Academy. I have always loved building things and engineering as a whole but until now I did not have an opportunity to work on a more intense and official engineering project. My starter project was called the TV-B-Gone and my intensive project is a speaker system that does an FFT on the incoming audio signal and exports the information to two arduinos that `display the FFT on two LED matrices.
Third Milestone
In my third milestone I talk about my attempts to expand my project and remove my reliance on my computer. Previously I had to rely on my computer to do the FFT. I wanted my project to be more self-reliant and mobile so I began working on getting the program Processing to work on the Raspberry Pi 2. This posed many challenges as the Pi is not initially set up to be able to run Processing. I eventually got everything to work and even was able to establish communications with my arduinos. I know this because the data recive LEDs on the arduinos were on. Even though I was able to send the data to the Arduinos, nothing would show up on the LED matrices. This may be because the Pi outputs data in a different way than my computer and the Arduinos were not properly programmed to recieve that different data format. In the end… I know that it is not impossible to get a Raspberry Pi to control my project; It would simply take more time in order to ensure that everything is working properly and that the Arduinos are programmed to recive that data that the Pi is sending.
Second Milestone
For my second milestone I decided to talk about the technical part of my project. I use my computer to do a Fast Fourier Transform, or FFT, on an incoming audio signal. The purpose of the FFT is to change the time domain of the audio sin wave into a a graph with a frequency domain. The FFT does this by looking at the audio being given to it for short periods of time and uses a set of very complex equations to determine the equations for all of the simple sin graphs that, when added together, make the audio wave being analysed.
Here is my Processing code.
———————————————————————————————————-
import ddf.minim.analysis.*;
import ddf.minim.*;
import processing.serial.*;
Serial port1;
Serial port2;
Minim minim;
AudioInput in;
FFT fft;
int buffer_size = 4096;
float sample_rate = 200000;
int freq_width = 250; // <-O-> set the frequency range for each band over 400hz. larger bands will have less intensity per band. smaller bands would result in the overall range being limited
//arrays to hold the 64 bands’ data
int[] freq_array = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float[] freq_height = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void setup()
{
size(200, 200);
minim = new Minim(this);
port1 = new Serial(this, “COM11” , 115200); // <-O-> set baud rate and port for first RGB matrix
port2 = new Serial(this, “COM13” , 115200); // <-O-> set baud rate and port for second RGB matrix
in = minim.getLineIn(Minim.MONO,buffer_size,sample_rate);
// create an FFT object that has a time-domain buffer
// the same size as line-in’s sample buffer
fft = new FFT(in.bufferSize(), in.sampleRate());
// Tapered window important for log-domain display
fft.window(FFT.HAMMING);
}
void draw()
{
for(int k=0; k<64; k++){
freq_array[k] = 0;
}
// perform a forward FFT on the samples in input buffer
fft.forward(in.mix);
freq_height[0] = fft.calcAvg((float) 0, (float) 30);
freq_height[1] = fft.calcAvg((float) 31, (float) 60);
freq_height[2] = fft.calcAvg((float) 61, (float) 100);
freq_height[3] = fft.calcAvg((float) 101, (float) 150);
freq_height[4] = fft.calcAvg((float) 151, (float) 200);
freq_height[5] = fft.calcAvg((float) 201, (float) 250);
freq_height[6] = fft.calcAvg((float) 251, (float) 300);
freq_height[7] = fft.calcAvg((float) 301, (float) 350);
freq_height[8] = fft.calcAvg((float) 351, (float) 400);
for(int n = 9; n < 64; n++)
{
freq_height[n] = fft.calcAvg((float) (351+(freq_width*(n-9))), (float) (500+(freq_width*(n-9))));
}
freq_height[64] = (fft.calcAvg((float) 20, (float) 60));
// <-O-> Log scaling function. Feel free to adjust x and y
float x = 8;
float y = 3;
for(int j=0; j<64; j++){
freq_height[j] = freq_height[j]*(log(x)/y);
x = x + (x);
}
// Amplitude Ranges if else tree
for(int j=0; j<65; j++){
if (freq_height[j] < 2000 && freq_height[j] > 180){freq_array[j] = 16;}
else{ if (freq_height[j] <= 200 && freq_height[j] > 160){freq_array[j] = 15;}
else{ if (freq_height[j] <= 160 && freq_height[j] > 130){freq_array[j] = 14;}
else{ if (freq_height[j] <= 130 && freq_height[j] > 110){freq_array[j] = 13;}
else{ if (freq_height[j] <= 110 && freq_height[j] > 90){freq_array[j] = 12;}
else{ if (freq_height[j] <= 90 && freq_height[j] > 70){freq_array[j] = 11;}
else{ if (freq_height[j] <= 70 && freq_height[j] > 60){freq_array[j] = 10;}
else{ if (freq_height[j] <= 60 && freq_height[j] > 50){freq_array[j] = 9;}
else{ if (freq_height[j] <= 50 && freq_height[j] > 40){freq_array[j] = 8;}
else{ if (freq_height[j] <= 40 && freq_height[j] > 30){freq_array[j] = 7;}
else{ if (freq_height[j] <= 30 && freq_height[j] > 20){freq_array[j] = 6;}
else{ if (freq_height[j] <= 20 && freq_height[j] > 15){freq_array[j] = 5;}
else{ if (freq_height[j] <= 15 && freq_height[j] > 11){freq_array[j] = 4;}
else{ if (freq_height[j] <= 11 && freq_height[j] > 8){freq_array[j] = 3;}
else{ if (freq_height[j] <= 8 && freq_height[j] > 5){freq_array[j] = 2;}
else{ if (freq_height[j] <= 5 && freq_height[j] > 2){freq_array[j] = 1;}
else{ if (freq_height[j] <= 2 && freq_height[j] > 0){freq_array[j] = 0;}
}}}}}}}}}}}}}}}}}
// organize and send the data
String sta = “M”;
String aa = str(freq_array[0]);
String bb = str(freq_array[1]);
String cc = str(freq_array[2]);
String dd = str(freq_array[3]);
String ee = str(freq_array[4]);
String ff = str(freq_array[5]);
String gg = str(freq_array[6]);
String hh = str(freq_array[7]);
String ii = str(freq_array[8]);
String jj = str(freq_array[9]);
String kk = str(freq_array[10]);
String ll = str(freq_array[11]);
String mm = str(freq_array[12]);
String nn = str(freq_array[13]);
String oo = str(freq_array[14]);
String pp = str(freq_array[15]);
String qq = str(freq_array[16]);
String rr = str(freq_array[17]);
String ss = str(freq_array[18]);
String tt = str(freq_array[19]);
String uu = str(freq_array[20]);
String vv = str(freq_array[21]);
String ww = str(freq_array[22]);
String xx = str(freq_array[23]);
String yy = str(freq_array[24]);
String zz = str(freq_array[25]);
String aaa = str(freq_array[26]);
String bbb = str(freq_array[27]);
String ccc = str(freq_array[28]);
String ddd = str(freq_array[28]);
String eee = str(freq_array[30]);
String fff = str(freq_array[31]);
String xaa = str(freq_array[32]);
String xbb = str(freq_array[33]);
String xcc = str(freq_array[34]);
String xdd = str(freq_array[35]);
String xee = str(freq_array[36]);
String xff = str(freq_array[37]);
String xgg = str(freq_array[38]);
String xhh = str(freq_array[39]);
String xii = str(freq_array[40]);
String xjj = str(freq_array[41]);
String xkk = str(freq_array[42]);
String xll = str(freq_array[43]);
String xmm = str(freq_array[44]);
String xnn = str(freq_array[45]);
String xoo = str(freq_array[46]);
String xpp = str(freq_array[47]);
String xqq = str(freq_array[48]);
String xrr = str(freq_array[49]);
String xss = str(freq_array[50]);
String xtt = str(freq_array[51]);
String xuu = str(freq_array[52]);
String xvv = str(freq_array[53]);
String xww = str(freq_array[54]);
String xxx = str(freq_array[55]);
String xyy = str(freq_array[56]);
String xzz = str(freq_array[57]);
String xaaa = str(freq_array[58]);
String xbbb = str(freq_array[59]);
String xccc = str(freq_array[60]);
String xddd = str(freq_array[61]);
String xeee = str(freq_array[62]);
String xfff = str(freq_array[63]);
String com = “,”;
String newl = “\n”;
String send1 = sta + aa + com + bb + com + cc + com + dd + com + ee + com + ff + com + gg + com + hh + com + ii + com + jj + com + kk + com + ll + com + mm + com + nn + com + oo + com + pp + com + qq + com + rr + com + ss + com + tt + com + uu + com + vv + com + ww + com + xx + com + yy + com + zz + com + aaa + com + bbb + com + ccc + com + ddd + com + eee + com + fff + newl;
port1.write(send1);
String send2 = sta + xaa + com + xbb + com + xcc + com + xdd + com + xee + com + xff + com + xgg + com + xhh + com + xii + com + xjj + com + xkk + com + xll + com + xmm + com + xnn + com + xoo + com + xpp + com + xqq + com + xrr + com + xss + com + xtt + com + xuu + com + xvv + com + xww + com + xxx + com + xyy + com + xzz + com + xaaa + com + xbbb + com + xccc + com + xddd + com + xeee + com + xfff + newl;
port2.write(send2);
}
void stop()
{
// always close Minim audio classes when you finish with them
in.close();
minim.stop();
super.stop();
}
———————————————————————————————————-
First Milestone
My first milestone is an assembled and working spectrum analyzer. The electronic components of the project include two Arduino redboards, two RGB LED matrices, and my computer to run the processing FFT. The FFT and the processing code used to do it are explained in more detail in my second milestone video. I have audio playing into my computer, Processing does an FFT on the audio, exports the data to the two Arduinos and the arduinos represent the data on the two RGB LED matrices. I also have two speakers to play the audio. In addition to the electronic components i designed and built an acrylic case to house the electronic components. I also designed a casing for the Arduinos in Autodesk Inventor and printed it with the 3D printer.
Here is the code that is uploaded onto both Arduinos.
———————————————————————————————————-
#include <avr/pgmspace.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library
#define CLK 8 // MUST be on PORTB!
#define LAT A3
#define OE 9
#define A A0
#define B A1
#define C A2
// Last parameter = ‘true’ enables double-buffering, for flicker-free,
// buttery smooth animation. Note that NOTHING WILL SHOW ON THE DISPLAY
// until the first call to swapBuffers(). This is normal.
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, true);
// <-O-> the values after “matrix.Color333” represent the RGB values with 7 being the brightest value for that particular colour
void lightcolumns(int rownum, int amplitude)
{
if(amplitude>15) // <-O-> set the threshold for the band to turn red
{
for( int y = 0; y < amplitude; y++){
matrix.drawPixel(rownum, y, matrix.Color333(255, 0, 0));
}
for(int y = amplitude; y <16; y++)
{
matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));
}
}
else if(amplitude>13) // <-O-> set the threshold for the band to turn yellow
{
for( int y = 0; y < amplitude; y++){
matrix.drawPixel(rownum, y, matrix.Color333(255, 255, 0));
}
for(int y = amplitude; y < 16; y++)
{
matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));
}
}
else if(amplitude>9) // <-O-> set the threshold for the band to turn green
{
for( int y = 0; y < amplitude; y++){
matrix.drawPixel(rownum, y, matrix.Color333(0, 255, 0));
}
for(int y = amplitude; y < 16; y++)
{
matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));
}
}
else
{
for( int y = 0; y < amplitude; y++){
matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 255));
}
for(int y = amplitude; y < 16; y++)
{
matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));
}
}
}
void setup()
{
matrix.begin();
Serial.begin(115200);
delay(1000);
}
void loop() {
int bla = digitalRead(12);
if(Serial.read() == (‘M’))
{
int led1 = Serial.parseInt();
int led2 = Serial.parseInt();
int led3 = Serial.parseInt();
int led4 = Serial.parseInt();
int led5 = Serial.parseInt();
int led6 = Serial.parseInt();
int led7 = Serial.parseInt();
int led8 = Serial.parseInt();
int led9 = Serial.parseInt();
int led10 = Serial.parseInt();
int led11 = Serial.parseInt();
int led12 = Serial.parseInt();
int led13 = Serial.parseInt();
int led14 = Serial.parseInt();
int led15 = Serial.parseInt();
int led16 = Serial.parseInt();
int led17 = Serial.parseInt();
int led18 = Serial.parseInt();
int led19 = Serial.parseInt();
int led20 = Serial.parseInt();
int led21 = Serial.parseInt();
int led22 = Serial.parseInt();
int led23 = Serial.parseInt();
int led24 = Serial.parseInt();
int led25 = Serial.parseInt();
int led26 = Serial.parseInt();
int led27 = Serial.parseInt();
int led28 = Serial.parseInt();
int led29 = Serial.parseInt();
int led30 = Serial.parseInt();
int led31 = Serial.parseInt();
int led32 = Serial.parseInt();
if (Serial.read() == ‘\n’)
{
lightcolumns(31, led1);
lightcolumns(30, led2);
lightcolumns(29, led3);
lightcolumns(28, led4);
lightcolumns(27, led5);
lightcolumns(26, led6);
lightcolumns(25, led7);
lightcolumns(24, led8);
lightcolumns(23, led9);
lightcolumns(22, led10);
lightcolumns(21, led11);
lightcolumns(20, led12);
lightcolumns(19, led13);
lightcolumns(18, led14);
lightcolumns(17, led15);
lightcolumns(16, led16);
lightcolumns(15, led17);
lightcolumns(14, led18);
lightcolumns(13, led19);
lightcolumns(12, led20);
lightcolumns(11, led21);
lightcolumns(10, led22);
lightcolumns(9, led23);
lightcolumns(8, led24);
lightcolumns(7, led25);
lightcolumns(6, led26);
lightcolumns(5, led27);
lightcolumns(4, led28);
lightcolumns(3, led29);
lightcolumns(2, led30);
lightcolumns(1, led31);
lightcolumns(0, led32);
matrix.swapBuffers(false);
}
}
}
———————————————————————————————————-
Starter Project
The TV-B-Gone is a small handheld device that, upon the click of a button, sends out a large combination IR signals. Those IR signals are a combination of many “turn off tv” commands. The TV-B-Gone is made of many parts (described in more detail in the video). Some of the more noticeable components are the button which tells the program to begin sending out IR codes. The LEDs, two clear and two with a blue-ish tint are the IR leds. Right behind the LEDs are a row of transistors. These transistors allow the IC to controll them with the low current that it runs on but still supply the full current to the LEDs that they need to run. Near the center of the board is the IC. This is the component that contains all of the information about the IR patterns.