Robotépítés kezdőknek

Robotépítés kezdőknek

VONALKÖVETŐ ROBOT - HARMADIK RÉSZ

2017. december 07. - FizikusRobotBlog

Elérkeztünk a vonalkövető robot építéséről szóló cikksorozat befejező részéhez, amelyben a robot programozásáról, teszteléséről és a továbbfejlesztési lehetőségekről lesz szó.

vk2-11.jpg

Programozás
A robot programozása az építés utolsó lépése. Ebben a részben a robotot megtanítom "gondolkodni" (beprogramozom hogy az egyes környezeti ingerekre (az érzékelők jeleire) miként is válaszoljon).

Mielőtt elkezdenénk a robot programozását, egy vonalkövető algoritmust kell létrehozni, ami megszabja, hogy a vonalérzékelő szenzor jeleire hogyan reagáljon a robot. Ehhez legelőször a vonalérzékelő szenzorokat kell kalibrálni, hogy meghatározzuk azokat a konstansokat, amelyek a robotvérlő program számára szükségesek. A robot pontos irányítása érdekében azt is meg kell vizsgálni, hogy a motorvezérlő parancsokra hogyan reagál a robot.

Vonalérzékelő szenzor tesztélese
Mielőtt a vonalérzékelő szenzorokat használni tudnánk, elemezni kell az általuk szolgáltatott jeleket, hogy el tudjuk dönteni mikor van egy adott szenzor a vonal felett és mikor a padló felett. Az LDRteszt.ino Arduino programmal beolvastam a bal és jobb oldali szenzorok jeleit, majd a mért értékeket soros porton elküldtem a PC-nek. A mért értékeket az Arduino soros monitorán jelenítettem meg. A vonalérzékelő szenzorokat először a vonal, majd a padló fölé helyeztem. A mért értékeket az alábbi táblázat mutatja:

vk3-1.jpg

Ha a szenzor a vonal felett van, akkor az ADC értéke 770-780 körül van. Ha a padló felett, akkor pedig 910-920 körül. Ezért határértéknek 820-at választottam. Ha egy szenzor értéke ezen határértéknél kisebb, akkor azt úgy értelmezem, hogy a szenzor a vonal felett van. Ha a határértéknél nagyobb, akkor pedig úgy hogy a padló felett van. A szenzorok teszteléséhez használt LDRteszt.ino Arduino1.0 kód:

// LDRteszt Arduino 1.0 kod

int BalLDR = 4; // Bal szenzor A4-re kotve

int JobbLDR = 5; // Jobb szenzor A4-re kotve

int balfenyero; // Bal szenzor ADC erteket tarolo valtozo

int jobbfenyero; // Jobb szenzor ADC erteket tarolo valtozo

void setup()

{

Serial.begin(9600); // 9600 baud-sebessegu soros kommunikacios port

beallitasa

}

void loop()

{

balfenyero = analogRead(BalLDR); // Bal szenzor ertekenek beolvasasa (0-

1023 kozotti ertek)

jobbfenyero = analogRead(JobbLDR); //Jobb szenzor ertekenek beolvasasa

(0-1023 kozotti ertek)

Serial.print("Bal: ");

Serial.print(balfenyero, DEC); //

Serial.print(", Jobb: ");

Serial.println(jobbfenyero, DEC); // a mert ertekek kiiratasa

delay(500); // Varakozas 0.5 masodpercig (500 ms)

}

 

Motorvezérlés tesztelése
A robotnál ugyanolyan áttétellel rendelkező, megegyező típusú DC motorokat használtam. Ettől függetlenül a két motor működési paraméterei eltérőek. Ugyanazzal a PWM jellel meghajtva őket más-más sebességgel fognak forogni. Ha azt akarjuk hogy a robot egyenesen tudjon haladni, akkor ezt mindenképpen ki kell küszöbölni. Ez is többféleképpen tehető meg.

Használhatunk pl. a motorok tengelyére erősített, résekkel ellátott tárcsát, amelyek forgását egy optokapuval detektálhatjuk. Ezáltal gondoskodhatunk arról, hogy előre haladásnál a két motor azonos sebességgel forogjon. Ha a két motor különböző sebességgel forog, akkor a gyorsabbat lassítani kell, vagy a lassabbat gyorsítani.

vk3-2.jpg

A vonalkövető robotnál ennél egyszerűbb, bár kevésbé megbízható megoldást használtam. A motorok teszteléséhez egy potenciométert kötöttem az A0 analóg bemeneti lábra, és azzal változtattam a motorokat meghajtó PWM jelet. A motormeghajtó függvények értékét kiírattam a PC-re is. A motorok elindulásához tartozó értékeket az alábbi táblázat tartalmazza:

