
“THE MECHANIX” guitar Tuner
Fan(Alex) Wang (FW45)
Ayan Nandi (AN94)
Paul Liew
(PCL25)
Introduction:
Motivation for Design

The Mechanix is a motorized guitar tuner for a standard
6-string electric or acoustic fixed bridge guitar. Named in honor of Megadeth
guitar legend Dave Mustaine, the Mechanix
is a unique and innovative product which has numerous patent possibilities. Traditional handheld guitar tuners are
passive; they tell the user whether the guitar string is in tune, sharp, or
flat, but the actual adjustment of the tension in the string has to be done by
the user. This requires a fair amount of dexterity from the user, particularly
when fine tuning is required. Thus, to increase both the convenience and the
precision of the tuning process, we designed an active, motorized guitar tuner.
The Mechanix responds to the user plucking one of the
strings by turning the tuning knob until the string has reached its Standard
Tuning note.
High Level Design
Rationale
and sources of project idea
Passive guitar
tuners have been commercially available for a long time and have also been implemented
as ECE476 projects before, but none have incorporated a machine-controlled
tuning process. The Mechanix is aimed at automating
the guitar tuning process as much as possible, so as to make the process of
tuning more precise and more convenient.
Background
math
Standard
Tuning, the most popular tuning on a 6-string guitar, is as follows:
|
String # |
Note |
Frequency (Hz) |
|
1 (Highest) |
E |
329.6 |
|
2 |
B |
246.9 |
|
3 |
G |
196.0 |
|
4 |
D |
146.8 |
|
5 |
A |
110.0 |
|
6 (Lowest) |
E |
82.4 |
Tuning the
guitar involves adjusting the tension in each string until it vibrates at its
Standard Tuning frequency.
Logical
Structure
Our project
can be divided into two main stages: signal processing and driving the motor.
Signal
Processing
The signal
from the plucked string, having a peak-to-peak amplitude on the order of tens
of millivolts, first went through a preamplifier that
scaled the amplitude up to the order of one volt. It was then put through a bandlimiting filter—a hardware low-pass filter with a
cutoff of 400 Hz—before being sampled by the A/D converter on the
microcontroller, so that the sampled signal would not be distorted by aliasing.
The sampled signal was then filtered in software using Butterworth filters to
suppress the higher harmonics of the vibrating string; the aim of this was to
yield, as far as possible, a clean sine wave of the fundamental frequency of
the plucked string. The frequency of this filtered signal was then calculated
by the method of counting zero crossings—noting the time taken for the
sine wave to rise through a threshold voltage 20 times, and dividing this time
by 20 to get the period of the wave, and taking the reciprocal of the period to
get the frequency. An LCD display shows the frequency of the vibrating string.
Driving
the motor
To connect the
rotating shaft of the motor to a tuning knob of the guitar, we needed a
‘claw’ fixed to the motor that would grasp the tuning knob. We had
the claw made in the machine shop of the Department of Mechanical and Aerospace
Engineering (special thanks to M&AE ’09 students Patxi
Fernandez-Zelaia and Adeboye
Ajayi for machining the part). We also estimated the
torque required to turn the tuning knobs and, with some assistance and
direction from Professor Francis Moon, we obtained a stepper motor from Rick
Schmidt of the M&AE department that produced the torque required to turn
the tuning knobs and met our design needs.
The motor was
driven based on the frequency calculated in the Signal Processing stage. If the
frequency calculated was within 1% of the Standard Tuning frequency of the
string, the motor was halted. If the frequency calculated exceeded the Standard
Tuning frequency by more than 1%, a signal was sent to the motor to rotate the
tuning knob in the direction that would loosen the string. If the frequency
calculated was below the Standard Tuning by more than 1%, a signal was sent to
instruct the motor to rotate in the string-tightening direction. Because we
used a stepper motor, we were able to control the turning of the tuning knobs
with great precision (to the nearest 1.8o, which was the step size
of the motor).
The motor took
as inputs PWM signals that would have required a rather complicated
implementation if done in software. We avoided this by using instead a motor
driver chip, which interfaced between the microcontroller and the motor and
which produced the required PWM signals to drive the motor based on simple
logical signals (0 or 1) from the microcontroller. This made our motor-driving
code clean and simple.
Relationship
of our design to available IEEE, ISO, ANSI, DIN, and other standards
We programmed
the microcontroller in ANSI C. We used the IEEE 32-bit floating point for the
floating point calculations required in calculating frequencies and filter
coefficients.
Program/Hardware
Design: Signal Processing Implementation
We now aim to
provide a cursory overview of the entire process of calculating the frequency
of a plucked guitar string, and consequently elaborate each specific piece in copious
detail. The Signal Processing
design uses both analog hardware as well as software methods to output a
frequency for a plucked guitar string signal.
Below is a
simple flowchart detailing the entire process:

