//ECE 476 Final Project //Ultrasonic ParKontroller //Mauricio Rodriguez Saenz (mar97), James Juwon Lee (jjl49) //Spring 2007 #include #include #include #define begin { #define end } #define terminator 15 //Hex value for the enter key #define LCDwidth 16 //LCD fits 16 characters char lcd_buffer[17]; int pulse_counter; //counts continuous pulses that did not get a pong int light_timer; //var used to flash LEDs int pong_timer; //counts how many cycles it took to receive a pong int count; //counter used to create pulses for the ping int v1, v2, v3, v4, v5, v6, v7; //vars used to determine a running average of the distance measured int avg; //holds running average value of distance measured int total_count; //debugging var used for LCD display int dist; //value of distance measured char c; //debugging var used for LCD display int timer; //used to create sound pulses //#asm // .equ __lcd_port=0x15 //#endasm //#include // LCD driver routines //procedure that flashes LEDs void light_flashing(void); //This interrupt works with timer2 //It runs at 160 kHz and on Compare on Match it clears OC2 on compare interrupt [TIM2_COMP] t2_compare(void) begin //divides the interrupt by four to create 40 kHz pulses that drive the emitter //Usually sends 5 pulses at a time to enhance functionality //although sometimes it works better with less or more pulses //set the output of PORTB.0 to high //only PORTB.0 is set as an output if((count==0) || (count==4) || (count==8) || (count==12) || (count==16))// || (count==20)) begin PORTB = 0xff; end //clears PORTB.0 if((count==2) || (count==6) || (count==10) || (count==14) || (count==18))// || (count==22)) begin PORTB = 0xfe; if (count==2) begin //after first high we set the timer to run pong_timer = 0; end TCNT1 = 0; end count++; //after an approriate waiting time for the pong we reset vars to send pulses again //we wait 4.375 mSec if(count==700) begin count = 0; pulse_counter++; end pong_timer++; end //Procedure that flases LEDs according to the distance of the object to the sensors //We have 6 different ranges //Limited by the minimum and maximum distance that can be read void light_flashing(void) begin light_timer++; if ((avg>0) && (avg <= 15)) begin PORTA = 0x3f; end else if ((avg > 15) && (avg <= 20)) begin PORTA = 0x1f; end else if ((avg > 20) && (avg <= 25)) begin PORTA = 0x0f; end else if ((avg > 25) && (avg <= 30)) begin PORTA = 0x07; end else if ((avg > 30) && (avg <= 35)) begin PORTA = 0x03; end else if (avg > 35) begin PORTA = 0x01; end end //Procedure that emits sound according to the distance of the object to the sensors //We have 6 different ranges //Limited by the minimum and maximum distance that can be read //We produce the beeping sound by setting and clearing TCCR0 //When set TCCR0 runs at approximately 4 kHz toggling OC0 void sound_gen(void) begin if(timer==0) begin TCCR0=0; end if((avg>0) && (avg <= 15)) begin if(timer==3) begin TCCR0 = 0x1c; end timer++; if(timer>=6) begin timer = 0; end end if((avg>15) && (avg <= 20)) begin if(timer==5) begin TCCR0 = 0x1c; end timer++; if(timer>=10) begin timer = 0; end end if((avg>20) && (avg <= 25)) begin if(timer==6) begin TCCR0 = 0x1c; end timer++; if(timer>=12) begin timer = 0; end end if((avg>25) && (avg <= 30)) begin if(timer==7) begin TCCR0 = 0x1c; end timer++; if(timer>=14) begin timer = 0; end end if((avg>30) && (avg <= 35)) begin if(timer==8) begin TCCR0 = 0x1c; end timer++; if(timer>=16) begin timer = 0; end end if(avg>35) begin if(timer==9) begin TCCR0 = 0x1c; end timer++; if(timer>=18) begin timer = 0; end end end void main(void) begin TCCR2=0x09; //16 MHz clock and CTC = 160 kHz OCR2 = 49; TCCR0 = 0; OCR0 = 7; //Only timer2 is enabled to interrupt //in this way we ensure that timer0 does not interfere with our main timer TIMSK = 0x80; DDRB = 0x01; //PortB is an input, except for PORTB.0 PORTB = 0x00; DDRA = 0xff; //PortA is an output PORTA = 0; pulse_counter = 0; light_timer = 0; pong_timer = 0; count = 0; c=1; v1=0; v2=0; v3=0; v4=0; v5=0; v6=0; v7=0; total_count = 0; timer = 0; //This code we keep at hand for debugging /* lcd_init(LCDwidth); //initialize the display lcd_clear(); */ //PushState = NoPush; //Example LCD display /* lcd_clear(); lcd_gotoxy(0,1); sprintf(lcd_buffer,"%-i",value); lcd_puts(lcd_buffer); lcd_gotoxy(0,0); lcd_putsf("DONE!! HIT C"); */ //lcd_init(LCDwidth); //initialize the display //lcd_clear(); #asm sei #endasm while(1) begin //Only goes in if all 5 pulses have been sent //reason being that when emiting the pulses the receiver gets some noise that //could be taken as a receive signal if ((count>=40) && (PINB.1)) begin //first thing we do is store the number of cycles that elapsed before receiving pong v1=pong_timer; //resolution comes out to 16 kHz or 6.25 micros per tick // 6.25 microSec * 340 m/Sec = .2125 cm v1 = ((int)(((double)v1)*.2125)/2.0); //distance calculated in cm pulse_counter = 0; //calculation of running average with previous 7 readings avg = (v1+v2+v3+v4+v5+v6+v7)/7; v2 = v1; v3 = v2; v4 = v3; v5 = v4; v6 = v5; v7 = v6; total_count++; //With the average calculated we emit sound sound_gen(); //Debugging code that displays useful info on LCD /* if ((c==1) && (total_count==7)) begin lcd_clear(); lcd_gotoxy(0,0); sprintf(lcd_buffer,"%-i",dist); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); sprintf(lcd_buffer,"%-i",v1); lcd_puts(lcd_buffer); lcd_gotoxy(0,0); lcd_putsf("Distance = "); lcd_gotoxy(11,0); sprintf(lcd_buffer,"%-i",avg); lcd_puts(lcd_buffer); c++; total_count = 0; end /* if ((c==2) && (total_count==7)) begin lcd_gotoxy(8,0); sprintf(lcd_buffer,"%-i",avg); lcd_puts(lcd_buffer); c++; total_count = 0; end if ((c==3) && (total_count==7)) begin lcd_gotoxy(14,0); sprintf(lcd_buffer,"%-i",avg); lcd_puts(lcd_buffer); c++; total_count = 0; end */ light_flashing(); end //After 20 pulses without a pong it goes into OFF mode if(pulse_counter >= 20) begin PORTA = 0x00; TCCR0 = 0; end end // end while end //end main