vk3-3.jpg

Látható, hogy a két motor közötti különbség kezdetben 20 körül van, de ez a sebesség növekedésével fokozatosan csökken. A motorokra adott PWM jeleket egy offszet értékkel megváltoztattam egymáshoz viszonyítva. A kerekekre ragasztotam egy markert, és megkerestem azt az értéket, amelynél a 2 kerék azonos sebességgel forgott. Ekkor a bal motor sebessége 98%, a jobb motoré pedig 100% volt.

Ennek a megoldásnak az a hátránya, hogy az offszet értéke sok paramétertől függ (például a motorokat meghajtó telepek feszültségétől), ezért ahogy az elemek merülnek, a robot irányítását is korrigálni kell (tehetünk a robotra például egy potenciométert, amivel a 2 motor közötti offszet értékét változtathatjuk, de a robot egyszerűbbé tétele miatt ezt elhagytam...).

 

Vonalkövető algoritmus

Miután már tudjuk értelmezni a vonalérzékelő szenzor adatait, és a robotunk tud egyenesen haladni, nekiállhatunk a vonalkövető algoritmus és a robotvezérlő program elkészítésének.

Bekapcsolás után az ADC-vel beolvassuk először a jobb, majd a bal oldali LDR érzékelővel mért fényerősséget (a fényerősséggel arányos feszültséget). A mikrovezérlő a vonal pozíciójától függően úgy irányítja a robotot (úgy változtatja a robotot meghajtó DC motorok sebességét és forgásirányát), hogy a vonal mindig a két szenzor között maradjon. Ha a bal oldali szenzor van a vonal felett (a bal oldali szenzor által mért fényerősség a beállított határértéknél kisebb), akkor a robot balra fordul (C). Ha a jobb oldali szenzor van a vonal felett (a jobb oldali szenzor által mért fényerősség a beállított határértéknél kisebb), akkor a robot jobbra fordul (D). Ha mindkét detektor jele a megadott határértéknél nagyobb (a vonal a két érzékelő között van), vagy ha mindkét detektor jele a megadott határértéknél kisebb ( a robot kereszteződéshez ért), akkor a robot megy előre (A és B). A határérték változtatásával lehet a robotot a környezeti fényviszonyokhoz hangolni. A következő ADC mérés előtt a mikrovezérlő várakozik 50 ms-ig. Ez az esetlegesen fellépő oszcillációk csökkentésére szolgál.

vk3-4.jpg

A robotot irányító algoritmust az alábbi táblázatban foglahatjuk össze (Ha a szenzor a vonal felett van, akkor az ADC értéke a határértéknél kisebb. Ezt az állapotot 1-essel jelöltem. Ha a szenzor a padló felett van, akkor az ADC értéke a határértéknél nagyobb. Ezt az állapotot 0-val jelöltem):

vk3-5.jpg

Folyamatábrán is ábrázolható a vonalkövető robotot irányító algoritmus:

vk3-6.jpg

A fenti algoritmust kell lekódolni az Arduino nyelvre.

Arduino fejlesztőkörnyezet
Az Arduino hardvert és fejlesztői környezetet egy korabbi posztban mar részletesen ismertettem. 

Vonalkövető Robot Arduino-val (Programozás/Tesztelés)
Arduino használata esetén elég egyszerű dolgunk van. A fejlesztői környezet eltakarja előlünk a hardvert, ezért nem kell részletesen ismerni a mikrovezérlő működését. Az AVR mikrovezérlő és a beépített perifériák használata legtöbbször néhány egyszerű paranccsal megoldható. A robotunk programozásához is csak azt kell tudnunk, hogy az I/O lábak állapotát hogyan tudjuk változtatni (a motorok forgásirányának a beállítsához), hogyan tudunk PWM jelet létrehozni (a motorok sebességének a beállítsához), és hogyan tudjuk megmérni ADC-vel a két szenzoron lévő feszültséget (a vonal érzékeléséhez).

Az Arduino programnak tartalmaznia kell egy setup() és egy loop() függvényt, különben nem fog működni. A (void) arra utal, hogy a függvény a meghívása után nem ad vissza eredményül semmilyen adatot. Az üres zárójel pedig arra utal, hogy a függvény hívásakor mi sem adunk meg semmilyen paramétert a függvénynek. A setup() csak egyetlen egyszer fut le a program legelején, mielőtt a programunk fő ciklusa elindulna. Ezért a steup() részben adhatjuk meg a főbb beállításokat, általános utasításokat, eszköz inicializálásokat (pl. lábak adatirányának beállítása, soros kommunikáció sebességének beállítása stb…). A loop() függvény lényegében a főprogram, ami folyamatosan fut és ismétlődik mindaddig amíg az Arduino panel be van kapcsolva.

