Robo Kit jako line follower

Tu pokazujemy jak o co chodzi z line followerem

O co chodzi?

Przyświecała nam idea stworzenia zestawu dzięki któremu można w przyjemny sposób rozpocząć przygodę z robotyką. Prostota obsługi jest tu priorytetem, dlatego też zdecydowaliśmy się na wykorzystanie gotowych modułów do realizacji jak największej ilości funkcji. Pojazd podążający za linią (line follower) jest najlepszy na początek. W miarę prosty w realizacji, pozwala jednocześnie zebrać pierwsze doświadczenia.

Zasada działania, czyli teoria do pominięcia

Jak sprawić by robot widział linię? Żeby odpowiedzieć sobie na to pytanie, należy wpierw zadać sobie inne: W jaki sposób my widzimy? Czemu nocne niebo jest czarne, kartka jest biała, a liście zielone? Wszystko to wynika ze zdolności do odbijania światła. A w zasadzie – do zdolności odbijania fali o konkretnej długości. Liście są zielone, bo zawarty w nich chlorofil odbija fale elektromagnetyczne o długości odpowiadającej zieleni, resztę pochłania. W ten sam sposób – dno studni czy nocne niebo wydaje się nam czarne, bo światło (fale EM) są przez nie pochłaniane. Właśnie z tej własności skorzystamy budując naszego robota.

Jako oczka followera wykorzystamy transoptory odbiciowe CNY70. Transoptor to zestaw diody i fototranzystora. W tym wypadku jest to dioda podczerwona. Podczerwień to fala EM na tyle długa, że ludzkie oko jej nie widzi. Podlega ona jednak tym samym prawom co światło widzialne – “czerń” ją bardzo dobrze pochłania, a “biel” bardzo dobrze odbija. Dzięki temu transoptor położony na kartce będzie dobrze przewodził, z kolei położony na taśmie izolacyjnej – nie będzie przewodził prawie w ogóle.

Umieszczając kilka transoptorów w jednej linii będziemy mogli określać gdzie znajduje się czarna linia, którą ma śledzić nasz robot.

Sposób podłączenia

Podłączenie CNY70:
CNY70, wyprowadzenia CNY70, ponumerowane wyprowadzenia

Między pin numer jeden, a zasilanie wpinamy rezystor 220 Ohm, pin numer dwa podłączamy do masy. Do pinu numer 4 równolegle wpinamy rezystor 50k Ohm oraz wyjście do pinu analogowego w Arduino, a pin nr trzy podłączamy do masy.

Jak widać, to czy transoptor przewodzi będziemy sprawdzać za pomocą funkcji analogRead(). Rezystory dobrane zostały na podstawie opisu czujnika na stronie producenta oraz wyciągając wnioski z pomyłek własnych i innych.

Program obsługujący:

#include <MotorShield.h>

#define predkosc 140
#define predkosc2 110
#define wartosc 900
MS_DCMotor lewy(MOTOR_B);
MS_DCMotor prawy(MOTOR_A);
void sprawdz(struct odczyty &odczyt);
void steruj(struct odczyty odczyt);
void drukuj(struct odczyty odczyt);

Korzystamy z biblioteki napisanej przez kogoś ze społeczności Arduino do obsługi Motor Shielda, którą można
pobrać tutaj.

Funkcja “sprawdz” odpowiada za odczyt napięcia za pomocą pinów analogowych i zapisanie odczytu do struktury. Stała “predkosc” i “predkosc2″ to kolejno, wypełnienie silników gdy robot jedzie prosto i skręca. Z kolei “wartosc” to nasz punkt odniesienia – jeśli funkcja analogRead() zwróci wartość większą niż 900 to czujnik jest umieszczony nad taśmą izolacyjną, a dla wartości mniejszej – nad kartką. Te trzy stałe są wielkościami dobranymi metodą prób i błędów, może się więc zdarzyć, że będziecie musieli je ustawić samodzielnie ;). Tak samo jak z ustawianiem fotela kierowcy, czy dostrajaniem radia.

Dam przykład: gdy zasilałem model baterią o napięciu 7.4V i dużej pojemności – takie wartości były dobre, z kolei gdy podłączyłem robota do zasilacza ustawionego na 6v, musiałem je podwyższyć. Podczas skrętu, jeden silnik nie dawał rady pokonać tarcia, jednak przy wypełnieniu 150 (predkosc2 = 150) już był w stanie to zrobić. Jak widać, zasada jest taka, że im niższe napięcie zasilania, tym większe musi być wypełnienie PWM to zrekompensować. Dlatego zawsze patrzcie na diody wbudowane w MotorShield, one mówią który silnik jest zasilany, czyli które koło powinno się kręcić.