STAGE 1 - PREAMPLIFIER
The line
output from the guitar is weak and has a low current. In order to be able to actually read
this signal, we would need to use a BJT amplifier. To circumvent this cumbersome task, we
used an Audio Buddy Preamplifier I already had at home. This gave this signal a boost and
removed some noise as well.
STAGE 2 – ANALOG
FILTER
The analog
signal output from the preamp is of infinite bandwidth and contains a large
amount of second and third harmonic.
It also has a random DC bias.
Before the signal can be send to the microcontroller ADC, it must be
band-limited to remove aliasing.
The biasing circuit first uses a 1 uF
capacitor to remove any DC bias the signal may have. We then used a voltage divider to bias
the signal at 2.5 V, the middle of the MCU conversion range. We then passed it through a Salen Key 2nd order low pass Butterworth to band
limit the signal to 400 Hz.
Below is a detailed diagram of the biasing circuit and the analog
filter:
The analog
filter uses a cutoff of 400 Hz, and the resistances and capacitances were
chosen by the equations below:


The filter has
transfer function:
A(s) = 1/(1 +
1.4142s + s^2)
STAGE 3 – ADC INPUT
The output of Stage
2 is sent to the ADC0 input of the ATMEGA32 and a reference voltage of 5 V is
used for sampling and quantization.
The sampling rate is 2 kHz, which satisfies the Nyquist
requirements for sampling and recovery.
A constant value of 127 was subtracted from the converted value so that
the input to the digital filter would be biased at zero and not at 2.5 V.
STAGE 4 – DIGITAL
FILTER
We used Bruce
Land’s code for a second order filter and modified to accommodate for the
added coefficients. The filter function
IIR2() will accommodate for the following transfer function:
Y[n] = b1*X{n]
+ b2*X[n-1] + b3*X[n-2] – a2*Y[n-1] –a3*Y[n-2]
The converted
and zero biased fixed point signal was sent to the filter, which would remove
the second harmonic of the guitar signal.
Each string had its own separate filter, which would have the first
harmonic in the middle of its band to minimize attenuation. The filters were able to reject second
harmonic at about 8+ dB for the lowest string, with minimum passband
attenuation. Matlab’s
fdatool() is used to show the magnitude response for
the low E string filter. For the
lower three strings, we actually filter twice to create a fourth order
filter. For the higher strings, we
have too much attenuation and simply use the function IIR2() once. This rejection factor increases for
higher strings, as the first and second harmonics are further apart. Below we detail the fdatool()
plot for the filters used for the lowest and highest strings. The point indicated designates the rejection
in dB for the second harmonic.
STAGE 5 – FREQUENCY
OUTPUT
A for loop
checks for signal zero crossings.
If two samples are below zero and the next two are above zero, a cycle
has been detected. After ten
cycles, the time checked is divided by ten and modified to compute the signal
frequency. The value of frequency
is somewhat unreliable due to transient behavior, so frequency calculations
half a note below or above the desired first harmonic are not fed to the
motor. Even then, small oscillations
will occur within range, but will eventually stabilize at the real
frequency. As long as there are
more correct readings than incorrect, the guitar string will tune correctly.
Frequency
Response for 4th Order Butterworth with band f = [20 120] –
low E

Frequency
Response for 2nd Order Butterworth with band f = [230 430] –
high E

