2 breadboards: $10.00
1
LCD Display: $5.00
1
Mega32: $8.00
1
LM358 (op amps): $0.43
8
Resistors: $0.08
3
Capacitors: $0.75
2
1N914 (diodes): $0.02
Total: $24.28
All
of these components were available in the lab so we didn’t use any vendors.
Appendix B: Task Breakdown
Dmitry Berenson: Hardware design,
testing, and implementation. Creating web-site.
Galen
Reeves: Software filtering. Program design, testing, and
implementation.
Appendix C: Data Sheets
LM358 op amp.
ATMEGA32 microcontroller.
LCD.
STK500 prototype board.
1N914 diode.
Appendix D: Commented Code
//final
project - Guitar tuner
#include <Mega32.h>
#include <math.h> // for sine
#include <stdio.h> // for sprintf
#include <string.h>
#include <stdlib.h>
//I
like these definitions
#define begin {
#define end
}
//LCD
stuff
#define LCDwidth 16
#asm
.equ __lcd_port = 0x15;
#endasm
#include <lcd.h>
unsigned char lcd_buffer[17];
//set
definitions
#define infinit_T 2000
#define bias 110
/*
Standard E tuning
frequency period
samples at 5kHz (0.2ms)
E = 82.4069
s0 0.0121 60.675
A = 110.0000 s1
0.0091 45.45
D = 146.8324 s2
0.0068 34.05
G = 195.9978 s3
0.0051 25.5
B = 246.9417 s4
0.0040 20.248
e = 329.6277 s5
0.0030 15.169
*/
//
Sampling variabls
unsigned char Sold,S; // hold past
two samples
unsigned int measured_T; // measured
period
unsigned int target_T; // target
period
unsigned char edgesSeen=0; // number of periouds seen
//variables
to hold string frequency bounds
unsigned int T_low,
T_high; //largest bounds
unsigned int T_low2, T_high2; //medium
bounds
unsigned int low_bound,
high_bound; //small bounds
//arrays
to hold string specific values
unsigned int T_array[6]; // hold target
periods for strings
unsigned int low_array[6];
unsigned int high_array[6];
unsigned int low_array2[6];
unsigned int high_array2[6];
unsigned int tight_array[6];
//state
variables
unsigned char string; //string to be tuned
char
name[]="EADGBe"; //display string name
//variable
for arithmatic
unsigned int i;
float c1,c2;
//variables
for filter
unsigned int filter_array[6];
// hold filter settings
unsigned int filter1; // alpha
unsigned int filter2; // 1-alpha
//
timer variables
unsigned int time1,time2;
//tasks
void sample(void); //take an ADC sample and output result to LEDs
void buttonSM(void); //set string to
tune
void
initialize(void); //all the usual mcu stuff
void set_string(void); //set parameters
specific to string
//**********************************************************
//timer
0 compare ISR
interrupt [TIM0_COMP] void
timer0_compare(void)
begin
//Decrement timer
variables
if
(time1>0) --time1; // sample()
if
(time2>0) --time2; // buttonSM()
end
//**********************************************************
//Entry
point and task scheduler loop
void main(void)
begin
initialize();
while(1)
begin
if(time1 == 0) sample(); //sample input and tune
if(time2 == 0) buttonSM(); //set string to tune
end
end
//**********************************************************
//sample
- take an ADC sample and output result to LEDs
void sample(void)
begin
time1 = 1; //return in 200 us
//sample from ADC
Sold = S; //stor old value
S = ADCH; //sample
ADCSR.6 = 1; //take
new sample with ADC
//filter input
signal
S= (char)((filter1*(int)Sold
+ filter2*(int)S)>>4);
//Increment period
if it is not maxed out
if
(measured_T < infinit_T
)
measured_T++;
else //otherwise
PORTB = ~0b00000001; //display ready
led
//Test for
zero-crossing
if(Sold
< bias && S >= bias) //if trigger
begin
edgesSeen++;
//increment number of edges seen
//make sure T
is not infinte
if(measured_T < infinit_T)
begin
//after seeing 10
complete periouds
if(edgesSeen == 10)
begin
edgesSeen = 0; //reset
number of edges seen
//accempt measured_T only if it is
in right range
if(measured_T < T_high && measured_T >
T_low)
begin
//set LEDs based on
range of measured_T
if(measured_T >
T_high2)
PORTB = ~0b00001000;
if(measured_T > high_bound && measured_T
<= T_high2)
PORTB = ~0b00010000;
if(measured_T >= low_bound && measured_T
<= high_bound)
PORTB = ~0b00100000;
if(measured_T >
T_low2 && measured_T < low_bound)
PORTB = ~0b01000000;
if(measured_T <=
T_low2)
PORTB = ~0b10000000;
end
measured_T
= 0;
end // if 10th edge
end //if less than infinit_T
else // if measured_T is infinite
measured_T =
0;
end //end trigger
end
//**********************************************************
void buttonSM(void)
begin
time2 = 150; //
return to buttonSM in 30 ms
//set each string
based on which button is pressed
switch(~PIND)
begin
case 0x04: // button0 on PD2 - E
string
= 0;
set_string();
break;
case 0x08: // button1 on PD2 - A
string
= 1;
set_string();
break;
case 0x10: // button2 on PD2 - D
string
= 2;
set_string();
break;
case 0x20: // button3 on PD2 - G
string
= 3;
set_string();
break;
case 0x40: // button4 on PD2 - B
string
= 4;
set_string();
break;
case 0x80: // button5 on PD2 - e
string
= 5;
set_string();
break;
end
end
//**********************************************************
//set_string()
- set string dependent variabls
void set_string(void)
begin
//display string
name on LCD
sprintf(lcd_buffer,"%-c",name[string]);
lcd_gotoxy(8, 0);
lcd_puts(lcd_buffer);
//set string
bounds from arrays
target_T = T_array[string];
filter1 = filter_array[string];
filter2 = 16-filter1;
T_low = low_array[string];
T_high = high_array[string];
T_low2 = low_array2[string];
T_high2 = high_array2[string];
high_bound = target_T + tight_array[string];
low_bound = target_T - tight_array[string];
end
//**********************************************************
//Set
it all up
void
initialize(void)
begin
//set up ports
DDRA=0x00;
// PORT A takes input from ADC
DDRC=0xff;
// PORT C outputs to LCD
DDRD=0x00;
// PORT D is an input from buttons
DDRB=0xff;
// PORT B outputs to LEDs
//turn LEDs off
PORTB=0xff;
//set up timer 0
TIMSK=2;
//turn on timer 0 cmp
match ISR
OCR0 = 50; //set the compare to 250 time ticks
//prescalar to 64 and turn on clear-on-match
TCCR0=0b00001011;
//init the task
timer
time1 = time2 = 0;
//LCD
initialization
lcd_init(LCDwidth);
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("String:");
//set up ADC
ADMUX = 0b00100000;
ADCSR = 0b10000110;
ADCSR.6 = 1; //
start conversion
//initialize
string values
T_array[0] = 607-8-2;
T_array[1] = 455-7-2;
T_array[2] = 341-7-1;
T_array[3] = 255-3-2;
T_array[4] = 202-4+1;
T_array[5] = 152-3;
//initialize tight
strig bounds
tight_array[0] = 2;
tight_array[1] = 2;
tight_array[2] = 1;
tight_array[3] = 1;
tight_array[4] = 0;
tight_array[5] = 0;
//initialize
string bounds
c1 = 1.05; //1.0293;
c2 = 1/c1; //0.9715;
for(i=0;i<6;i++)
begin
high_array[i] = (unsigned int)(c1*((float)T_array[i]));
low_array[i] = (unsigned int)(c2*((float)T_array[i]));
high_array2[i] = T_array[i]
+ (tight_array[i]+3);
low_array2[i] = T_array[i]
- (tight_array[i]+3);
end
//initialize
filters
filter_array[0] = 15;
filter_array[1] = 15;
filter_array[2] = 12;
filter_array[3] = 12;
filter_array[4] = 4;
filter_array[5] = 4;
//set initial
string to E
string = 0;
set_string();
//crank up the ISRs
#asm
sei
#endasm
end