void sprawdz(struct odczyty &odczyt)
{
odczyt.przew = analogRead(2);
odczyt.prwew = analogRead(3);
odczyt.lewwew = analogRead(4);
odczyt.lewzew = analogRead(5);
}

Funkcja “steruj” analizuje wskazania transoptorów i kontroluje moc silników. Jeśli choć jeden środkowy czujnik (odległość między nimi jest ciut większa niż szerokość taśmy izolacyjnej, w idealnym przypadku fototranzystory obu czujników znajdują się nad czarną linią, a diody już nie) pojazd jedzie do przodu. Jednak jeśli to czujnik umieszczony na obrzeżach płytki znajdzie się nad czarną linią – program wyłączy odpowiedni silnik. W związku z tym, że trasa czasem się przecina pod kątem prostym dodałem warunek – jeśli oba czujniki umieszczone na obrzeżach znajdują się nad czarnym, pojazd ma jechać dalej (drugi “if”). W komentarzu dopisałem funkcję, która zatrzymuje robota gdy ten wyjedzie na kartkę, jednak nie opłaca się jej stosować. Jak sami zauważycie – w większości przypadków, jeśli robot wyjedzie poza linię to będzie kręcił się w kółko do momentu kiedy wróci na linię. Dzieje się tak, gdyż w przypadku wyjechania poza linię program nie zmienia wartości wypełnienia sygnału zasilającego silniki. Po prostu nie ma opisanego takiego przypadku :).

void steruj(struct odczyty odczyt)
{
if(odczyt.lewwew > wartosc || odczyt.prwew > wartosc)
{
prawy.setSpeed(predkosc);
lewy.setSpeed(predkosc); //jedzie na wprost
if(odczyt.lewzew >wartosc && odczyt.przew > wartosc)
{
prawy.setSpeed(predkosc);
lewy.setSpeed(predkosc);
// jedzie dalej
}
if(odczyt.przew > wartosc && odczyt.lewzew < wartosc)
{
//prawy zwalnia
prawy.setSpeed(0);
lewy.setSpeed(predkosc2);
}
if(odczyt.przew < wartosc && odczyt.lewzew > wartosc)
{
//lewy zwalnia
lewy.setSpeed(0);
prawy.setSpeed(predkosc2);
}
}
/* if(odczyt.lewwew < wartosc && odczyt.prwew < wartosc && odczyt.przew < wartosc && odczyt.lewzew < wartosc)
{
lewy.setSpeed(0);
prawy.setSpeed(0);
}
*/
}

Na koniec moja ulubiona, ratująca życie funkcja “drukuj”. Jeśli coś nie działa, dzięki niej łatwo sprawdzić co ;). Na przykład: robot z jakiegoś powodu nie chce się trzymać linii. Po podłączeniu do Arduino, okazuje się, że czujnik nr “X” nie reaguje na linię, ale za to reaguje na światło lampki. Diagnoza – dioda w transoptorze odmówiła współpracy, albo dołączamy gdzieś obok małą diodę IR, albo wymieniamy cały czujnik ;)

void drukuj(struct odczyty odczyt)
{
Serial.print("analog pin 1: ");
Serial.println(odczyt.przew);
Serial.print("analog pin 2: ");
Serial.println(odczyt.prwew);
Serial.print("analog pin 4: ");
Serial.println(odczyt.lewwew);
Serial.print("analog pin 5: ");
Serial.println(odczyt.lewzew);
Serial.println();
}

Podsumowanie:

Właśnie udało Wam się zbudować swojego pierwszego robota :D Do budowy toru, proponuję wykorzystać zwykłą, czarną taśmę izolacyjną, tylko zamiast przyklejać ją bezpośrednio do podłogi – lepiej przykleić ją do kartek ze starego zeszytu i dopiero te kartki przykleić taśmą samoprzylepną do podłogi. Klej z taśmy izolacyjnej strasznie brudzi i ciężko schodzi. Tor powinien być możliwie płaski i równy, bez garbów. Poza tym pamiętajcie, że robot ma spory promień skrętu, więc może Follwer może mieć problemy z pokonaniem zakrętu ostrzejszego niż 90 stopni. Popróbujcie, ponaginajcie granice możliwości :D Poniżej zamieszczam program do pobrania i listę wykorzystanych elementów.

Program i projekt na pewno można udoskonalić, do czego Was gorąco zachęcam. Eksperymentujcie, czytajcie i co najważniejsze – nie zniechęcajcie się. Powodzenia w podbijaniu świata robotyki!

Cały program do pobrania z http://static.nettigo.pl/robo/linefollower.ino