Program/Hardware
Design: Software Functionality
Initialization
- void initialize(void)
First, set up Timer0 to run at 2kHz.
Then set up Timer2 to fast PWM mode so it displays the waveform of the
digitally filtered signal. Then, enable ADC and set the ADC prescaler
to 128. Set up PORTA as input because we are using the ADC and the rest of the
inputs are connected to switches used to select which string to tune.
Initialize the program to be not in tune and motor not moving. Next, the
program calls function KillEmAll(); to initialize
other state variables. PORTB is set up as output to control the motor. The
outputs from PORTB are connected to the motor driver chip. The unused logical
inputs on the chip must be tied to ground or Vcc.
PORTB.0 is set to zero because reset is not used. PORTB.1 controls the
direction of which the motor spins. PORTB.2 and PORTB.3 control the step size of
the motor. Since the torque should be maximized on this motor, the step size is
set to 1/16 of a whole step. The sync function on the chip is not used,
therefore PORTB.4 is set to zero. PORTB.5 is the clock of the chip. The chip
will only work when there is a rising clock edge from the clock input. So
PORTB.5 is toggled when the program wants the motor to move. The variable time1
is initialized to 1000 so the function ReighInBlood()
can run at 2Hz. Finally, set up PORTC as output because the LCD is connected to
it, set up PORTD.7 as the DAC output, initialize the LCD display and turn on
the interrupts.
String Selection - void ReignInBlood(void) –
running at 2Hz
This part of the software is the slowest process running on the MCU.
The purpose of this piece of code is to let the user choose which string is
being tuned. Due to the band-limiting filter at the input of the ADC, the
higher strings tend to be attenuated. Therefore, two levels of control are in
place in this function. First, the input signal to ADC can either come from the
second amplifier or the first (the second amplifier is a further amplification
of the output from the first). In this case, the program chooses between two
ADC ports, ADC0 and ADC1, with ADC0 being the signal without extra
amplification. Second, when doing the digital filtering, the signal can be
filtered once or filtered by cascading two filters. It turns out that for the
lowest two strings, ADC0 and cascading filters yield the best result; for the middle
two strings, ADC0 with a single filter works the best; for the highest two
strings, ADC1 with a single filter produce the best response. For each string,
the filtering coefficients and the corresponding frequency boundaries will be
set. The frequency boundaries (realFH and realFL) are set to within 1% of the real frequency (the
choice of 1% will be discussed in the accuracy section) and are used to
controlled the motor. Another set of boundaries (H and L) are set to within 5%
of the real frequency. The reason being a half step corresponds to 2^(1/12)
which is about 5%. For each string, a flag is set (start=1) to indicate that
the tuning process can start.
Filtering
& Motor Control - interrupt [TIM0_COMP] void timer0_compare(void) –
running at 2kHz
Once the starting flag is set, the
program enters into the code. First, if the guitar is not in tune, the motor
has been started, and the motor still has steps left, the motor will move. The
time variable merely keeps track of the time since the last calculation of
frequency. Next, the ADC input will be read. The reason for subtracting 128
from the reading is because the filter uses signed numbers while the ADC
reading ranges from 0 to 255 unsigned. After storing the ADCH in x0, another
ADC reading starts. The next line outputs the filter result to DAC so it can be
read on the oscilloscope. Then, depends which string it is, x0 is either
filtered by a single filter or two filters cascaded together. Here we used the
and modified the IIR2 Butterworth filter code written by
Frequency
Display - void lcdcdcd(void) – running at 10Hz
This function merely displays the
calculated the frequency if it's within 5% of the actual frequency of the
string.
Motor, Motor
Control
The motor that is used in this project
is a 6-wire unipolar stepper motor. First we had to
figure out what each wire did. This was done by measuring the resistance
between different combinations of two wires. If two wires have infinite
resistance between them, they are from two different coils; if two wires have
half the resistance of some other combinations, it means one of the two wires
is connected to the voltage source; if two wires have the whole resistance,
they are the two ends of the same coil. Next, we needed to figure out the phase
of the wires so we could connect the motor to the motor driver chip. So we had
to connect both power wires to a voltage source. Then choose any of the 4 wires
that are left and connect it to ground. Then ground the last three wires in
sequence to see which one makes it turn CW, which one makes makes
it turn CCW, and which one does nothing. Make a chart for all four wires, then
figure out the sequence of wire combinations that makes the motor turn CW or
CCW. Once the motor is figured out, we can move on to the motor driver. The
driver chip has two sides. One side of the chip communicates with the MCU and
the other side controls the motor. The motor controlling side requires at least
10V to function. This was a problem because the motor was only rated at 5V. We
let 10V run through the motor, and we didn't burn the motor, so we assumed that
it was safe. The example circuitry for the motor driver chip looks taunting at
first. After close examination of the data sheet, however, we realized that we
didn't need to implement everything the data sheet had suggested. This
simplification saved us one pMOS transistor and
dramatically reduced our workload. After scoping each output, and figuring out
the phase difference between each output, we could connect the motor like so:
the two ends on the same coil should have 180 degree phase difference while the
ends on the same side of different coils should have 90 degree phase
difference.
Below is the schematic for the motor
driver circuit taken from the data sheet:

Results

SPEED OF EXECUTION & reliability
The tuner takes some time to tune a string, as the DSP waits for a
reading in the range of half a note within the desired fundamental
harmonic. Thus, the tuning
process can be slow.
At times the result may be incorrect and it may take more than once time
to tune a string correctly. This
situation occurs more frequently
when tuning the B string, as it is of an incorrect thickness.
Accuracy
We had a number of accuracy issues to deal with in this project.
First of all, we have the accuracy issues on the DSP side: the quantization of
the original guitar signal by the ADC and the attenuation of the signal by the
digital filter. Then we have a motor which is inaccurate up to 3%. This becomes
a huge issue for this project because each half note is only 5% apart and a
human with perfect pitch can actually detect up to 0.1% or about 3 cents of
inaccuracy. To counter all these obstacles, we let the motor move in very fine
steps and smaller overall movements but more frequently. The string is tuned
when the motor starts to turn back and forth around a certain point. This
turned out to work well.
USABILITY
Our device is somewhat cumbersome, with many fragile wires and
stray cables. I would say that few
people other then ourselves would be able to use this
device in its current state.
Conclusions
Results
of our design versus our initial expectations
Through the
course of our project our expectations were continually revised as we
encountered the practical limitations and constraints that we had to work with.
We envisioned initially, for instance, 6 motors simultaneously tuning all the
strings; this initial vision was quickly abandoned upon realizing how bulky and
inelegant it would be to clamp 6 motors to the head of a guitar. Also, accuracy
of tuning did not appear to be a big issue initially, as we supposed the
process of counting zero crossings to be fairly straightforward; we discovered
through our design process, however, that allowing a small margin of error
(~1%) in tuning the frequency was an unavoidable concession that we had to
make. One thing we might do differently next time is to use a different
filtering scheme (e.g. a set of three closely spaced bandpass
filters to determine frequency by comparing the three filter responses, rather
than calculating the frequency based on the output of a single bandpass filter) which might improve the accuracy of our
frequency calculations.
Conformation
of our design to the applicable standards
Our code
easily conformed to the ANSI C and IEEE 32-bit floating point standards.
Intellectual
property considerations
We did not
reuse code or someone else’s design, although we read previous ECE476
guitar tuner project reports, and the method of counting zero crossings was
suggested to us by Prof Bernard Hutchins. We did not reverse-engineer other
designs and did not have to deal with patent/trademark issues. Sampling of the
motor driver chip was also hassle-free and required no non-disclosures. We
think our project is patentable; its usefulness is obvious, and it is somewhat
surprising that there is not a product like this on the market already.
Ethical
considerations
To the best of
our knowledge, we did not violate any of the rules on the IEEE code of
ethics. Our motor drew a lethal 1 A
current; however, we made sure that the circuit was closed and that we did not
touch the motor circuit while it was on.
Therefore, the device is safe for general use, though as a product would
require more stringent requirements.
In terms of crediting others for our work, we did make an effort to
thank the persons who machined the motor driveshaft as well as Bruce Land, who
gave us a lot of good ideas and criticism.
If we were to develop this as a real product, we would explore new ideas
and methods and credit them as well.
We were honest in our reporting of accuracy and reliability, and did not
attempt to hide our drawbacks. Once
we patent this idea, we wish to sell the design and accept full responsibility
for any design flaws. We will not
attempt to misrepresent any data or testing results. In requesting samples or free parts, we
were not bribed or paid by any person or company to use their specific
part.
Legal
considerations
We did not
encounter any legal restrictions in the course of our project.
Different Approaches, Failures, Difficulties:
1.
We
initially tried to implement a state-machine based motor control scheme. The idea
was to let the frequency calculations happen, and then decide what to do after
the frequency settled on one value. This didn't work out well because the
frequency calculations are not that reliable. We decided that the better
approach would be to let the motor move more frequently but in smaller steps so
that overall the motor moves towards the right direction.
2.
We
thought we would need a gear train to turn the guitar because stepper motors
are known to have weak torques. After consulting Professor Moon and Rick
Schmidt from M&AE, we realized that a gear train would be way too expensive
to implement for this project and we only needed a strong stepper motor which
we got from Rick Schmidt.
Appendix: Parts list
and cost details
|
Part |
Part number |
Quantity used |
Cost ($) |
Source |
|
STK500 board |
STK500 |
1 |
15 |
Rented |
|
Atmel mega32
mcu |
ATmega32 |
1 |
8 |
Rented |
|
White board |
N/A |
2 |
12 |
Rented |
|
LCD |
LCD |
1 |
8 |
Rented |
|
DIP socket |
N/A |
1 |
0.50 |
Rented |
|
1-pin jumper
cable |
N/A |
10 |
5 |
Rented |
|
Power supply |
N/A |
2 |
5 |
Rented |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Op-amp |
LM358 |
2 |
0 |
Rented |
|
M-Audio
Preamp |
Audio Buddy |
1 |
0 |
Own |
|
Motor |
LM061-FD02 |
1 |
0 |
Scavenged |
|
Motor driver
chip |
SLA7060M |
1 |
0 |
Sampled |
|
Claw |
N/A |
1 |
0 |
Outsourced |
|
Total Cost: |
$53.50 |
|
|
|
|
Balanced
Budget |
Yes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Appendix: Distribution
of tasks among team members
We collaborated
on all aspects of the project, though each of us did ‘specialize’
in different aspects. Alex was most familiar with the coding; Ayan was most familiar with the filter design process; Paul
dealt mostly with building the hardware. All of us tested, debugged and refined
our guitar tuner in lab together.
References
Data sheets
Mega32:
http://instruct1.cit.cornell.edu/courses/ee476/AtmelStuff/full32.pdf
Motor driver:
http://www.allegromicro.com/en/Products/Part_Numbers/97060/97060.pdf
Motor:
http://www.techkits.com/SuperiorM06.pdf
Vendor sites
Motor driver:
http://www.allegromicro.com/en/Products/Part_Numbers/97060/
Code/designs borrowed from others
DSP code from
Prof Bruce Land:
http://instruct1.cit.cornell.edu/courses/ee476/Math/avrDSP.htm
Background sites
Previous 476
guitar tuner projects:
http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2005/ejt22/index.htm
http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2004/ddb25/index.htm
Analog filter
design:
http://focus.ti.com/lit/ml/sloa088/sloa088.pdf
DSP on mega32:
http://instruct1.cit.cornell.edu/courses/ee476/Math/avrDSP.htm
Appendix: Commented
Software Code
//time base will be 10e-4
//stuff that needs to be added in:
//
//
//PORT hookups:
//Port A: ADC
//Port B: LED outputs
//Port D: pushbutton inputs
#asm
.equ __lcd_port=0x15
#endasm
#include <lcd.h> // LCD driver routines
#include <Mega32.h>
#include <stdio.h>
#define begin {
#define end
}
#define float2fix(a) ((int)((a)*256.0))
#define fix2float(a) ((float)(a)/256.0)
#define int2fix(a) (((int)(a))<<8)
int
time, cycle, timerecorded, hc, start, L, H, th, step;
char inTune, motorS;
signed int x0, y0, y1, y2,y3,y4,y5,y6,y7,y8,y9,thre, thre1, TT;
signed int P1, P0;
char