A robotvezérlő program feladata egyszerű: beolvassa a vonalérzékelő szenzorok jeleit, amelyek alapján meghatározza a robot válaszát és ennek megfelelően vezérli a motorokat.

vk3-7.jpg

A program legelején a könnyebb érthetőség miatt elnevezem a motorvezérlő Pin4 - Pin7 lábakat, majd a setup() részben a pinMode paranccsal kimenetnek definiálom őket (a lábak alapértelmezésben bemenetnek vannak definiálva, ezért azokat nem kell megadni). Az alábbi függvények szükségesek az Arduino lábak beállításához és kezeléséhez:

pinMode(láb, mód); - a lábak adatirányát állíthatjuk be ezzel az utasítással (INPUT: bemenet, OUTPUT: kimenet).

digitalWrite(láb, érték); - ha egy lábat kimenetnek állítottunk be, akkor ezzel az utasítással az állapotát magasra (HIGH - +5V), vagy alacsonyra (LOW – 0V) állíthatjuk.

analogWrite(láb, érték); - ha egy lábat kimenetnek állítottunk be, és a láb képes PWM-re, akkor ezzel az utasítással adhatunk rá PWM jelet. A függvénynek paraméterként egy 0 - 255 közötti értéket kell megadni a kitöltési tényező beállításához

analogRead(láb); - ezzel az utasítással mérhető meg ADC-vel egy analóg lábon lévő feszültség. A függvény 0 - 1023 közötti értéket ad vissza eredményül.

A főprogram legelején, a loop() végtelen cikuls folyamatosan beolvassa az analogRead() utasítással a jobb és bal szenzor jeleit a BalLDR és JobbLDR nevű változókba. Az if() és else if() utasítások azt vizsgálják, hogy melyik szenzor van a vonal vagy a padló felett, és ettől függően a korábban tárgyalt vonalkövető algoritmusnak megfelelően úgy vezéreli az Arduino a motorokat, hogy a követendő vonal mindig a két szenzor között legyen.

A robot irányításának a leegyszerűsítése érdekében létrehoztam a MotorBal és MotorJobb motorvezérlő függvényeket. A függvényeknek 100 és -100 közé eső számot kell megadni paraméternek (előre 100% - hátra 100%). Azt figyelembe kell venni, hogy amint azt a motorvezérlés teszteléséről szóló részben már tárgyaltam, a súrlódás miatt kb. ±65%-os érték felett indulnak csak el a motorok (ez az érték függ a motoroktól és a motorok tápfeszültségétől is). A motorvezérlő függvényeken belül a motorok forgásirányát a digitalWrite() utasítás, a motorok sebességét pedig az analogWrite()utasítás állítja be.

A vonalkövető robot Arduino1.0 kódja:

//Vonalkoveto robot Arduino 1.0 kod

#define M1 4 // Pin4 : Motor1 forgasirany (Bal Motor)

#define EN1 5 //Pin5 : Motor1 sebesseg (PWM)

#define EN2 6 //Pin6 : Motor2 sebesseg (PWM)

#define M2 7 //Pin7 : Motor2 forgasirany (Jobb Motor)

int BalLDR = 4; // Bal szenzor az A4 analog bemenetre kotve

int JobbLDR = 5; //Jobb szenzor az A5 analog bemenetre kotve

int balfenyero; // Bal szenzor ADC erteket tarolo valtozo

int jobbfenyero; // Jobb szenzor ADC erteket tarolo valtozo

int Motor = 80; // Kezdeti motorsebesseg megadasa

int Hatarertek = 820; // Vonalerzekeles hatarerteke

void setup() //Beallitasok

{

pinMode(EN1, OUTPUT); //Motor1 sebesseg lab: kimenet

pinMode(EN2, OUTPUT); //Motor2 sebesseg lab: kimenet

pinMode(M1, OUTPUT); // Motor1 forgasirany lab: kimenet

pinMode(M2, OUTPUT); // Motor2 forgasirany lab: kimenet

}

void loop() //Foprogram - vegtelen ciklus

