Robo Kit, czyli pierwsze kroki z robotyką. Line Follower.

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. Dzięki wykorzystaniu gotowych modułów (Arduino UNO, Motor Shield, gotowe podwozie robota) możemy kolejne roboty budować w oparciu o te same podzespoły. Jednocześnie nie jesteście ograniczeni tylko do robotów – Arduino może być sercem projektów niemających nic wspólnego z robotyką.

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.

Sposób podłączenia:

Montaż czujników na uniwersalnej płytce możecie znaleźć na stronie akademia.nettigo.pl

Końcowy montaż płytki oraz instrukcja podłączenia znajduje się tutaj

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);

Deklaracja zmiennych i użytych funkcji. 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. Wszystkie roboty z detekcją linii działają na tej samej zasadzie, w internecie można spotkać wiele projektów opartych na m. in.: attiny2313, atmega168 czy na atmega328p – takiej jak w Uno, jednak programowanie gołych scalaczków może sprawić trudności początkującym. 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, wyglądajcie kolejnych wpisów ;)

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