2005-12-11 Linjeföljare Digitala projekt Johan Engström e02je Henrik Persson e02hp
Abstract This project is about how we built a line follower. The project-course is given by the It-institution of LTH and is called Digital project. A circuit board and two electrical motors that are placed on the rear axis build the chassis of the line follower. By using two IR diodes we can detect the line. The two photo diodes are then emitting the IRlight. By the microcontroller, AVR Atmega16, the two motors are then regulated two give a comfortable speed of the car. The code to the microcontroller is written in the program language C.
Innehållsförteckning Kravspecifikation...2 Funktionsbeskrivning...2 Genomförande...3 Hårdvaran...3 Komponentlista...4 Mjukvaran...4 Resultat av projektet...5 Slutsats av digitala projekt...5 Bilaga 1, C-kod... Bilaga 2, kretsschema...
Kravspecifikation Tanken med linjeföljaren är precis som det låter att ett lego-byggt fordon skall följa en linje som är markerad på en yta. Vårt krav på fordonet är såklart att den skall kunna följa linjen, även som linjen viker av åt olika håll. Dessutom vill vi få den till att så snabbt som möjligt kunna göra detta. Våra kompisar, Fredrik Boberg och Axel Gustafson, läser också Digitala Projekt kursen nu och dom bygger också en linjeföljare. Därför blir nästa mål ganska självklart, vår bil skall vara bättre än deras. Så här tidigt i projektet kan det vara ganska svårt att säga vilka olika delar i systemet som behövs för att uppfylla våra krav. Men en av de tyngsta delarna kommer förmodligen att bli att designa vår hjärna på bilen. Tanken är att vi skall använda oss av en AVR ATmega16 processor för att sköta styrningen över hela systemet. Funktionsbeskrivning Eftersom våran konstruktion skall följa en el-tejps linje i marken måste vi ha någon form av inläsningen som kan berätta för oss var bilen befinner sig i förhållande till tejplinjen. Detta görs med två diodpar. Varje par består utav en IR-diod samt en fotodiod. När IR dioden sänder ut ljuset på marken så emitterar fotodioden ljuset och genererar en spänningen. Beroende på om ljuset emitteras ifrån el-tejpen eller från golvet runt om kring, så blir spänningsnivån olika. Spänningarna skickas sedan in till AVR:en som behandlar signalerna genom beräkningar. Signalerna skickas sedan vidare till en H-brygga där dom pulsas ut till motorerna. Att motorerna är pulsade krävs eftersom vi vill styra varje motor separat. Till dom fyra ingångarna på H- bryggan, In1-In4, skickas våra styrsignaler ifrån processorn. Dom pulsas sedan ut till våra två motorer via utgångarna Out1-Out4. För att se kopplingsschemat över H- bryggan så titta i figur 1. Figur 1, kopplingsschema över H-bryggan 2
Genomförande Efter det att vi skrivit klart våran kravspecifikation och bestämt exakt för vad bilen skulle klara av började vi med att leta efter material. I kravspecifikationen står det att vi skulle bygga ett lego-fordon. Men så blev det inte. Istället fick vi en komplett bakaxel med två likströmsmotorer som hade en perfekt utväxling till vårat ändamål. På bakaxeln satte vi sedan vårat kretskort med komponenter och det utgjorde på så sätt vårat chassi på bilen. Framhjulet bestod utav en kula som satt fast i en led. Lys- och fotodioderna är monterade ungefär i mitten på kortets undersida så nära underlaget som möjligt. För att förstärka spänningsskillnaden över dioderna så användes ett 10MΩ motstånd i serie. Signalen skickas sedan in till AVR:en där den förstärks och behandlas. Från processorn skickas sedan signalen vidare i pulser till H- bryggan som kan ge varje motor antingen full eller ingen gas alls med cirka 4ms uppdateringstid. Hårdvaran Nedan så vissas en schematisk skiss över hur de olika hårdvarue komponenterna är ihopkopplade, figur 2. Batteripacket är på 2000mAh, vilket gör att vi kan köra med bilen i ungefär 15 min. För ett komplett kopplingsschema över konstruktionen, se appendix 1. På vårat kretskort finns även en del strökondensatorer inkopplade för att plocka bort så mycket störningar som möjligt. Batteri IR- fotodioder AVR ATmega16 H-brygga M1 M2 Figur 2, schematisk bild över hårdvaran 3
Komponentlista Nedan så har vi skrivit ner de olika komponenter som ingår i våran hårdvara. AVR ATmega 16, 8-bitars mikrokontroller 2st fotodioder 2st IR-dioder 1st H-brygga (dual full-bridge driver L298) 2st likströmsmotorer, kompletta med utväxlad bakaxel från Tamiya Batteri pack, 6V Diverse motstånd och kondensatorer Mjukvaran Programmeringen som används bygger på en enkel princip, läs av värdena på dioderna och sedan avgöra vilken motor som ska driva. Inläsningen till processorn sker via den inbyggda AD-omvandlaren. AD-omvandlaren jämför de båda spänningssignalerna och sparar undan värdena i en vektor som sorteras i realtid. Efter inläsning av 12 värden väljs medianvärdet och detta värde bestämmer åt vilket håll bilden ska svänga, eller om den ska fortsätta efter föregående värde. Motorstyrningen sker med hjälp utav en avbrottsrutin som gör att vi får en cyklisk process. Programmet bestämmer hur långa dessa pulser är och kan variera motorerna effektivt. Under drift körs motorerna typiskt den ena med 5 % och den andra på 50 %. Om högre hastigheter väljs hinner inte inläsningen med att läsa av linjen. 4
Resultat av projektet Bilen är nu färdigbyggd och fungerar faktiskt väldigt bra. Det enda problemet som vi har är när den körs på ganska så mörkt golv. Då blir det problem vid inläsningen och potential skillnaden blir för liten över dioderna. I kravspecifikationen skrev vi ju också att bilen skulle ha varit uppbyggd i lego. Men så blev det inte. Chassiet består istället av ett kretskort eftersom detta passade mycket bättre till det redan färdiga bakaxel paketet som vi fick av Bertil. Det lilla kittet ifrån Tamiya fungerar perfekt till sådana här ändamål. Tyvärr så gav motorerna ifrån sig en väldig massa störningar som gjorde att pulserna till H-bryggan kunde se lite konstiga ut på oscilloskopet. Detta problemet kom vi dock runt med hjälp av kondensatorerna. Programmeringen var ett litet knepigt kapitel det med eftersom vi inte alls har sysslat med C-programmering tidigare. Men man får se det som att vi har blivit en erfarenhet rikare! Slutsats av digitala projekt Att få bygga någonting eget är något som saknas enormt i dom obligatoriska kurserna på LTH. Att därför läsa digitala projekt är något som dom flesta borde göra. I den här kursen lär man sig att knyta an alla sina teoretiska tankar och producera något verkligt av dom. En sak som man skall tänka på är att det tar mer tid än vad man från början tänkt sig. Under arbetsförloppet stöter man garanterat på problem och saker som inte riktigt blir vad man hade tänkt sig ifrån början. Men allt sådant är bara nyttigt och lärorikt. Vi rekommenderar starkt denna kurs för dig som är sugen på att välja den. 5
Bilaga 1 #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <inttypes.h> int m1=2,m2=2,var=0; uint16_t result[12],sort[12]; int16_t temp,tal,k,i,j,temp2,counter; void main(void) { DDRD = 0xff; DDRC = 0xc0; PORTD = _BV (6); while(1) { return; TCNT1H = 0x00; TCNT1L = 0x00; //Timerfunktionen startas med avbrott TCCR1A = _BV (WGM10) _BV (WGM11) _BV (COM1A1) _BV(COM1A0) _BV(COM1B1) _BV(COM1B0); TCCR1B = _BV (CS11); TIMSK = _BV (TOIE1); ADCSR = _BV(ADPS0) _BV(ADPS1) _BV(ADPS2); sei(); INTERRUPT (SIG_ADC) //AD-omvandling klar { result[counter] = ADCL; result[counter] = (int)adch<<8; temp = temp + result[counter]; j=counter; sort[j] = result[counter]; while(j>0){ //sortering av vektorn j--; if(sort[j+1]<sort[j]){ temp2 = sort[j]; sort[j] = sort[j+1]; sort[j+1] = temp2; if(counter==11){ if(1){ tal = sort[6]; //tar median värdet av de inlästa if((tal>550)&(tal<980)){ PORTC = 0x80; //grön diod if(1){
if(1){ m2=9; m1=1; if((tal<500)&(tal>=40)){ PORTC = 0x40;//röd diod if(1){ m1=9; if(1){ m2=1; k=0; i=12; while(j>0){ //rensar vektorn i--; sort[i]=0; temp = 0; counter++; if(counter==12){ counter=0; INTERRUPT (SIG_OVERFLOW1) //timeravbrott { if(var<m1){ PORTD = _BV (3); if(var>=m1){ PORTD &= ~_BV (3); if(var<m2){ PORTD = _BV (1); if(var>=m2){ PORTD &= ~_BV (1); var++; if(var>=15){ var = 0; k=1; ADMUX= _BV(MUX3) _BV(MUX0) _BV(REFS0) _BV(REFS1); ADCSR =_BV(ADEN) _BV(ADSC) _BV(ADIE); //AD-omvandlaren startar
Bilaga 2