{

balfenyero = analogRead(BalLDR); //Bal szenzoron levo feszultseg merese

(0 - 1023 kozotti ertek)

jobbfenyero = analogRead(JobbLDR); //Jobb szenzoron levo feszultseg merese

(0 - 1023 kozotti ertek)

// Ha mindket szenzor a vilagos padlo felett van: Elore

if (balfenyero>Hatarertek && jobbfenyero>Hatarertek)

{

MotorBal(Motor-2); //Bal motor: elore

MotorJobb(Motor); //Jobb motor: elore

}

// Ha Bal szenzor a vonal felett van, Jobb a padlo felett: Balra kanyarodas

else if (balfenyero<Hatarertek && jobbfenyero>Hatarertek)

{

MotorBal(0); //Bal motor: stop

MotorJobb(Motor); //Jobb motor: elore

}

// Ha Jobb szenzor a vonal felett, Bal a padlo felett van: Jobbra kanyarodas

else if (balfenyero>Hatarertek && jobbfenyero<Hatarertek)

{

MotorBal(Motor-2); //Bal motor: elore

MotorJobb(0); //Jobb motor: stop

}

//Elore (mindket szenzor a vonal felett van: keresztezodes)

else if (balfenyero>Hatarertek && jobbfenyero>Hatarertek)

{

MotorBal(Motor-2); //Bal motor: elore

MotorJobb(Motor); //Jobb motor: elore

}

delay(50); // Varakozas 50ms-ig

}

void MotorBal(int sebesseg)

{

if (sebesseg>0) //Eloremenet

{

digitalWrite(M1,HIGH); //M1 irany (elore)

analogWrite(EN1,sebesseg*255/100); //M1 sebesseg(PWM)

}

else //Hatramenet

{

digitalWrite(M1,LOW); //M1 irany (hatra)

analogWrite(EN1,abs(sebesseg)*255/100); //M1 sebesseg(PWM)

}

}

void MotorJobb(int sebesseg)

{

if (sebesseg>0) //Eloremenet

{

digitalWrite(M2,HIGH); //M2 irany (elore)

analogWrite(EN2,sebesseg*255/100); //M2 sebesseg(PWM)

}

else //Hatramenet

{

digitalWrite(M2,LOW); //M2 irany (hatra)

analogWrite(EN2,abs(sebesseg)*255/100); //M2 sebesseg(PWM)

}

}

 

Az alábbi videón a végeredmény látható:

 

Továbbfejlesztés
A videón látható, hogy a robot viszonylag lassan haladva követi a vonalat. Ha a motorokat teljes, 100%-os sebességre állítom, akkor a túl nagy sebesség miatt, a kanyarodás során a vonal kikerül a két szenzor közül, és a robot elvéti a vonalat. Tehát bőven van továbbfejleszteni való még a roboton. Az alábbiakban megemlítek néhány lehetőséget:

Több szenzor alkalmazása esetén nagymértékben csökkenthető annak a valószinűsége, hogy a robot elveszítse a vonalat. Ráadásul így sokkal fejlettebb vonalkövető algoritmusok is használhatók. Ezáltal a vonalkövetési sebesség is növelhető. Infravörös LED-ek alkalmazásával pedig a környezeti fényviszonyok által keltett zavar csökkenthető. Pl. 5 db TCRT5000-es infravörös reflektív optocsatoló szenzort az alábbi ábra szerint elrendezve építhetünk egy vonalérzékelő detektorsort.

vk3-8.jpg

Ez már sokkal több információt szolgáltat a követendő vonalról. Ezáltal olyan vonalkövető algoritmusok is használhatók ahol a robot sebessége és a kanyarodás íve a vonal pozíciójától függően változtatható. Egy ilyen algoritmus egyszerűsített vázlata látható az alábbi rajzon:

vk3-9.jpg

Ha a vonal a középső detektor alatt van (A), akkor a robot teljes sebességgel haladhat előre. Ha a vonal kicsit eltér a középső helyzettől (B), akkor kicsit lelassítva, enyhe ívben kanyarodva követhető a vonal. Ha a vonal valamelyik szélső detektor alatt van (C), akkor a robotot teljesen lelassítva, élesen kell kanyarodni.

Az általam használt DC motorok áttétele elég nagy (1:200), ez nagymértékben korlátozza az elérhető végsebességet. Egy kisebb áttételű és erősebb motort használva tovább növelhető a sebesség.

Egyik kedvenc vonalkövető robotom az alábbi képen látható F-1 robot, ami 9db TCRT5000-ből épített érzékelősort használ. A robot meghajtása 12V-os PC hűtőventillátor motorokból készült. Az irányítást pedig egy PIC18F2520-as mikrovezérlő látja el:

vk3-10.jpg

A fent említett továbbfejlesztési lehetőségek sora korántsem teljes, csak gondolatébresztő szándékkal írtam. Látható, hogy a vonalkövető robot megépítése csak a kezdet, és innen nagyon sokféle irányba haladhatunk tovább...

Ezzel a cikksorozat végére is értem. Remélem tetszett, és sokan kedvet kapnak tőle a robotépítéshez.

Üdvözlettel: Fizikus

A bejegyzés trackback címe:

https://robotepites.blog.hu/api/trackback/id/tr9013451637

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása