Polish & Present Submit Assignment: William Schwartz

for this week I did not have a ton to do. I did all the assembly last week, so this week all I had to do was program the teensy, and do the audio analysis.

using the teensy audio library made things pretty easy, I am still doing some minor adjustments, but for the most part the project is completed there is still some averaging and little tweaks to make but I am very pleased with the project

https://youtu.be/JU8OloREU7E

https://youtu.be/N2PDXgPbCHg

these are two videos of the head in operation 🙂

 

here is my current Arduino code:

#include <Adafruit_NeoPixel.h>
#include <Audio.h>
#include <Wire.h>
#include <SerialFlash.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

void setLedColorHSV(byte h, byte s, byte v);

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputAnalog adc1(A0); // ADC0 input
AudioAnalyzeFFT1024 myFFT;

// Connect either the live input or synthesized sine wave
AudioConnection patchCord1(adc1, 0, myFFT, 0);

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN 5
const int POWER_LED_PIN = 13; // Output pin for power LED (pin 13 to use Teensy 3.0's onboard LED).
byte h;
byte s;
byte v;
byte RedLight;
byte GreenLight;
byte BlueLight;
int currentlight;

float avg_fft[512]; 
int avg_fft_cout = 1;

#define NUMPIXELS 41
#define NUMCELLS 25
int cells[NUMCELLS] = {3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 3, 4, 3, 2};

// ----------- ALL THE DIFFERENT MAPPINGS THAT I HAVE MADE!!! ---------------------------------------
// even maping base at the neck
int mapping[NUMCELLS] = {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0};
// random mapping
//int mapping[NUMCELLS] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0};
// random mapping base at the left ear
//int mapping[NUMCELLS] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 5, 5, 5};
// random mapping base in the neck
//int mapping[NUMCELLS] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 0, 5, 5, 5, 5, 1, 2, 3};

// --------------------------------------------------


#define freq_bands 6

// defines the frequency ranges for each band 
int freq_high[freq_bands] = {90, 40, 30, 20, 12, 6};
int freq_low[freq_bands] = {40, 31, 21, 13, 6, 1};

// stores the results of going through each band
int freq_max_bin[freq_bands] = {};
float freq_max_amp[freq_bands] = {};
float prev_freq_max_amp[freq_bands] = {};
byte freq_hue[freq_bands] = {};
byte prev_freq_hue[freq_bands] = {};

int top_freq = 0;

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
// Turn on the power indicator LED.
pinMode(POWER_LED_PIN, OUTPUT);
digitalWrite(POWER_LED_PIN, HIGH);
randomSeed(10);

pixels.begin(); // This initializes the NeoPixel library.
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Configure the window algorithm to use
myFFT.windowFunction(AudioWindowHanning1024);
//myFFT.windowFunction(NULL);
}

void loop() {
float n;
int i;
int fft_count = 0;

delay(10);

// ________________________________________________________ 
// copy initial sample
if (myFFT.available()) {
for (i = 0; i < 512; i++) {
avg_fft[i] = myFFT.read(i);
}
// averge other samples
while (fft_count < avg_fft_cout) {
if (myFFT.available()) {
for (i = 0; i < 512; i++) {
avg_fft[i] = (avg_fft[i] + myFFT.read(i))/2.0;
}
fft_count++;
}
}
}
// ________________________________________________________

int f; // used as intex for band we are in
int bin = 0; // hold on to the current bin

for (f = 0; f < freq_bands; f++) {

freq_max_amp[f] = 0;
bin = 0;

for (i=freq_high[f]; i > freq_low[f]; i--) {
n = avg_fft[i];
if ( n > 0.01) {
freq_max_amp[f] = max(freq_max_amp[f], n);
// recently added might make things worse? we will see...
//if (freq_max_amp[f] == n) {
bin = i;
//}
}
}

if (bin != 0 && bin != freq_max_bin[f]){
freq_max_bin[f] = bin;
// TODO: the bins are off!! bin 5 should be RED!! currently bin 0 is red
freq_hue[f] = 252 - ((f+1%6)*42 + random((freq_max_bin[f]-freq_low[f])*(42/(freq_high[f]-freq_low[f]))));

}

if (freq_max_amp[f] == 0){
freq_max_bin[f] = 0;
}

// Serial.println();
// Serial.print((255/f));
// Serial.println();
// freq_hue[f] = (255/f);

// set the hue to the bin hue
if (freq_max_bin[f] != 0){
Serial.println();
Serial.print("BAND ");
Serial.print(f);
Serial.print(" amplitude is ");
Serial.print(freq_max_amp[f], 20);
Serial.print("the bin is ");
Serial.print(freq_max_bin[f]);
}
}

// PUSH ALL THE DATA TO THE LIGHTS!!!
// ________________________________________________________ 
currentlight = 0;
for(int i=0;i<NUMCELLS;i++) {

h = freq_hue[mapping[i]];
if (h != 0 && prev_freq_hue[mapping[i]] != 0) {
h = (h - prev_freq_hue[mapping[i]])/3 + prev_freq_hue[mapping[i]];
}
prev_freq_hue[mapping[i]] = h;

s = 255;
if (freq_max_amp[mapping[i]] != 0.0){
// v = (int)(freq_max_amp[mapping[i]]*1000.0);
v = (int)(freq_max_amp[mapping[i]]*1000.0);
v = (int) abs(v - prev_freq_max_amp[mapping[i]])/3 + prev_freq_max_amp[mapping[i]];
top_freq = max(top_freq, v);
// Serial.println();
// Serial.print(top_freq);
// Serial.println();
prev_freq_max_amp[mapping[i]] = v/1.1-1;
} else {
//v = ((int)(prev_freq_max_amp[mapping[i]]*1000.0))/2-1;
v = prev_freq_max_amp[mapping[i]];
prev_freq_max_amp[mapping[i]] = (int) prev_freq_max_amp[mapping[i]]/1.2;
if (v != 0) {
Serial.println();
Serial.print(prev_freq_max_amp[mapping[i]]);
Serial.println();
}

}
setLedColorHSV(h,s,v);
for (int j=0;j<cells[i];j++) {
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(currentlight, pixels.Color(RedLight, GreenLight, BlueLight));
currentlight = currentlight + 1;
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
// ________________________________________________________


}

void setLedColorHSV(byte h, byte s, byte v) {
// this is the algorithm to convert from RGB to HSV
h = (h * 192) / 256; // 0..191
unsigned int i = h / 32; // We want a value of 0 thru 5
unsigned int f = (h % 32) * 8; // 'fractional' part of 'i' 0..248 in jumps

unsigned int sInv = 255 - s; // 0 -> 0xff, 0xff -> 0
unsigned int fInv = 255 - f; // 0 -> 0xff, 0xff -> 0
byte pv = v * sInv / 256; // pv will be in range 0 - 255
byte qv = v * (256 - s * f / 256) / 256;
byte tv = v * (256 - s * fInv / 256) / 256;

switch (i) {
case 0:
RedLight = v;
GreenLight = tv;
BlueLight = pv;
break;
case 1:
RedLight = qv;
GreenLight = v;
BlueLight = pv;
break;
case 2:
RedLight = pv;
GreenLight = v;
BlueLight = tv;
break;
case 3:
RedLight = pv;
GreenLight = qv;
BlueLight = v;
break;
case 4:
RedLight = tv;
GreenLight = pv;
BlueLight = v;
break;
case 5:
RedLight = v;
GreenLight = pv;
BlueLight = qv;
break;
}
}





Leave a Reply