Introduction: Visual / Aural Guitar Tuner "The Tune Trainer"

About: I'm a software guy who likes to tinker with hardware in my spare time. I'm not an expert at anything, but I'll try anything.

Build a strobe tuner with an integrated tone generator to teach tuning by ear.

-=Background=-
I have always dabbled in instruments. Over the course of my life, I've attempted (with varying success) Piano, Guitar, Banjo, Penny Whistle, Ocarina, Panpipes, Great Highland Bagpipes, Smallpipes, and Didgeridoo (don't ask, It was late, and I was a bit tipsy). In the process, I have continually hit one major hurdle. I am absolute rubbish at tuning by ear. I cannot tell if a guitar is out of tune in the least, unless it is so far off that you can play "The Bells of Saint Mary" without fretting at all. I was up late one night, experimenting with some PWM code for the Arduino when I suddenly had an epiphany. "Beat" tuning is very similar to measuring speed with a strobe. I thought that perhaps combining the obvious visual input of a strobe with the auditory input of a tone, could help me to better grasp tuning by ear. Thus an idea was born
----

"The Tune Trainer" is a combination of two devices. One is a strobe that flashes at the frequency of a tuned string. The other is a tone generator. together they give the user two methods of tuning

1) Strobe - The musician sets the tuner for a string and strums said string while aiming the strobe at it. The strobe causes the apparent speed of motion of the string to decrease as the user approaches the correct frequency. as the the string gets closer to tuned, the string's vibration will happen in visible pulses of speed and apparent lethargy, which slow as the tuning improves. These variations in speed should coincide with the frequency of audible "beats" when beat tuning.

2) Tone - The musician sets the tuner for a string and strums said string while listening carefully. If the string is very far from true, he'll hear discord. once he is close enough that the discord disappears, he will begin to hear "beats" in the combined sound of the two tones, caused by constructive and destructive interference between the waves. The beats should decrease in tempo and amplitude as you approach a perfect tuning. (in theory)

The user can chose Both or either method to tune, hopefully allowing the combined methods to train the ear in the aural method of tuning.

The other neat thing about this project is strobe tuning itself, which looks AWESOME!!!1!

Step 1: Materials

you will need the following materials (or similar) to build the tuner:

-Arduino prototyping board with the IDE installed on a computer
-9v battery
-9v battery clip
-9v battery connector
-Barrel-type power connector for Arduino
-6 normally open momentary pushbuttons (RS has LOTS of NC switches in similar packages, beware)
-3 SPST switches
-High Powered LED and associated resistor for a 5v load (the brighter the better, min 40,000 mcd)
-LED mounting bracket
-Piezo speaker (for a 5v load)
-1uF Capacitor (optional, run in parallel with speaker, to improve tone.)
-project box

Step 2: Programming

The program for the arduino takes in button commands from the 6 pushbuttons on pins 2-7 and outputs the selected frequency in light and sound via pins 10 and 11 (two of the PWM pins) these outputs are pulsed high and low at the frequency of the selected note to drive the Peizo and the LED respectively

here's the basic flow of the program (in pseudo-code):

loop
-check for buttons
-if button
--set "frequency"
--loop
-- -set led HIGH
-- -set piezo HIGH
-- -wait "led pulse length"
-- -set led LOW
-- -wait "frequency"/2 - "led pulse length"
-- -set piezo LOW
-- -wait "frequency"/2
-- -check for buttons
-- -if button
-- --break
-- -end if
--end loop
-end if
end loop

and the full code

