THE FIRST TUTORIAL ON HOW TO USE A FULLY INDEPENDENT AUDIO SPECTRUM ANALYZER (NO COMPUTER NEEDED)

Behold, for those of you who want to customize your project on the first day, you have came to the right page.

Name: Benjamin Chen

School: Homestead High School

Area of Interest: Computer Science or anything that makes money and doesn’t require much studying

Grade: Rising senior

Demo Night

Third Milestone

I’ve learned a lot through Bluestamp: fft, wiring, and coding. It was pretty fun.

During the second week, I didn’t get my microphone and I tried make my arduino do most of the math. However, for some reason, it would never work properly. I’ve also tried adding in various modes, with mode 2 working somewhat well and mode 3 simply bugging out.

CAUTION: If you’re here to just copy and paste my code on the first day to get your basic project working, you’re missing out on the experience of debugging. However, if you want to start customizing on your first day and create more advanced projects, that is a good goal (although your Bluestamp instructor might not like it). When I explain how everything works in the top video, I’m not too sure of what I’m talking about. Anyway, just remember that the number of bands is like the frame rate. The higher the frame rate, the better the experience you will have. Perhaps the line that separates the bands is horizontal, not vertical. It might make more sense that way because the first bands corresponds to the lower frequencies, while the latter bands corresponds to the higher frequencies. That, I know for certain. Like you, I’m only a highschooler who got his information online. I don’t even if I separated the bands correctly. However, this is enough information to get you started.

Arduino code for milestone three
Arduino code:

include <Adafruit_NeoMatrix.h>
include <Adafruit_GFX.h>
include <Adafruit_NeoPixel.h>
define PIN 6
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(32, 8, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800);
void draw(int column, int amplitude);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);
void runMode1();
void runMode2();
void light(int index);

boolean newData = false;
int mode;

void setup() {
// put your setup code here, to run once:
matrix.begin();
matrix.setBrightness(5);
matrix.show();
Serial.begin(115200);
}
void loop() {
//if (Serial.available() > 0) {
//String input = Serial.read();
//if (Serial.read() == "w")
//runMode1();
//else if (Serial.read() == "e")
runMode2();
//}

}
void runMode2() {
//Serial.println("hi");
char receivedChars[5];
int count = 0;
int numOfDigits = 1; //how many digits make up a column
int index;
while (Serial.available() > 0 && newData == false) {
int input = Serial.read();
if (input == 'q') {
receivedChars[count] = input;
}
else if (input == '>')
newData = true;
else
receivedChars[count] = input;
count++;
}
newData = false;

if (receivedChars[0] = 'q') {
numOfDigits++;
if (receivedChars[1] = 'q')
numOfDigits++;
}

Serial.println(numOfDigits);

if (numOfDigits == 1) {
index = receivedChars[2];
Serial.println("hi");
} else if (numOfDigits == 2) {
index = atoi(receivedChars[1]) * 10 + atoi(receivedChars[2]);
Serial.println("hi");
} else if (numOfDigits == 3) {
index = atoi(receivedChars[0]) * 100 + atoi(receivedChars[1] * 10 + atoi(receivedChars[2]));

}
int value = receivedChars[3];

//Serial.println(index);

if (value == 8)
light(index);
else if (value == 7)
light(index);
else if (value == 6)
light(index);
else if (value == 5)
light(index);
else if (value == 4)
light(index);
else if (value == 3)
light(index);
else if (value == 2)
light(index);
else if (value == 1)
light(index);
else if (value == 0)
light(index);
}
void runMode1() {
Serial.println("hi");
char receivedChars[4];
int count = 0;
boolean singleDigit = false;
int column;
while (Serial.available() > 0 && newData == false) {
int input = Serial.read();
if (input == 'q') {
singleDigit = true;
receivedChars[count] = input;
}
else if (input == '>')
newData = true;
else
receivedChars[count] = input;
count++;
}
newData = false;
if (!singleDigit) {
column = receivedChars[1];
} else {
column = atoi(receivedChars[0]) * 10 + atoi(receivedChars[1]);
}
int value = receivedChars[2];
if (value == 8)
draw(column, 8);
else if (value == 7)
draw(column, 7);
else if (value == 6)
draw(column, 6);
else if (value == 5)
draw(column, 5);
else if (value == 4)
draw(column, 4);
else if (value == 3)
draw(column, 3);
else if (value == 2)
draw(column, 2);
else if (value == 1)
draw(column, 1);
else if (value == 0)
draw(column, 0);
}

void draw(int column, int amplitude) {
uint32_t color;
int rgb = int(255 - column * 7);
color = matrix.Color(255, rgb, rgb);
//color = RED;
matrix.drawLine(column, 0, column, amplitude, color);
matrix.show();
matrix.drawLine(column, 0, column, amplitude, matrix.Color(0, 0, 0));
}

void light(int index) {
matrix.setPixelColor(index, matrix.Color(255, 0, 0));
matrix.show();
delay(100);
}
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);

Second Milestone

Coding was harder the putting the hardware together. I used Processing to communicate with my Arduino. I used the Processing FFT class to analyze the sound. Sending data to the Arduino was the hardest part. I used various methods, from sending integers, strings, and chars. I found that sending chars was the easiest way to communicate with the Arduino.

Arduino code for milestone two

include <Adafruit_NeoMatrix.h>
include <Adafruit_GFX.h>
include <Keypad.h>
include “fix_fft.h”

define PIN 2

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(32, 8, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800);
//Adafruit_SSD1306 display(4);

void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);
void mode1();
void mode2();
void mode3();
void mode4();

byte mode;
byte brightness = 20;
char keys[4][4] = {{‘1’, ‘2’, ‘3’, ‘A’}, {‘4’, ‘5’, ‘6’, ‘B’}, {‘7’, ‘8’, ‘9’, ‘C’}, {‘*’, ‘0’, ‘#’, ‘D’}};
byte lights[8][32];
byte rowPins[4] = {3, 4, 5, 6};
byte colPins[4] = {7, 8, 9, 10};
boolean start = false;
char im[128], data[128];
int i = 0, val;
byte colorScheme = 0;
//byte pixelCount = 0;

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, 4, 4);

void setup() {
// put your setup code here, to run once:
matrix.begin();
matrix.show();
matrix.setBrightness(5);
Serial.begin(115200);
}
void loop() {

//int j = 31;
char key = keypad.getKey();
if (key == ‘1’)
mode = 1;
else if (key == ‘2’)
mode = 2;
else if (key == ‘3’)
mode = 3;
else if (key == ‘4’)
mode = 4;
else if (key == ‘A’)
brightness++;
else if (key == ‘B’) {
if (brightness > 0)
brightness–;
}
else if (key == ‘C’) {
if (colorScheme < 5)
colorScheme++;
}
else if (key == ‘D’)
if (colorScheme > 0)
colorScheme–;

matrix.setBrightness(brightness);

for (i = 0; i < 128; i++) {
val = analogRead(A0);
data[i] = val;
};

fix_fft(data, im, 7, 0);

//mode1();

if (mode == 1)
mode1();
else if (mode == 2)
mode2();
else if (mode == 3)
mode3();
else if (mode == 4)
mode4();

}

void mode1() {
uint32_t color;

int columns[32];

for (int i = 0; i < 32; i++) {
int total = 0;
for (int j = 0; j < i + 4; j++) {
total += data[i + j];
}
columns[i] = int (total / 4);
}

if (colorScheme == 0)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(255, 63 + i * 6, 63));
else if (colorScheme == 1)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(255 – i * 6, 255, 63));
else if (colorScheme == 2)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(63, 255, 63 + i * 6));
else if (colorScheme == 3)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(63, 255 – i * 6, 255));
else if (colorScheme == 4)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(63 + i * 6, 63, 255));
else if (colorScheme == 5)
for (int i = 0; i < 32; i++)
matrix.drawLine(i, 0, i, data[i], matrix.Color(255, 63, 255 – i * 6));

matrix.show();

matrix.fillScreen(matrix.Color(0, 0, 0));
}

void mode2() {
uint32_t color; //there are 4 boxes

for (byte i = 0; i < 128; i++) {
byte total;
for (byte k = 96; k < 128; k++)
total += data[k];
byte average = total / 32;

byte total2;
for (byte k = 64; k < 96; k++)
total2 += data[k];
byte average2 = total / 32;

byte total3;
for (byte k = 32; k < 64; k++)
total3 += data[k];
byte average3 = total / 32;

byte total4;
for (byte k = 0; k < 32; k++)
total4 += data[k];
byte average4 = total / 32;

if (average > 1) {
if (i >= 96 && average == 7) {
color = matrix.Color(200, 193, 43);
matrix.drawLine(1, 0, 30, 0, color); //bottom
matrix.drawLine(1, 7, 30, 7, color); //top
matrix.drawLine(0, 0, 0, 7, color); //left
matrix.drawLine(31, 0, 31, 7, color); //right
matrix.show();
}
if (i >= 64 && average2 == 7) {
color = matrix.Color(255, 124, 0);
matrix.drawLine(1, 1, 1, 6, color); //left inner 1
matrix.drawLine(30, 1, 30, 6, color); // right inner 1
matrix.drawLine(2, 1, 29, 1, color); //bottom inner 1
matrix.drawLine(2, 6, 29, 6, color); //top inner 1
matrix.show();

}
if (i >= 32 && average3 == 7) {
color = matrix.Color(255, 149, 0);
matrix.drawLine(2, 2, 2, 5, color); //left inner 2
matrix.drawLine(29, 2, 29, 5, color); //right inner 2
matrix.drawLine(3, 2, 28, 2, color); //bottom inner 2
matrix.drawLine(3, 5, 28, 5, color); //top inner 2
matrix.show();

}
if (i >= 0 && average4 == 7) {
color = matrix.Color(239, 0, 0);
matrix.drawLine(3, 3, 3, 4, color); //left inner 3
matrix.drawLine(28, 3, 28, 4, color); //right inner 3
matrix.drawLine(4, 3, 27, 3, color); //bottom inner 3
matrix.drawLine(4, 4, 27, 4, color); //top inner 3
matrix.show();
}
}
matrix.fillScreen(matrix.Color(0, 0, 0));
}
}

void mode3() {
uint32_t color;

for (byte i = 0; i < 128; i++) { //takes data
int amp = 0;

if (data[i] > 5)
amp = 4; //red
else if (data[i] > 3)
amp = 3; //yellow
else if (data[i] > 2)
amp = 2; //green
else if (data[i] > 1)
amp = 1; //blue
//if (data[i] == 7)
//amp = 1;

if (i > 112)
lights[7][0] = amp;
if (i > 96)
lights[6][0] = amp;
if (i > 80)
lights[5][0] = amp;
if (i > 64)
lights[4][0] = amp;
if (i > 48)
lights[3][0] = amp;
if (i > 32)
lights[2][0] = amp;
if (i > 16)
lights[1][0] = amp;
if (i > 0)
lights[0][0] = amp;
}

for (byte i = 0; i < 8; i++) //draws data
for (byte j = 0; j < 32; j++) {
if (lights[i][j] == 1)
color = matrix.Color(0, 0, 255);
else if (lights[i][j] == 2)
color = matrix.Color(0, 255, 0);
else if (lights[i][j] == 3)
color = matrix.Color(255, 255, 0);
else if (lights[i][j] == 4)
color = matrix.Color(255, 0, 0);

if (lights[i][j] != 0) {
matrix.drawPixel(j, i, matrix.Color(255, 0, 0));
matrix.show();
}
}

matrix.fillScreen(matrix.Color(128, 0, 128));
}

void mode4() {
for (int i = 0; i < 64; i++)
matrix.drawLine(i / 2, 0, i / 2, data[i], matrix.Color(236, 28 + i * 3, 28));

matrix.show();

matrix.fillScreen(matrix.Color(0, 0, 0));
}
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);

Processing code for milestone two
Processing code:

import processing.serial.*;
import processing.sound.*;

AudioIn in;
FFT fft;
float[] spectrum = new float[512];
int column[] = new int[32];
boolean newData = false;
Serial port;
int mode = 1;

void setup() {
size(640, 360);
background(255);
fft = new FFT(this, 512);
in = new AudioIn(this, 0);
// start the Audio Input
in.start();
// patch the AudioIn
fft.input(in);
port = new Serial(this, "COM3", 115200);
}
void draw() {
fft.analyze(spectrum);
if (port.available() > 0) {
System.out.println(port.readStringUntil('\n'));
}

if (mode == 0) {
port.write("w");
for (int i = 0; i < 256; i++) {
double adjustedValue = spectrum[i] * 100000;
int columnNum = (int) (i/8);

if (columnNum < 10) {
port.write("q");
port.write(columnNum);
} else {
port.write(columnNum);
}

if (adjustedValue > 128) {
port.write(8);
} else if (adjustedValue > 64) {
port.write(7);
} else if (adjustedValue > 32) {
port.write(6);
} else if (adjustedValue > 16) {
port.write(5);
} else if (adjustedValue > 8) {
port.write(4);
} else if (adjustedValue > 4) {
port.write(3);
} else if (adjustedValue > 2) {
port.write(2);
} else if (adjustedValue > 1) {
port.write(1);
} else {
port.write(0);
}
port.write(">"); //end
}
} else {
//port.write("e");
int values[][] = new int[8][32];
for (int col = 0; col < 32; col++) {
for (int row = 0; row < 8; row++) {
values
[row][col] = col + (row * 32); } } for (int col = 0; col < 32; col++) { for (int row = 0; row < 8; row++) { //System.out.println(values[row][col]); port.write(values[row][col]); if (values[row][col] < 10) { port.write("q"); port.write("q"); port.write(values[row][col]); } else if (values[row][col] < 100) { String temp = values[row][col] + ""; port.write("q"); port.write(temp.charAt(0)); port.write(temp.charAt(1)); } else { String temp = values[row][col] + ""; port.write(temp.charAt(0)); port.write(temp.charAt(1)); port.write(temp.charAt(2)); } port.write(8); port.write(">"); } } /*for (int i = 0; i < 512; i++) { double adjustedValue = spectrum[i] * 10000000; if (adjustedValue > 0) for (int col = 0; col < 32; col++) { for (int row = 0; row < 8; row++) { if (values[row][col] * 2 == i) port.write(values[row][col]); if (adjustedValue > 128) { port.write(8); } else if (adjustedValue > 64) { port.write(7); } else if (adjustedValue > 32) { port.write(6); } else if (adjustedValue > 16) { port.write(5); } else if (adjustedValue > 8) { port.write(4); } else if (adjustedValue > 4) { port.write(3); } else if (adjustedValue > 2) { port.write(2); } else if (adjustedValue > 1) { port.write(1); } else { port.write(0); } port.write(">"); } } }*/ } }

First Milestone

MileStone 1

My first milestone was lighting up the LED matrix. I plugged in the 5V and GND directly to the Arduino. I then plugged the DIN into 6. Using the NeoPixel class. I then coded in the Arduino IDE to light up the board. The video shows how the class stores each individual LED.

Circuit Diagram

Circuit Diagram

circuit-sketch

For the 32×8 LED matrix, connect DIN to pin 2 and VCC (or VDD) to 5V. Please, if you’re wondering where to connect GND, use your brain.

Start typing and press Enter to search

Bluestamp Engineering