Proiectul constă în realizarea unui robot care urmărește o linie de culoare constrastantă față de suprafața pe care se deplasează.
Am plecat de la ideea de a realiza ceva ce se deplasează de la 0 pentru a ma familiariza cu proiectarea “from scratch” a unui dispozitiz și deoarece mi s-a părut interesant a realiza un robot, indiferent de scopul lui.
Schemă bloc:
Urmărirea liniei se va face cu ajutorul a patru senzori, și anume 4 diode situate în partea din față a robotului ce vor transmite semnal analogic comparatorului pentru a obține valori de 0 sau 1. Comparatorul va trimite aceste valori microcontrolerului. Pe baza programului, microcontrolerul decide mișcarea servomotoarelor.
Atunci când un senzor va fi poziționat deasupra unei suprafețe albe se va transmite valorea 0 microcontrolerului. Când senzorul se află deasupra suprafeței negre valoarea transmisă va fi 1. Astfel în funcție de valorile celor patru senzori, de fapt în funcție de unde se află linia se va decide modul de acționare a servomotoarelor.
Pentru deplasare am folosit 2 servomotoare ce sunt legate fiecare la o roată căreia îi transmit mișcarea. Servomotoarele sunt comandate prin PWM.
Am plecat de la plăcuța realizată în prima etapă:
Listă de piese necesare (fără piesele pentru plăcuța de la etapa I):
Precizez că servomotoarele au inițial un unghi de rotație de 180º. Pentru utilizarea lor în cadrul acestui proiect a fost necesară modificare mecanică pentru a permite o rotație de 360º. Un exemplu în acest sens găsiți la http://www.kronosrobotics.com/an116/GAN116_3003.shtml. Totuși este necesar doar modificarea din poza de mai jos pentru a permite un unghi de rotație de 360º.
Pentru legarea servomotoarelor se utilizează 3 pini:
Controlul servomotorului se realizează prin semnal PWM transmis de microcontroller. Servomotorul compară semnalul PWM primit cu poziția sa curentă și o ajustează corespunzător. Circuitele interne ale servomotorului asteapta un semnal de frecvență constantă 50Hz adică se repetă o dată la 20 ms.
Semnalul trimis servomotorului este HIGH pentru 1-2ms și LOW pentru restul de timp până la 20 ms. Durata cât este semnalul HIGH determină noua poziție a servomotorului.
Plăcuța de senzori arată astfel și a fost preluată dintr-un proiect din anii trecuți:
Partea de comparare arată astfel pentru fiecare senzor:
Iar plăcuța care transformă semnalele analogice în 0 sau 1 arată astfel:
Mediu de dezvoltare: AVRStudio şi Code Vision AVR
Software-ul este simplu. De fiecare dată cînd se doreşte comandarea unui servomotor, se activează enable-ul corespunzător şi se generează PWM.
Pentru a genera semnalul PWM de 50 Hz se foloseşte Phase and Frequency Correct al timerului 1 de pe Atmega16. In acest caz, timer-ul porneşte de la 0, numără până la ICR1 şi coboară înapoi la 0. Pentru ca acest ciclu să dureze 20 ms am optat pentru:
Funcţionare PWM
Din datasheet-ul Atmega16 :
TCNT1 este registrul in care se numara de la 0 la ICR1: la intalnirea pe ramura ascendenta a OCR1A/OCR1B, OC1A/OC1B este pus pe HIGH, iar pe ramura descendenta pe LOW.
O diagrama mai edificatoare in acest sens:
Se poate observa folosirea ambelor canale PWM ale Timerului 1 (A si B). Am decis folosirea ambelor întrucât motoruş stanga se deplasează invers faţă de cel de pe partea dreapta.
Am implementat o funcţie de deplasare înainte:
void move_forward() { PWM_channelA(MOTOR2, 2000); // sTANGA FATA PWM_channelA(MOTOR2, 1000); PWM_channelB(MOTOR1, 1000); // DREAPTA FATA PWM_channelB(MOTOR1, 2000); PORTB = SET; PORTA = SET; OCR1A = 2000; OCR1B = 1000; }
Structura de decizie a direcţiei este:
if (((PINC&_BV(PC5))==0)&&((PINC&_BV(PC4))!=0)){// dreapta interior motorul dreapta sta PWM_channelA(MOTOR2, 2000); PWM_channelA(MOTOR2, 1000); PORTA = SET; OCR1A = 2000; }else if((PINC&_BV(PC4))==0){ // dreapta exterior drepta = MERGE INAPOI PWM_channelB(MOTOR1, 2000); PWM_channelB(MOTOR1, 1000); PORTB = SET; OCR1B = 2000; PWM_channelA(MOTOR2, 2000); PWM_channelA(MOTOR2, 1000); PORTA = SET; OCR1A = 2000; }else{//motorul drept merge inainte PWM_channelB(MOTOR1, 1000); PWM_channelB(MOTOR1, 2000); PWM_channelA(MOTOR2, 2000); PWM_channelA(MOTOR2, 1000); PORTB = SET; PORTA = SET; OCR1A = 2000; OCR1B = 1000; } if (((PINC&_BV(PC7))==0)&&((PINC&_BV(PC6))!=0)) { //stanga interior stanga = sta PWM_channelB(MOTOR1, 1000); PWM_channelB(MOTOR1, 2000); PORTB = SET; OCR1B = 1000; } else if((PINC&_BV(PC6))==0) { //stanga exterior => MERGE INAPOI PWM_channelA(MOTOR2, 1000); PWM_channelA(MOTOR2, 2000); PWM_channelB(MOTOR1, 1000); PWM_channelB(MOTOR1, 2000); PORTA = SET; OCR1A = 1000; PORTB = SET; OCR1B = 1000; } else { PWM_channelB(MOTOR1, 1000); PWM_channelB(MOTOR1, 2000); PWM_channelA(MOTOR2, 2000); PWM_channelA(MOTOR2, 1000); PORTB = SET; PORTA = SET; OCR1A = 2000; OCR1B = 1000; }*/
Line-followerul montat arată astfel:
Am reuşit să-l fac să se deplaseze dar am probleme la circuitu cu senzori.
Destul de greu de realizat, întrucât nu aveam nimic gata făcut. A durat mult chiar şi numai realizarea şasiului.
Probleme mari cu mufele: atât cu mufa USB cât şi cu cea de alimentare: deci atenţie la prima etapă la lipituri.
Din punct de vedere hardware dificil de realizat dar extrem de interesant. Trebuie timp suficient pentru a finaliza proiectul deoarece m-am lovit de foarte multe probleme la care nu ma aşteptam.
Aici e arhiva cu fişierul sursă + Makefile arhiva surse