Proiectul nostru reprezinta un robot line-follower construit din scheletul unei masinute cu telecomanda.
La fiecare pas, led-urile emit radiatie in infrarosu. Fototranzistorii care joaca rolul de senzori trimit un semnal care variaza invers cu cantitatea de radiatie reflectata de suprafata. Cand ne aflam deasupra liniei negre, se va trimite o valoare mai mare si respectiv, pentru cazul suprafetei lucioase, se trimite o valoare mai aproape de 0. Aceste valori sunt trecute prin convertorul analog digital al microcontrollerului si pe baza acestora se trimit semnale catre motoare astfel incat robotul sa ramana deasupra liniei.
Programul pentru atmega16 a fost realizat folosind compilatorul avr-gcc pentru Linux. Nu s-au folosit librarii si surse altele decat libraria standard C pentru AVR
Cele mai importante elemente din program:
Miscarea inainte-inapoi a robotului este realizata prin Fast - PWM folosind counter-ul 1 al microcontroller-ului. Factorul de umplere pentru avansare este controlat de OCR1B si pentru deplasare inapoi OCR1A.
void go_forward(uint8_t speed) { CLR(PORTD, LEFT); CLR(PORTD, RIGHT); BACKWARD_DRIVE = 0; _delay_ms(10); FORWARD_DRIVE = speed; } void go_left(uint8_t speed) { BACKWARD_DRIVE = 0; CLR(PORTD, RIGHT); SET(PORTD, LEFT); FORWARD_DRIVE = speed; } void go_right(uint8_t speed) { BACKWARD_DRIVE = 0; FORWARD_DRIVE = speed; CLR(PORTD, LEFT); SET(PORTD, RIGHT); } void go_backward(uint8_t speed) { FORWARD_DRIVE = 0; _delay_ms(10); CLR(PORTD, LEFT); CLR(PORTD, RIGHT); BACKWARD_DRIVE = speed; } void full_stop() { FORWARD_DRIVE = 0; BACKWARD_DRIVE = 0; CLR(PORTD, LEFT); CLR(PORTD, RIGHT); }
Senzorii sunt cititi prin multiplexarea pe 4 canale (pinii 0-3 ai portului A) ale convertorului analog-digital incorporat in Atmega16, folosind precizei pe 1024 de biti.
Achizitia de date este realizata in acest mod:
int ADC_get(uint8_t channel) { //setati canalul de pe care vreti sa faceti citirea ADMUX &= 0xE0; ADMUX |= channel; ADCSRA |= _BV(ADEN)| _BV(ADSC); //asteptati sa se termine o conversie while(!(ADCSRA & (1<<ADIF))); //returnati rezultatul conversiei return ADC; } void get_sensors() { int i; for (i = 0; i < SENSOR_NO; i++) { A[i] = ADC_get(i); on_stripe[i] = A[i] > THRESHOLD[i]; } }
Sectiunea din program care realizeaza efectiv controlul masinii este descrisa in continuare:
forever { get_sensors(); delta = on_stripe[0] + on_stripe[1] - on_stripe[2] - on_stripe[3]; if (is_on_white()) { full_stop(); led_on(); _delay_ms(1000); return 0; } if (delta < 0) { led_off(); go_right(SLOWER); } else if (delta > 0) { led_off(); go_left(SLOWER); } else { led_off(); go_forward(FASTER); } }
Montajul final pentru robot este descris in figurile de mai jos:
Desi nu am folosit motoare specialiazate se pot obtine rezultate satisfacatoare atat timp cat controlul este realizat prin PWM. La alegerea masinutei un lucru avut in vedere a fost disponibilitatea acesteia de a lua curbe cu excentricitate mica. Din pacate, din lipsa timpului, nu am apucat sa testam suficient si deci, calibrarea parametrilor nu este cea optima.