Appendix A: Costs


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.0000s1†† 0.0091†††† 45.45

†† D = 146.8324s2†† 0.0068†††† 34.05

†† G = 195.9978s3†† 0.0051†††† 25.5

†† B = 246.9417s4†† 0.0040†††† 20.248

†† e = 329.6277s5†† 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: // button0on PD2 - E

†††††††††††††††† string = 0;

†††††††††††††††† set_string();

†††††††††††††††† break;

 

††††† case 0x08: // button1on PD2 - A

†††††††††††††††† string = 1;

†††††††††††††††† set_string();

†††††††††††††††† break;

 

††††† case 0x10: // button2on PD2 - D

†††††††††††††††† string = 2;

†††††††††††††††† set_string();

†††††††††††††††† break;

 

††††† case 0x20: // button3on PD2 - G

†††††††††††††††† string = 3;

†††††††††††††††† set_string();

†††††††††††††††† break;

 

††††† case 0x40: // button4on PD2 - B

†††††††††††††††† string = 4;

††††† †††††††††††set_string();

†††††††††††††††† break;

 

††††† case 0x80: // button5on 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