Robot Following using Camera (Marian Vysluzil)
Zadanie
Úlohou bolo zostrojiť robota platformy Acrob, ktorý bude sledovať čiaru pomocou kamery mobilného telefónu z ktorého budú dáta odosielané pomocou technológie bluetooth.
Hardware
Ako základ bol použitý robot Acrob založený na platforme Arduino.
Bluetooth prijímač/vysielač bol použitý JY-MCU v1.02 ktorý , ale pracuje na napätí 3.3V na rozdiel od Acroba ktorý pracuje na 5V. Preto bolo treba upraviť komunikačný signál smerom od robota k bluetooth modulu. Úprava bola spravená odporovým deličom ktorý zmenšil výstupné napätie z robota na 3V ktoré modulu postačovalo. Vstupné napätie z modulu do robota upravované nebolo.
Software
Komunikácia:
Aplikácia pre mobilný telefón bola napísaná v Jave pre operačný systém Android. Pre komunikáciu bola pridaná upravená knižnica Amarino, ktorá slúži pre komunikáciu s Arduinom na robotovi Arcob (knižnicu Amarino si treba nainštalovať aj do mobilného telefónu) a oproti štandardnej verzií obsahuje nový konštruktor, ktorý namiesto HardwareSerial komunikácie použije SoftwareSerial aby bolo možné naraz používať SerialMonitor Arduina a bluetooth modul.
MeetAndroid::MeetAndroid(int rxPin, int txPin, long int baud) { customErrorFunc = false; SoftwareSerial *softSerial = new SoftwareSerial(rxPin, txPin); softSerial->begin(baud); stream = softSerial; init(); }
Riadenie robota:
Na riadenie bol použitý jednoduchý PID kontroler ktorý upravuje rýchlosť motorov. Robot sa snaží držať v strede čiary ktorú nájde pomocou funkcie findTape(), ktorá nájde najvzdialenejšiu čiaru väčšiu ako 10 pixlov v prvej polovici „videnia robota“, čo je vlastne obrázok z kamery, ak takú čiaru nenájde robot pokračuje v ceste rovno.
public int findTape(int[] rgb, int width, int height) { int tapeStart = -1; int tapeEnd = -1; int tmpStart = -1; int tmpEnd = -1; int scanline = -1; for (int x = height/2; x < height; x += 5) { for (int pix = 0; pix < height; pix++) { int pixVal = (0xff & (int) rgb[x + pix * width]); if (pixVal == 0) { if (tmpStart == -1) { tmpStart = pix; } else { tmpEnd = pix; if (tmpEnd - tmpStart > minPixels && (Math.abs((tmpEnd - tmpStart) / 2 - height / 2) < Math.abs((tapeEnd - tapeStart) / 2 - height / 2))) { tapeEnd = tmpEnd; tapeStart = tmpStart; scanline = x; } } } else { tmpStart = -1; tmpEnd = -1; } } if(tapeStart>-1){ break; } } if (tapeStart > -1 && tapeEnd > -1 && scanline > -1) { for (int pix = tapeStart; pix <= tapeEnd; pix++) { rgb[scanline + pix * width] = 0xff000000 | (0 << 16) | (255 << 8) | 0; } } else { return -1; } return (tapeEnd + tapeStart) / 2; }
Rozlíšenie kamery bolo nastavene na 176x144 pixlov. Keď robot vypočíta výchylku odošle dáta na Arduino (pre každý motor zvlášť), kde sa príjmu a ak sú v rozsahu od 0-30 daný motor ostane stáť , v opačnom prípade sa rozbehnú. Ak robot nedostane dáta do 500ms zastaví. Robot po každej úprave rýchlostí motorov odošle na Android číslo ako kontrolu spojenia.
void set_motor_speed(byte flag, byte numOfValues) { int data[numOfValues]; meetAndroid.getIntValues(data); meetAndroid.send(1); motor1speed = data[1]; motor2speed = data[0]; lastcmd = millis(); }
Záver
Robot fungoval dobre a dráhu zvládol. Občasný problém v kontrole robota bol odraz svetla na leskom povrchu dráhy ktorú mal robot absolvovať. Riešenie by bolo napríklad aby mobil svietil na dráhu osvetlením pre fotoaparát , čo by znamenalo opätovné nastavenie premennej treshold ktorá určuje ktorá farba je čierna.
Video