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.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