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

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.

Comments

author
Bosleymusic made it!(author)2014-04-06

Is there any way you can reformat your code to be readable? It's sort of unclear what you've done in defining the numbers related to the given pitches. You should clarify as well, that you are counting periods in uS, and that is the nature of the #define'd numeric values.

author
mrmerino made it!(author)2012-05-08

Ok... I don't feel comfortable with arduino yet, too many ways to goof up. Is this something I can do with a 555?

author
nitetime3021 made it!(author)2010-01-29

I want to build a box that unlocks when notes are sung. Have you ever seen a project like that?

author
PoisonedV made it!(author)2008-01-05

This is awesome

author
PoisonedV made it!(author)2008-01-05

Although I have to add, I dislike using arduino in permanent projects. Pricey.

author
mmbutler made it!(author)2009-07-21

Sparkfun sells the 28-pin DIP ATMega 328 for $4.30; a crystal is maybe $1 and then you might need a voltage regulator, another 50 cent part. You don't need to throw a $35 Arduino at everything that works with an Arduino. Though you will need to make a one-time purchase of some of the reusable bootloader programming equipment and such. :)

author
larsjet made it!(author)2007-11-30

is t future project with 2 cameras, I have those cameras as well

author
gschoppe made it!(author)2007-12-02

I haven't gotten the lens assembly worked out yet, but its a prototype tele-presence unit.

author
5Volt made it!(author)2007-07-04

Strobe tuning ! Interesting a Physics class experiment. As a tuning instrument : I'm not a musician but it looks good to me. Ciao

author
zzag made it!(author)2007-07-03

I have one of these: Planet Waves strobe pick

http://www.planetwavestuners.com/index.php?option=com_tuner&task=tunerdetailpage&id=1

but had always thought it would be a neat AVR project to try and duplicate. You've nudged me closer.

Nice post... thanks.

author
gmoon made it!(author)2007-07-02

The strobed LED is a neat trick. I might have to build my own version of your device--I've got several different AVRs types here. Shouldn't be too hard to adapt your code for gcc (yeah, I'm aware the Arduino is avr based.) Since I'd like a version that supports alternate tunings, maybe adding a LCD to display the current tuning mode. And a few less buttons--just a mode button, and forward & reverse (on/off, too.)

About This Instructable

19,047views

54favorites

License:

Bio: I'm a self proclaimed renaissance man. My goal in life is to have a conversational/practical knowledge of every subject known to man. I ... More »
More by gschoppe:The AnonyBox - A cheap and easy network device to manage anonymity onlineJack-o-lanterns from years pastHeart-Shaped Paperclips
Add instructable to: