Introduction: Automatic Guitar Tuner
Two things that I really like to do are: play guitar and tinker with my Arduino. I was very interested at the thought of this project, so I decided to do it. I am new to programming, so this was a real challenge to me!
This machine works with an electric guitar. It takes the electrical signal transmitted from the guitar and analyzes the code. It all starts with the Op Amp circuit. The circuit itself was designed by amandaghassaei, and I want to thank her for helping me get a running start on my project.
Here is the list of processes in a nutshell:
1. The string is picked, and the electrical signal is sent through the stereo cable, which carries the sound waves.
2. The female stereo adapter receives the sound waves and puts it into the Op Amp circuit.
3. The Op Amp circuit takes the sound waves and increases the amplitude, so that the Arduino can read it easily. It then sends the signal into the Arduino to be sampled.
4. The Arduino samples the frequency of the sound waves, and records it on the serial port so the user can see.
5. The Arduino looks at which direction the 6-way rotary switch is in, so that it can determine which string it is tuning.
6. The position of the rotary switch determines what the desired frequency is for the string to be at (with a margin of error of 2Hz)
7. If the String is not in tune, then the motor moves accordingly.
8. This process repeats until the string is tuned, then the user moves on to the next string.

Participated in the
Arduino Contest
36 Comments
10 years ago on Introduction
https://www.instructables.com/files/deriv/F67/LTKF/HKM94B2Q/F67LTKFHKM94B2Q.SQUARE.jpg
This is a picture of my contraption, since you can't really see it in the video
Reply 3 years ago
Schematic please😫🙏🙏💓
5 years ago
Can I get Schematic please?
10 years ago on Introduction
I am currently working on the schematic. I will post it as soon as possible. As far as the audio input circuit, go to amandaghassaei's arduino audio input instructable. Thank you for your interest!
Reply 6 years ago
can i know what the component that u use in this project?..
9 years ago on Introduction
Is this code working properly? Because I compiled it and didn't work.
Thanks
Reply 7 years ago
The below code compiled
#include <Servo.h>
Servo Servo1; //declaration of servo object
int angleStill = 90; //stores servo position
int angle = 90; //stores servo position
int trim = 0; //trim adjustment to zero position
int servoPin = 8; //Arduino pin assigned to servo
int clockwisespeed = 120; //the speed to go in the clockwise direction
int countclockwisespeed = 60; //the speed to go in the counter clockwise direction
boolean clipping = 0; //clipping indicator variables
//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];//sstorage for timing of events
int slope[10];//storage fro 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
int minfreq; //it will be changed according to its string
int maxfreq; //it will be hanged according to to its string
int basefreq = 0; //define baseline noise to ignore any frequency less than this value
//int highstring;//says if you are tuning high string or not
//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 = 3;//slope tolerance- adjust this if you need
int timerTol = 10;//timer tolerance- adjust this if you need
int notenum = 0; //set the guitar string number I want to tune
int notenumPrior = 0; //holds the previously selected guitar string
//-------------------------------------------------------------------------------------------------------------
//all Arduino programs must have a setup routine
//Starts Setup routine
void setup(){
Serial.begin(9600); //begins sampling the serial port for monitoring purposes
pinMode(13, OUTPUT); //clipping indicator
pinMode(12, OUTPUT); //wave period indicator
pinMode(11, OUTPUT); //freq too low
pinMode(10, OUTPUT); //freq spot on
pinMode(9, OUTPUT); //freq too high
//sets all three pitch indicator lights off
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
pinMode(7, INPUT);// different paths from dip switch indicating the notenum value (output)
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
digitalWrite(7, HIGH);// making sure the input pins are set high, so when pressed they will be on low
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
Servo1.attach(servoPin); //attaches servo on pin x to servo object
//ADC - Handle Analog to Digital Conversion of Guitar Signal
cli(); //disables 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); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
}
void reset()
{//clea out some variables
index = 0;//reset index
noMatch = 0;//reset match couner
maxSlope = 0;//reset slope
}
//Launch Continuous Interupt Service Routine (ISR) for Sampling Analog to Digital Conversion of Guitar Audio Input
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)) //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]) ) //sum timer values
totalTimer = 0 ;
for (byte i=0;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
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
void checkClipping(){//manage clipping indicator LED
if (clipping){//if currently clipping
PORTB &= B11011111;//turn off clipping indicator led
clipping = 0;
}
}
//----------------------------------------------------------------------------------------------
//Start of Main Arduino Loop
void loop() // loop
{
//highstring = 0;
frequency = 38462/float(period); //calculate frequency timer rate/period
// added for debugging and visualizing data
Serial.print(frequency);
Serial.println(" hz");
Serial.println(" ");
Serial.println("string picked: ");
Serial.print(notenum);
notenum_val(); //call function to determine value of note/string we want to tune
freq_range_identify(); //set frequency threshold ranges for string previously selected
checkClipping(); //frequency determining and led indicator loop
set_indicator_lights(); //checks value of current frequency and lights correct indicator light. Then moves servo accordingly
//Serial.println(angle);
move_motor(); //move tuning servo motor
//delay(1000); //turn on to control debouncing
notenumPrior = notenum;
} //end of main loop
//-----------------------------------------------------------------------------------------------
//Determine String selected from rotary switch and voltage values on designated arduino pins
void notenum_val()
{
int val_1 = digitalRead(2); //read the value of rotary switch pins
int val_2 = digitalRead(3);
int val_3 = digitalRead(4);
int val_4 = digitalRead(5);
int val_5 = digitalRead(6);
int val_6 = digitalRead(7);
if (val_1 == LOW && val_2 == HIGH && val_3 == HIGH && val_4 == HIGH && val_5 == HIGH && val_6 == HIGH) //switch set on pressed, then notenum = 1
{
if (notenumPrior != 1)
{
delay(5000);
notenum = 1;
}
else
{
notenum = 1;
}
}
else if (val_1 == HIGH && val_2 == LOW && val_3 == HIGH && val_4 == HIGH && val_5 == HIGH && val_6 == HIGH) //Switch 3 pressed, noenum = 2
{
if (notenumPrior != 2 )
{
delay(5000);
notenum = 2;
}
else
{
notenum = 2;
}
}
else if (val_1 == HIGH && val_2 == HIGH && val_3 == LOW && val_4 == HIGH && val_5 == HIGH && val_6 == HIGH) //switch 4 pressed, notenum = 3
{
if (notenumPrior != 3)
{
delay(5000);
notenum = 3;
}
else
{
notenum = 3;
}
}
else if (val_1 == HIGH && val_2 == HIGH && val_3 == HIGH && val_4 == LOW && val_5 == HIGH && val_6 == HIGH) //switch 5 pressed, notenum = 4
{
if (notenumPrior != 4)
{
delay(5000);
notenum = 4;
}
else
{
notenum = 4;
}
}
else if (val_1 == HIGH && val_2 == HIGH && val_3 == HIGH && val_4 == HIGH && val_5 == LOW && val_6 == HIGH) //switch 6 pressed, notenum = 5
{
if (notenumPrior != 5)
{
delay(5000);
notenum = 5;
}
else
{
notenum = 5;
}
}
else if (val_1 == HIGH && val_2 == HIGH && val_3 == HIGH && val_4 == HIGH && val_5 == HIGH && val_6 == LOW) //switch 7 pressed, notenum = 6
{
if (notenumPrior != 6)
{
delay(5000);
notenum = 6;
}
else
{
notenum = 6;
}
}
else
{
notenum == 0;
//sets all three pitch indicator lights off
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
}
}
//---------------------------------------------------------------------------------------------------
// Sets the flat, sharp and spot on frequency thresholds depending on the string we're trying to tune
void freq_range_identify()
{
switch (notenum)
{
case 1://desired frequency=80-84 -- ideal value is 82
minfreq = 80;
maxfreq = 84;
break;
case 2://desired frequency between 108-112 ideal=110
minfreq = 108;
maxfreq = 112;
break;
case 3://desired frequency between 145-149 ideal= 147
minfreq = 145;
maxfreq = 149;
break;
case 4://desired frequency between 194-198 ideal=196
minfreq = 194;
maxfreq = 198;
break;
case 5://desired frequency= 245-249 -- ideal value is 247
minfreq = 245;
maxfreq = 249;
break;
case 6: //desired frequency between 328-332 ideal=330
minfreq = 328;
maxfreq = 332;
//highstring = 1;//stating high string is one being tuned
break;
}
}
//---------------------------------------------------------------------------------------------------
//Sets the 3 appropriate pitch indicator lights and sets the direction and speed of the tuning motor
void set_indicator_lights()
{
// if (highstring = 1)
//{
// checkfreq();
//}
if (frequency <= basefreq)
{
digitalWrite (11, LOW);
digitalWrite (10, LOW);
digitalWrite (9, LOW);
angle = 90;
}
else if (frequency < minfreq && frequency > basefreq)
{
digitalWrite (11, HIGH);
digitalWrite (10, LOW);
digitalWrite (9, LOW);
angle = countclockwisespeed;
}
else if (frequency > maxfreq)
{
digitalWrite (11, LOW);
digitalWrite (10, LOW);
digitalWrite (9, HIGH);
angle = clockwisespeed;
}
else
{
digitalWrite (11, LOW);
digitalWrite (10, HIGH);
digitalWrite (9, LOW);
angle = 90;
delay(1000);
checkfreq();
}
}
//---------------------------------------------------------------------------------------------------
void checkfreq()
{
frequency = 38462/float(period); //calculate frequency timer rate/period
Serial.println("doublecheck");
Serial.print(frequency);
Serial.println(" hz");
Serial.println(" ");
if (frequency <= basefreq)
{
digitalWrite (11, LOW);
digitalWrite (10, LOW);
digitalWrite (9, LOW);
angle = 90;
}
else if (frequency < minfreq && frequency > basefreq)
{
digitalWrite (11, HIGH);
digitalWrite (10, LOW);
digitalWrite (9, LOW);
angle = countclockwisespeed;
}
else if (frequency > maxfreq)
{
digitalWrite (11, LOW);
digitalWrite (10, LOW);
digitalWrite (9, HIGH);
angle = clockwisespeed;
}
else
{
digitalWrite (11, LOW);
digitalWrite (10, HIGH);
digitalWrite (9, LOW);
angle = 90;
Serial.println("String is tuned! Please move on!");
Serial.println(" ");
delay(5000);
}
}
//Turns the tuning motor appropriately
void move_motor()
{
Servo1.write(angle+trim);
delay(50);
Servo1.write(angleStill+trim);
}
Reply 9 years ago on Introduction
Last time I checked it compiled correctly and worked with the circuit. I will work on cleaning up the code and making a schematic so you can hopefully make your own!
8 years ago
what kind of microphone did you use?
8 years ago on Introduction
Can anyone link Amanda's stuff on here for me? I'm having trouble finding it
8 years ago on Introduction
The low E on a guitar is 82.41 Hz. If you go low by 2 Hz (your margin of error) then you end up about halfway to Eb. That quarter tone is *very* noticeable.
I'm not saying this to discourage you, or discount your work. On the contrary, I think this is a fantastic idea and great work. I just want to see it get even better!
9 years ago on Introduction
Nice!! What kind of servo motor you have use? and can you get schematics?
Reply 9 years ago on Introduction
Did you ever find out what kind of servo is being used?
Reply 9 years ago on Introduction
no but i used AAS-750MG servo. it has enought torque.
9 years ago on Introduction
Has anyone been able to replicate this, and if so, how did you wire the 2 pol 6 way switch with the arduino?
9 years ago on Introduction
wow !!! awesome
10 years ago
Owhhh..hmmm, let say i do exactly your project like on the picture and take your code. Will the project works? Or i need to refer to amandaghassaei's project too?
Reply 9 years ago on Introduction
The audio input and frequency detection I used are identical to amandaghassaei's. I reccommend you follow her instructables to make them, simply because I am working on cleaning up the code and making a schematic so you can make your own. Thanks.
9 years ago on Introduction
can i get a schematic pls?
Reply 9 years ago on Introduction
I will get on it. Sorry I have been absent, I have been rather busy recently. I will do whatever I can to help! I do not have a schematic, but I will make one. Thanks for your interest!