//**************************// THE TUNE TRAINER v1.0// BY: GREG SCHOPPE// http://www.gschoppe.com//**************************// STRINGS  ========================================#define  e      3034    // 329.63 Hz#define  b      4050    // 246.94 Hz#define  g      5102    // 196.00 Hz#define  d      6811    // 146.83 Hz#define  a      9091    // 110.00 Hz#define  E     12135    // 82.407 Hz#define  NONE      0    // Default State// -- length of time the LED is on in each cycle#define FlashLength     1024// SETUP ============================================// Set up input on 6 pinsint inPin_e = 7;int inPin_b = 6;int inPin_g = 5;int inPin_d = 4;int inPin_a = 3;int inPin_E = 2;// Set up output on a PWM pin (digital 9, 10 or 11)int freqOut = 11;// Do we want debugging on serial out? 1 for yes, 0 for noint DEBUG = 0;void setup() {   pinMode(freqOut, OUTPUT);  // declare pushbuttons as input  pinMode(inPin_e, INPUT);  //high-e  pinMode(inPin_b, INPUT);  //     b  pinMode(inPin_g, INPUT);  //     g  pinMode(inPin_d, INPUT);  //     d  pinMode(inPin_a, INPUT);  //     a  pinMode(inPin_E, INPUT);  // low-e   // turn on pull-up resistors  digitalWrite(inPin_e,HIGH);  //high-e  digitalWrite(inPin_b,HIGH);  //     b  digitalWrite(inPin_g,HIGH);  //     g  digitalWrite(inPin_d,HIGH);  //     d  digitalWrite(inPin_a,HIGH);  //     a  digitalWrite(inPin_E,HIGH);  // low-e    if (DEBUG) {     Serial.begin(9600); // Set serial out if we want debugging  }  // SIGNAL THAT THE CHIP IS READY  digitalWrite(freqOut,HIGH);  delay(500);  digitalWrite(freqOut,LOW);   }int input () {  if(digitalRead(inPin_e)==LOW) {    return(e);  }  if(digitalRead(inPin_b)==LOW) {    return(b);  }  if(digitalRead(inPin_g)==LOW) {    return(g);  }  if(digitalRead(inPin_d)==LOW) {    return(d);  }  if(digitalRead(inPin_a)==LOW) {    return(a);  }  if(digitalRead(inPin_E)==LOW) {    return(E);  }  return(NONE);}void playTone (int period) {  if(period==NONE) { //if no button has been pressed    return;  }    int ToneLength = period/2 - FlashLength;  int OffLength  = period/2;    // SIGNAL THAT THE INPUT WAS ACCEPTED  digitalWrite(freqOut,LOW);  delay(100);  digitalWrite(freqOut,HIGH);  delay(100);  digitalWrite(freqOut,LOW);  delay(500);  // CONTINUE TO STROBE LOOP    // -- the strobe loop runs 4 strobes before each test,  // -- to try and lose as few microseconds as possible.  while(true) {    // BEGIN SET OF 4 STROBES	    // ON TONE & LIGHT    PORTB = (B00001100 | PORTB);   // -- turns on  Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(FlashLength);    // OFF LIGHT    PORTB = (B11110111 & PORTB);   // -- turns off Pin 11; Leaves all others as-is;    delayMicroseconds(ToneLength);        // OFF BOTH    PORTB = (B11110011 & PORTB);   // -- turns off Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(OffLength);        // ON TONE & LIGHT    PORTB = (B00001100 | PORTB);   // -- turns on  Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(FlashLength);    // OFF LIGHT    PORTB = (B11110111 & PORTB);   // -- turns off Pin 11; Leaves all others as-is;    delayMicroseconds(ToneLength);        // OFF BOTH    PORTB = (B11110011 & PORTB);   // -- turns off Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(OffLength);        // ON TONE & LIGHT    PORTB = (B00001100 | PORTB);   // -- turns on  Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(FlashLength);    // OFF LIGHT    PORTB = (B11110111 & PORTB);   // -- turns off Pin 11; Leaves all others as-is;    delayMicroseconds(ToneLength);        // OFF BOTH    PORTB = (B11110011 & PORTB);   // -- turns off Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(OffLength);        // ON TONE & LIGHT    PORTB = (B00001100 | PORTB);   // -- turns on  Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(FlashLength);    // OFF LIGHT    PORTB = (B11110111 & PORTB);   // -- turns off Pin 11; Leaves all others as-is;    delayMicroseconds(ToneLength);        // OFF BOTH    PORTB = (B11110011 & PORTB);   // -- turns off Pin 11 and Pin 10; Leaves all others as-is;    delayMicroseconds(OffLength);    // END SET OF 4 STROBES        //Check Input Pins    if ( (PIND & B11111100) != B11111100) {    // -- PIND is a register containing the state of pins 0-7 as a byte;    // -- i.e. B11111101 would signify that pins 1 and 5 were LOW and the rest were HIGH.    // -- the testing against B11111100 is to ignore inputs on pin 0 and pin 1 (RX and TX)    // -- so, the above code means that if any of pins 2-7 are low, we exit the loop.		return;	}      }  }void loop() {	playTone(input());}

I saved a bit of time in the inner loop with some hacked together bit operations, but overall the coding is pretty basic. Its also a bit of a hack, so please don't nag me about rogue style syntax laws. I know what they are, but when I'm rushing, I ignore them...

you can change the frequencies of each button by altering the declarations at the top.

Step 3: Build It Already!!

-load the program onto the Arduino

-cut holes in your project box to accommodate the 6 buttons, 3 switches, and the LED.
-mount the 9v battery clip
-mount the Arduino
-connect all wires as shown in the circuit diagram
-connect power (barrel connector to 9v battery snap via switch)
-test
-mount all components
-seal

// yes I know this is sketchy, but the schematic explains the exact connections
// if you need more description ask, and I'll try to oblige

Step 4: Enjoy

aim the tuner at a string and start the corresponding strobe...

WOWEE!!

now, start the tone, and listen for the rhythmic variations in perceived volume and pitch that correspond to the effect you're seeing.

Its EDU-TAINING...

I never could quite grasp what the "beats" were until i built this...

I'm still rubbish at tuning, but hopefully that's improving.

The Instructables Book Contest

Participated in the
The Instructables Book Contest