Scopul proiectului nostru consta in realizarea unui robot pornind de la scheletul unei masinute teleghidate. Functiile acestui robot vor fi urmarirea unei linii negre pe o suprafata alba, cat si detectarea unui obstacol aflat in fata deplasarii sale.
Principala functie a robotului va fi aceea de “line follower”. Acesta va urmari linia neagra pe o suprafata alba, cu precizarea ca grosimea liniei negre va trebui sa fie suficient de mare incat sa nu genereze erori de logica si sa determine o functionare nedorita.
Ceea ce aducem in plus fata de robotelul line follower este detectarea unei viitoare coliziuni si evitarea obstacolului (neautomatizata). Logica este urmatoarea: in momentul in care robotul detecteaza un obstacol (la o distanta rezonabila fata de el), se va opri din miscare si va trece pe “regim manual”, adica se va realiza controlul prin telecomanda. In momentul in care senzorii detecteaza din nou linie neagra (si nu mai detecteaza un obstacol), robotul va trece din nou pe regim automat si va urmari linia.
Pentru realizarea partii hardware am pornit de la un schelet de masinuta teleghidata si placuta realizata de noi pentru prima etapa a proiectului. In continuare prezentam principale piese hardware folosite in plus:
Diagrama bloc pentru urmarirea liniei:
Scheme electrice - TODO
Urmatoarea secventa reprezinta algoritmul clasic pentru detectarea liniei:
Pentru ocolirea obstacolului manual se va folosi urmatorul algoritm:
In continuare se poate vedea codul sursa scris in C:
#include <avr/io.h>
#ifndef F_CPU #define F_CPU 16000000UL #endif
#include <avr/interrupt.h> #include <util/delay.h>
#define ALTERATION 7 #define ITERATIONS 3 #define WAIT 100
void moveForward(){
PORTD |= (1<<PD0); PORTD &= ~(1<<PD1);
}
void stopMoveForward(){
PORTD &=~ ((1<<PD0) | (1<<PD1));
}
void moveBackward(){
PORTD |= (1<<PD1); PORTD &= ~(1<<PD0);
}
void stopMoveBackward(){
PORTD &=~ ((1<<PD0) | (1<<PD1));
}
void turnRight(){
PORTD |= (1<<PD2); PORTD &= ~(1<<PD3);
}
void stopTurnRight(){
PORTD &=~ ((1<<PD3) | (1<<PD2));
}
void turnLeft(){
PORTD |= (1<<PD3); PORTD &= ~(1<<PD2);
}
void stopTurnLeft(){
PORTD &=~ ((1<<PD2) | (1<<PD3));
}
void moveLeft(){
moveForward(); turnLeft();
}
void stopMoveLeft(){
stopMoveForward(); stopTurnLeft();
}
void moveRight(){
moveForward(); turnRight();
}
void stopMoveRight(){
stopMoveForward(); stopTurnRight();
}
void Main_Init(){
DDRD = 0xFF; PORTD = 0x00;
DDRB = 0x00; PORTB = 0xFF;
PORTD |= (1<<PD4); PORTD |= (1<<PD5);
//sei();
}
int main(){
int i; int m = 0; Main_Init();
while (1){
// Verificare obstacol if (PINB &(1<<PINB1) ){ // Nu deteteaza nimeni nimic if ( (PINB & (1<<PINB0)) && (PINB & (1<<PINB2)) ){ moveForward(); for(i=0; i<ITERATIONS; i++) _delay_ms(WAIT); stopMoveForward(); }
// Detecteaza senzoru dreapta if ( !(PINB & (1<<PINB0)) && (PINB & (1<<PINB2)) ){ moveRight(); for(i=0; i<ITERATIONS+ALTERATION; i++) _delay_ms(WAIT); stopMoveRight(); } // Detecteaza senzoru stanga if ( (PINB & (1<<PINB0)) && !(PINB & (1<<PINB2)) ){ moveLeft(); for(i=0; i<ITERATIONS+ALTERATION; i++) _delay_ms(WAIT); stopMoveLeft(); }
} _delay_ms(WAIT); }
return 0;
}
Download softul: soft.zip
In final, am reusit sa obtinem un line follower functional care se opreste la detectarea unui obstacol. Nu am reusit sa implementam si partea de trecere inapoi pe controlul telecomenzii.
De observat ca desi robotelul functioneaza corect, din cauza ca masinuta este ceva mai veche, miscarea nu este atat de fluenta sau exacta cat ne-am fi dorit. Miscarile dreapta/stanga sunt putin cam slabe, iar miscarea inainte este cam prea rapida, uneori putand sari de pe traseu.
Proiectul a fost interesant si ne-a facut placere sa lipim fire, chiar daca de multe ori acestea erau prea subtiri si firave pentru nervii si rabdarea noastra :) Ar fi trebuit sa lucram pe placuta imprimata, dar ne-am dat seama prea tarziu de asta.
TODO