HueHarmony2.ino
Dec 4th, 2017 by patarf
*The following code is concatenated and altered code from http://www.instructables.com/id/Arduino-Audio-Input/, http://www.instructables.com/id/Arduino-Frequency-Detection/, http://www.instructables.com/id/Arduino-Guitar-Tuner/, https://nootropicdesign.com/projectlab/2013/07/05/audio-sampler/
/*From http://www.instructables.com/id/Arduino-Audio-Input/,
http://www.instructables.com/id/Arduino-Frequency-Detection/,
and http://www.instructables.com/id/Arduino-Guitar-Tuner/
Using Audio Hacker, instead of separate components
Using electret condenser microphone, or Audio Hacker input
*/
#include <AudioHacker.h>
//clipping indicator variables
boolean clipping = 0;//0 = not clipping, 1 = currently clipping
//data storage variables
byte newData = 0;
byte prevData = 0;
unsigned int time = 0;//keeps time and sends values to store in timer[] occasionally
int timer[10];//storage for timing events
int slope[10];//storage for slope of events
unsigned int totalTimer;//used to calculate period
unsigned int period;//storage for period of wave
byte index = 0;//current storage index
float frequency;//storage for frequency calculations
int maxSlope = 0;//used to calculate max slope as trigger point
int newSlope;//storage for incoming slope data
//variables for decided whether you have a match
byte noMatch = 0;//counts how many non-matches you’ve received to reset variables if it’s been too long
byte slopeTol = 2;//slope tolerance- adjust this if you need
int timerTol = 15;//timer tolerance- adjust this if you need
//variables for amp detection
unsigned int ampTimer = 0;
byte maxAmp = 0;
byte checkMaxAmp;
byte ampThreshold = 30;//raise if you have a very noisy signal
//finds frequency, compares to sound, outputs more accurate “correct” frequency
//variables for tuning
int correctFrequency;//the correct frequency for the string being played
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//only takes one input value, 9600 bits per second
//AudioHacker.begin();
//pinMode(13,OUTPUT);//led indicator pin
//pinMode(12,OUTPUT);//output pin
pinMode(A0, INPUT);
cli();//disable interrupts
//set up continuous sampling of analog pin 0 at 38.5kHz
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enable auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
}
ISR(ADC_vect) {//when new ADC value ready
//PORTB &= B11101111;//set pin 12 low
prevData = newData;//store previous value
newData = ADCH;//get value from A0
if (prevData < 127 && newData >= 127){//if increasing and crossing midpoint
newSlope = newData – prevData;//calculate slope
if (abs(newSlope-maxSlope)<slopeTol){//if slopes are =
//record new data and reset time
slope[index] = newSlope;
timer[index] = time;
time = 0;
if (index == 0){//new max slope just reset
//PORTB |= B00010000;//set pin 12 high
noMatch = 0;
index++;//increment index
}
else if (abs(timer[0]-timer[index])<timerTol && abs(slope[0]-newSlope)<slopeTol){//if timer duration and slopes match
//sum timer values
totalTimer = 0;
for (byte i=0;i<index;i++){
totalTimer+=timer[i];
}
period = totalTimer;//set period
//reset new zero index values to compare with
timer[0] = timer[index];
slope[0] = slope[index];
index = 1;//set index to 1
//PORTB |= B00010000;//set pin 12 high
noMatch = 0;
}
else{//crossing midpoint but not match
index++;//increment index
if (index > 9){
reset();
}
}
}
else if (newSlope>maxSlope){//if new slope is much larger than max slope
maxSlope = newSlope;
time = 0;//reset clock
noMatch = 0;
index = 0;//reset index
}
else{//slope not steep enough
noMatch++;//increment no match counter
if (noMatch>9){
reset();
}
}
}
if (newData == 0 || newData == 1023){//if clipping
//PORTB |= B00100000;//set pin 13 high- turn on clipping indicator led
clipping = 1;//currently clipping
}
time++;//increment timer at rate of 38.5kHz
ampTimer++;//increment amplitude timer
if (abs(127-ADCH)>maxAmp){
maxAmp = abs(127-ADCH);
}
if (ampTimer==1000){
ampTimer = 0;
checkMaxAmp = maxAmp;
maxAmp = 0;
}
}
void reset(){//clea out some variables
index = 0;//reset index
noMatch = 0;//reset match couner
maxSlope = 0;//reset slope
}
//My code to incorporate
/*
//Frequency values of 5 basic chords in Hz
arrChordG = (98.0, 123.5, 146.8, 196.0, 246.9, 392.0) As Decimal //6 strings strummed
decChordG = ? As Decimal //new calculated frequency
//or if these frequencies show up in this order
arrChordD = (146.8, 220.0, 293.7, 370.0) As Decimal //4 strings strummed
decChordD = ? As Decimal //new calculated frequency
arrChordAm = (110.0, 164.8, 220.0, 261.6, 329.6) //5 strings strummed
decChordAm = ? As Decimal //new calculated frequency
arrChordC = (130.8, 164.8, 196.0, 261.6, 329.6) //5 strings strummed
decChordC = ? As Decimal //new calculated frequency
arrChordEm = (82.4, 123.5, 164.8, 196.0, 246.9, 329.6) //6 strings strummed
decChordEm = ? As Decimal //new calculated frequency
//Input as frequency in Hz
decInput = 0 As Decimal
}
*/
void checkClipping(){//manage clipping indicator LED
if (clipping){//if currently clipping
//PORTB &= B11011111;//turn off clipping indicator led
clipping = 0;
}
}
//find correct frequency from input frequency
//may need to tweak ranges
void stringCheck(){
if(frequency<80.0){
Serial.println(“Below range.”);
}
if(frequency>80.0&frequency<85.0){
correctFrequency = 82.4;
Serial.print(“E 6th string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>85.0&frequency<90.0){
correctFrequency = 87.3;
Serial.print(“F 6th string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>90.0&frequency<95.0){
correctFrequency = 92.5;
Serial.print(“F# 6th string, 2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>95.0&frequency<100.0){
correctFrequency = 98.0;
Serial.print(“G 6th string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>100.0&frequency<105.0){
correctFrequency = 103.8;
Serial.print(“G# 6th string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>105.0&frequency<113.0){
correctFrequency = 110.0;
Serial.print(“A 5th string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>113.0&frequency<120.0){
correctFrequency = 116.5;
Serial.print(“A# 5th string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>120.0&frequency<127.0){
correctFrequency = 123.5;
Serial.print(“B 5th string, 2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>127.0&frequency<135.0){
correctFrequency = 130.8;
Serial.print(“c 5th string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>135.0&frequency<142.0){
correctFrequency = 138.6;
Serial.print(“c# 5th string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>142.0&frequency<150.0){
correctFrequency = 146.8;
Serial.print(“d 4th string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>150.0&frequency<160.0){
correctFrequency = 155.6;
Serial.print(“d# 4th string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>160.0&frequency<170.0){
correctFrequency = 164.8;
Serial.print(“e 4th string, 2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>170.0&frequency<180.0){
correctFrequency = 174.6;
Serial.print(“f 4th string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>180.0&frequency<190.0){
correctFrequency = 185.0;
Serial.print(“f# 4th string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>190.0&frequency<200.0){
correctFrequency = 196.0;
Serial.print(“g 3rd string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>200.0&frequency<214.0){
correctFrequency = 207.7;
Serial.print(“g# 3rd string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>214.0&frequency<226.0){
correctFrequency = 220.0;
Serial.print(“a 3rd string, 2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>226.0&frequency<240.0){
correctFrequency = 233.1;
Serial.print(“a# 3rd string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>240.0&frequency<250.0){
correctFrequency = 246.9;
Serial.print(“b 3rd string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
//is this wrong?
if(frequency>250.0&frequency<260.0){
correctFrequency = 255.0;
Serial.print(“b#? 255.0 is not right? 2nd string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
//is this wrong?
if(frequency>260.0&frequency<270.0){
correctFrequency = 261.6;
Serial.print(“c? is the other one capital C? 2nd string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>270.0&frequency<284.0){
correctFrequency = 277.2;
Serial.print(“c#’ 2nd string,2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>284.0&frequency<300.0){
correctFrequency = 293.7;
Serial.print(“d’ 2nd string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>300.0&frequency<320.0){
correctFrequency = 311.1;
Serial.print(“d#’ 2nd string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>320.0&frequency<340.0){
correctFrequency = 329.6;
Serial.print(“e’ 1st string, open “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>340.0&frequency<360.0){
correctFrequency = 349.2;
Serial.print(“f’ 1st string, 1st fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>360.0&frequency<381.0){
correctFrequency = 370.0;
Serial.print(“f#’ 1st string, 2nd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>381.0&frequency<400.0){
correctFrequency = 392.0;
Serial.print(“g’ 1st string, 3rd fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>400.0&frequency<425.0){
correctFrequency = 415.3;
Serial.print(“g#’ 1st string, 4th fret “);
Serial.print(correctFrequency);
Serial.println(” Hz”);
}
if(frequency>425.0){
Serial.println(“Above range.”);
}
}
void loop() {
// put your main code here, to run repeatedly:
checkClipping();
if (checkMaxAmp>ampThreshold){
frequency = 38462/float(period);//calculate frequency timer rate/period
//print results
Serial.print(“Input frequency: “);
Serial.print(frequency);
Serial.print(” Hz “);
stringCheck();//hear frequency, find correct frequency
}
delay(100);//in milliseconds, delete this if you want
//do other stuff here (incorporate chord checking)
/*
//receive input
temporarily store decInput
compare decInput to chords
if decInput = decChordG then
Serial.print(imgChordG); //images with all info?
else if decInput = decChordD then
Serial.print(imgChordD);
else if decInput = decChordAm then
Serial.print(imgChordAm);
else if decInput = decChordC then
Serial.print(imgChordC);
else if decInput = decChordEm then
Serial.print(imgChordEm);
End if
*/
//*Low pass filter. For <70 and >500
}