Järgnev õpetus on koostatud TTÜ avatud ülikooli ja MTÜ TTÜ Robotiklubi koostöös eesmärgiga aidata Robotexil osalevaid või seda plaanivaid võistkondi.
Robotex on eesti suurim ja populaarseim võistlus, mis leiab aset igal aastal novembris või detsembris Tallinnas. Võistlusel on ette antud lähteülesanne, mis tavaliselt muutub igal aastal. Täpsemat infot võistluse ja reeglite kohta saab aadressilt http://www.robotex.ee
Käesolev juhend sisaldab täielikku dokumentatsiooni ja praktilisi näpunäiteid ühe Robotex 2010 reeglitele vastava roboti ehitamiseks. Robot on oma ülesehituselt ja võimetelt ette nähtud juuniorite klassis osalemiseks, kus robotitel pole kasutada kalleid ja kiireid mootoreid, pisikesi arvuteid ning kaameraid. Sellesse klassi on oodatud gümnaasiumiõpilased ja robootikaga alles tutvust tegevad huvilised.
Juhendi baasil loodud platvormi eesmärgiks on olla lihtne ning odav esimene katsetus robotite ehitamise vallas. Sellest lähtuvalt kasutatakse laialt saadaolevaid konstruktsioonimaterjale ning elektroonikakomponente. Roboti baaskomponentideks on valitud Kodulabori komplektis sisalduvad moodulid. Kuna kõiki komponente kodulaborites siiski ei leidu, lisanduvad mõningad spetsiifilised osad. Tänu moodularhitektuurile võib iga soovija robotit muuta vastavalt oma äranägemisele.
Kuna ilma pilditöötluseta ja kallite laserkaugumõõdikuteta on pallide leidmine väljakult tehniliselt üsna keerukas, tuleb minna lihtsama vastupanu teed ja kaugelt avastamise asemel palle aktiivselt ringi sõites otsida. Selleks on roboti algoritmis ette nähtud väljakul edasi-tagasi sõitmine ja pallide juhuslik avastamine.
Robot kasutab pallide leidmiseks ultraheli kaugusandurit. Andur on asetatud mõõtma kaugust roboti parema külje peale. Pallide otsimiseks sõidab robot väljaku keskel ühe värava juures teise juurde ja mõõdab pidevalt temast paremale jäävate objektide kaugust. Kui roboti ja seina vahele jääb pall siis kauguse näit väheneb ja robot võtab hoo maha, et vaikselt liikudes pallist mööduda nii, et kaugusanduri näit jälle suureneks. Sedasi saab robot üpris täpselt palli kõrvale sõita.
Edasi on põhimõtteliselt lihtne - robotil tuleks keerata 90 kraadi paremale ja sõita pallini, kuid paraku ei ole palli kõrvale seisma jäämine ja pööre nii täpne, et robot saaks kätte poole meetri kaugusel oleva palli. Selleks on pärast palli avastamist kaks varianti: kohe palli püüdma minek või selle lähemalt otsimine. Kui pall asub robotist kuni 30 cm kaugusel pöörab robot kohe palli poole ja üritab selle kätte saada nii nagu on näidatud ka järgneval skeemil:
Kui pall asub kaugemal kui 30 cm siis robot sõidab esmalt edasi veel 10 cm, siis pöördub 90 kraadi paremale ja hakkab otse seina suunas sõites ultrahelianduriga otsima palli mis peaks robotist taaskord paremat kätt olema. Nii kui ultraheliandur näeb lähedal olevat objekti, sõidab robot natuke edasi, pöördub teist korda 90 kraadi paremale ja saab palli üsna nina alt kätte. Seda kauge palli leidmise algoritmi iseloomustab järgnev skeem:
Robot saab pallianduri abil aru kas ta on palli kätte saanud või mitte. Palli püüdmiseks on roboti ninas V-kujuline lehter ja selle kohal pöörlev kummist rull mis paneb lehtrisse sattunud palli pöörlema roboti suunas. Palli pööritamine takistab selle minema veeremist roboti liikumise ajal.
Pärast palli kättesaamist hakkab robot otsima vastase väravat kuhu pall toimetada. Värava leidmiseks on väravate kohal infrapuna (IR) majakad mis kiirgavad väljaku suunas RC5 protokolliga signaale, ehk põhimõtteliselt on saatjad justkui telekapuldid. Värava leidmiseks on robotil kahe kanaliga RC5 vastuvõtja millel on kahe infrapuna detektori vahel sein. Kui vastuvõtja on suunatud majaka suunas, kiirgab majakas mõlemasse detektorisse; kui vastuvõtja on majaka suhtes viltu, siis signaal jõuab ainult ühte detektorisse. Vastavalt sellele milline detektor majakat “näeb” saab robot aru värava suunast. Kui suund on õige saab robot otse värava suunas sõita.
Roboti ees on ~8 cm kõrgusel infrapuna kaugusandur, mis mõõdab takistuste kaugust. Takistuseks võivad võistlusel olla vastase robot või seinad. Sellesama anduriga saab robot ka aru väravast kuna väravate tagumise seina alumises 10 cm osas on riie millelt infrapuna kiirgus peegeldub. Sõites värava suunas ja jõudes värava seinast ~20 cm kaugusele lõpetatakse palli kinnihoidmine ja lükatakse see väravasse. On oht, et värava suunas sõites võib robot värava seina asemel märgata vastast - selleks ootab robot enne palli lahti laskmist natukese, lootuses, et vastane liigub eest ära.
Löögimehhanism pallide kaugel väravasse löömiseks puudub, kuna see on tehniliselt keerukas ja otseselt pole seda vaja. Pärast palli vastase väravasse lükkamist hakkab robot palle otsima oma värava suunas liikudes.
Komponent | Selgitus | Kogus |
---|---|---|
Veermik | 1 | |
Alusplaat | Alumiiniumist kere | 1 |
Haarats | Alumiiniumist raam rulli ja pallianduri jaoks | 1 |
Mootor | DC | 1 |
Rull | Palli keerutamiseks | 1 |
Kummirõngas | Palli keerutamiseks | 2 |
Kodulabori Kontrollermoodul | Mikrokontrolleriga põhiplaat | 1 |
Kodulabori Mootorite moodul | H-sillad mootorite juhtimiseks | 1 |
Kodulabori Andurite moodul | Erinevate andurite ühendamiseks | 1 |
Kodulabori Kommunikatsioonimoodul | RC5 vastuvõtjaga suhtlemiseks | 1 |
Ultraheli kaugusandur | Palli leidmiseks | 1 |
Infrapuna kaugusandur | Takistuste avastamiseks | 1 |
Kooder | Optokatkesti sammude lugemiseks | 2 |
Palliandur | Peegeldusandur palli nägemiseks | 1 |
M3x6 polt | Komponentide kinnitamiseks | 16 |
M3x10 polt | Koodrite kinnitamiseks | 4 |
Mutter | Komponentide kinnitamiseks | 20 |
Seib | Komponentide kinnitamiseks | 4 |
Jalgpalliroboti keskseks osaks on Pololu RP5 lintidega veermik sellele kinnitatava alusplaadiga. Alusplaadi külge kinnitatakse omakorda rullimehhanism, elektroonikamoodulid, andurid, koodrid, jms. Jalgpalliroboti konstruktsiooni väljatöötamisel on lähtutud sellest, et robot oleks võimalikult kompaktne, lihtne ja käepäraste vahenditega ehitatav. Materjalide ja erinevate detailide valikul on arvestatud nende kättesaadavusega.
Alusplatvormina kasutatakse Pololu RP5 lintidega veermikku. Veermikuga on kaasas kaks alalisvoolumootorit, kummagi lindi jaoks üks. Nende abil suudab veermik liikuda kiirusega kuni 15 cm/s. Lindid tagavad platvormile hea manööverdamisvõime. Lisaks on platvormiga kaasas ka patareihoidik 6 AA suuruses patarei jaoks. Platvormi mõõtmed on 180 mm x 140 mm x 60 mm. Augud alusplaadi kinnitamiseks on platvormil algselt juba olemas, kuid need tuleb siiski veel keermestada. Rohkem informatsiooni veermiku ja selle tellimise kohta saab järgnevalt aadressilt: http://www.pololu.com/catalog/product/1060
Alusplaat seob omavahel jalgpalliroboti kõiki detaile. Erinevate komponentide kinnitamiseks on alusplaadile puuritud vajalikud augud. Kõik komponendid on seejuures kinnitatud M3 polte ja mutreid kasutades. Alusplaat ise kinnitatakse veermiku külge nelja poldi abil. Lisaks poldiaukudele on alusplaadil auk patareihoidiku lihtsamaks väljavõtmiseks ning kaks auku koodrite kaablite jaoks. Alusplaadile tuleb teha ka kaks painutust (vt pilti). Alusplaadi materjali valikul tuleb arvestada sellega, et materjali oleks võimalik painutada.
Rullimehhanism koosneb haaratsist, rullist, rulli kummirõngastest, rulli käitavast alalisvoolumootorist ja hingest, mille abil mehhanism alusplaadi külge kinnitatakse. Haaratsile kinnitatakse ka kahepoolse teibiga optiline andur. Alalisvoolumootorina kasutatakse Kodulabori Micro motors L149.6.10 reduktoriga mootorit.
Haarats seob omavahel rullimehhanismi kõiki komponente. Haaratsi külge kinnitatakse alalisvoolumootor, optiline andur ning hing. Lisaks sellele on haaratsi üheks põhiülesandeks golfipalli fikseerimine rulli ette. Haarats on konstrueeritud nii, et golfipalli sattumisel haaratsi ette suunatakse see rulli pindade poole. Haaratsi antud ehitus takistab ka golfipalli minema veeremist roboti pööramisel. Kuna haaratsile tuleb teha mitmeid painutusi, peab materjali valikul sellega arvestama.
Rulli tööpõhimõte seisneb palli sellisel viisil pöörlema panemises, et see kogu aeg roboti poole veereks . Rulli diameeter on 20 mm ja laius 50 mm. Rulli ühte otsa on puuritud auk mootori võlli jaoks ning sellega risti on puuritud ja keermestatud teine auk, mille kaudu poldi abil rull võlli külge fikseeritakse.
Rullile kinnitatakse kaks kummirõngad siseläbimõõduga 19 mm ja välisläbimõõduga 30 mm, kummide laius on 15 mm. Kummidevaheline kaugus rullil on 10 mm. Kummid tagavad parema kontakti rulli ja golfipalli vahel ja seega golfipalli parema püsimise rulli ees.
Infrapuna kaugusanduri ning RC5 vastuvõtja kinnitamiseks on lihtne U-kujulise profiiliga kinnitus. Kinnitusele on puuritud augud infrapuna kaugusanduri ja kinnituse enda alusplaadi külge kinnitamiseks. RC5 vastuvõtja fikseerimiseks kasutatakse kahepoolset teipi. Kuna tehakse painutusi, peab sellega ka kinnituse materjali valikul.
Patareihoidiku väljavõtmise võimaldamiseks on Kodulabori moodulid paigaldatud alusplaadile puksidega. Alusplaadil on moodulite kinnitamiseks puuritud vastavad augud. Moodulid paiknevad kihiliselt ning on omavahel kergesti ühendatavad.
Roboti ehitamiseks kasutatakse Kodulabori täiskomplekti, mis sisaldab järgnevaid mooduleid (eraldi plaate):
Moodulite pikema kirjelduse koos pistikute piikide täpse kirjeldusega leiab leheküljelt
http://home.roboticlab.eu/et/hardware/homelab
Järgneval pildil on toodud lihtsustatud ülevaade andurite jms ühendamisest.
Robotil vajab toitepinget nii kontrolleri moodul kui ka mootorite moodul. Mõlemad kasutavad energiaallikana sama akupatareid. Kasutatakse kaheks hargnevat juhet. MOotorite mooduli toitepistiku ühendamise õpetus on lehel
http://home.roboticlab.eu/et/hardware/homelab/motor
NB! Standardse akupatarei fikseeritud pinge tõttu peab kontrolleri plaadil lühistama dioodsilla. Silla funktsioon plaadil on pöörata toitepinge polaarsus alati ühte pidi. See tähendab, et silda kasutades pole toitepinge polaarsus tähtis. Paraku jääb sillal u 1,5V pingelangu, mis on lubamatult palju.
Lühistades silla on toitepinge õige polaarsus tähtis! Pistiku keskmine piik on positiivne ja välime äär negatiivne.
Roboti veermikul on mõlema lindi ülekandes 2 aukudega hammasratast. Asetades optokatkesti niimoodi hammasratta kohale, et see jääb optokatkesti pilu vahele saab optokatkestiga registreerida hammasrattas olevaid auke. Kui optokatkesti vahele jääb auk, siis optokatkesti ühes otsas oleva valgusdioodi valgus kiirgab teises otsas oleva fototransistori peale ja viimane hakkab voolu juhtima. Lugedes pöörlevas hammasrattas olevaid auke saab selle info põhjal välja arvutada läbi teepikkuse. Originaalis on mõlemas veermiku hammasrattas üks auk, kuid sinna tuleb sümmeetriliselt juurde puurida 2 auku, et koodri täpsust parandada. Sedasi saab lindi läbitud teepikkust mõõta ligikaudu 1 cm täpsusega.
Koodrid on ühendatud Kodulabori Mootorite mooduli “encoder” pistikupesas. Vasaku poole kooder on ülemises, parema poole kooder alumises pesas. Koodrite impulside lugemiseks kasutatakse tarkvara Kodulabori teegi koodrite moodulit.
Robotexil on väravate kohale paigutatud infrapuna signaali saatjad, mis edastavad Philips’i RC5 protokolli abil kanaleid 1 kuni 4. Nende signaalide vastuvõtmiseks on tehtud eraldiseisev moodul. Vastuvõtumoodul ühendatakse kodulabori kommunikatsioonimooduliga kaabliga, mille ühendusskeem on välja toodud plokkskeemis. Samas on välja toodud info vastuvõtja olulisemate komponentide kohta.
Vastuvõtumoodulile on paigutatud kaks signaali vastuvõtjat/demoduleerijat. Tänu sellele on võimalik paika panna roboti asend väravate suhtes.
Vastuvõtja saadab 4800 bps kiirusel välja 1-baidiseid UART sõnumeid, milles sisaldub infrapunavastuvõtja indeks ning vastuvõetud kanal. Väljasaadetavate UART sõnumite kirjeldused on välja toodud allpool olevates tabelites:
Vastuvõtja indeksiga 0 (vasakpoolne)
Kanal | Kaheksandiksüsteemis(HEX) | Kahendsüsteemis(BIN) |
---|---|---|
1 | 0x01 | 0b00000001 |
2 | 0x02 | 0b00000010 |
3 | 0x03 | 0b00000011 |
4 | 0x04 | 0b00000100 |
Vastuvõtja indeksiga 1 (parempoolne)
Kanal | Kaheksandiksüsteemis(HEX) | Kahendsüsteemis(BIN) |
---|---|---|
1 | 0x11 | 0b00010001 |
2 | 0x12 | 0b00010010 |
3 | 0x13 | 0b00010011 |
4 | 0x14 | 0b00010100 |
RC5 vastuvõtja skeemi ja trükkplaadi pildid. Skeemi ja trükplaadi failid, tarkvara ning komponentide nimistu paiknevad lehekülje alumises osas, alajaotuses “Failid”.
Palli tuvastamiseks rulliku all kasutatakse infrapuna peegeldusandurit. Saatajalt peegeldunud kiirgus jõuab vastuvõtjasse ja selle kiirguse intensiivsuse järgi saab määrata objekti kauguse. Intensiivsus sõltub lisaks kaugusele ka objekti pinna värvist ja siledusest. Robotexi ülesande golfipall on alati ühesugune ja seega vastab igale intensiivuse tasemele kindel kaugus andurist.
Kuna võistlusel on alati palju välklampe, kaameraid, valgusteid jms infrapunakiirguse allikaid, siis kasutatakse moduleeritud signaali, st saatja kiirgab teatud sagedusel ja vastuvõtja reageerib ainult sellel sagedusel olevale signaalile. Kõik selle teeb ära üks integraallülitus - Hamamatsu S4282-51. Ainsaks väliseks komponendiks on infrapunakiirgur (diood) ning tundlikkust reguleeriv takisti jadamisi dioodiga.
Pallianduri skeem on näidatud pildil. U1 on Hamamatsu S4282-51 andur. Kondensaator C1 silub toitepinge kõikumist. Kuna IP-diood võtab üsna palju voolu, siis selle sisse-välja lülitamise hetketel muutub voolutugevus anduri juhtmetes. Juhtmete induktiivsuse tõttu ei saa muutus toimuda hetkeliselt ja kondensaator täidab lühiajalise energiaallika osa. Kondensaatori parameetrid pole kriitilised. Peaasi, et nimipinge ületab 5V ja mahtuvus 1uF või rohkem.
Takisti R1 määrab anduri tundlikkuse. Ilma takistita oleks anduri reageermiskaugus u 5cm (sõltub ka IP-dioodi valikust). Takisti valimine käib katse-eksituse meetodil (vahemik 0 - 30 oomi).
Dioodi valimisel tuleb lähtuda S4282-51 andmelehel märgitud lainepikkusest (800nm), kus andur on kõige tundlikum. Dioodi kiirgusnurk peaks olema võimalikult väike, et palliandur näeks ainult otse ette. Suure nurgaga dioodi puhul võib andur reageerida juba siis, kui pall pole täpselt otse anduri ees. Dioodi kiirgusnurk 11 kraadi ja alla selle tagab hea tulemuse.
Pistik JP1:
Roboti tarkvara on kirjutatud AVR Studios C keeles. Tarkvara kasutab kodulabori teeki ja AVR-GCC kompilaatorit mis tuleb kaasa WinAVR-iga. Programm on jagatud funktsioonide järgi mitmeks failiks - näiteks on sõitmise funktsioonide ja andurite näitude lugemiseks erinevad failid. Põhifailis asub main funktsioon mis käivitab kõik juhtimis- ja tagasiside protsessid. Roboti algoritm asub samas failis olevas suures olekutabelis.
Programm on üles ehitatud tavapärase olekumasina eeskujul, kuid et kood liiga pikaks ei läheks ning kogu algoritm ühes kohas koos oleks, kasutatakse sisendite kontrolliks ja väljundite juhtimiseks ühtset suurt tabelit. Selleks, et algoritmis saaks kiirelt ja mugavalt lugeda andurite näite, juhtida mootoreid ja kuvada infot, on kõik muud protsessid toimima pandud katkestuste pealt. Katkestuste pealt töötades ei sega mõõtmis- ja juhtimisprotsessid algoritmi tööd ja vastupidi - need toimuvad paralleelselt.
Tabeli struktuur on järgmine:
Tabeli ridade pikkuse vähendamiseks ning määramata sisendite/väljundite võimaldamiseks kasutatakse tabelis makrokäsklusi. Järgnevalt on kasutatavad käsklused lahti seletatud.
Käsklus | Seletus |
---|---|
EQ(n) | Sisend peab olema n-ga võrdne |
NE(n) | Sisend ei tohi olla n-ga võrdne |
GT(n) | Sisend peab olema suurem n-st |
LT(n) | Sisend peab olema väiksem n-st |
BM(n) | Kontrollitakse n-ndat bitti sisendis |
CSM(n) | Sisendi väärtus peab olema suurem või võrdne n ja eelmise meelde jäetud ultraheliandurist saadud kauguse summaga |
CSB(n) | Sisendi väärtus peab olema suurem või võrdne n ja eelmise meelde jäetud ultraheliandurist saadud kauguse vahega |
DRV(l, r) | Seab vasaku mootori kiiruseks l ja parema mootori kiiruseks r. Arvud -100…100, kus 0 on peatatud olek ning negatiivne arv tähistab sama kiirust vastassuunas. |
STA(n) | Seab uue oleku n |
TMR(n) | Seab taimeri uueks väärtuseks n |
ROL(0/1) | Lülitab pallihoidmise rulliku välja/sisse |
LED(0/1) | Lülitab LED'i välja/sisse |
SEG(0-9) | Seab 7-segmendilise indikaatori näidatava väärtuse 0-9 |
// // Input-output logic list // This table does all the "thinking" // logic_step logic_list[] = { // INPUT OUTPUT // STATE TIMER CODEL CODER BUTTN IRRED USONI BALLS OWN OPPO STATE TIMER CHASSIS ROLLER SEGMNT LEDRED US M+ { EQ( 1), 0, 0, 0, BM(1), 0, 0, 0, 0, 0, STA( 2), 0, 0, 0, 0, LED(1), 0 }, // Start command { 0, 0, 0, 0, BM(4), 0, 0, 0, 0, 0, STA( 1), 0, DRV( 0, 0), ROL(0), SEG(0), LED(0), 0 }, // Stop command // --- Drive to the center ------------------------------------------------------------------------------------------------------------------------------------------ { EQ( 2), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 3), 0, DRV(-100, 100), 0, 0, 0, true }, { EQ( 3), 0, 0, GT(18), 0, 0, 0, 0, 0, 0, STA( 4), 0, DRV( 100, 100), 0, 0, 0, 0 }, { EQ( 4), 0, CSB(1000), CSB(1000), 0, 0, 0, 0, 0, 0, STA( 5), 0, DRV( 100,-100), 0, 0, 0, 0 }, { EQ( 5), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 10), 0, DRV( 0, 0), 0, 0, 0, 0 }, // --- Start searching ---------------------------------------------------------------------------------------------------------------------------------------------- { EQ( 10), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 11), 0, DRV( 100, 100), ROL(0), SEG(1), 0, 0 }, { EQ( 11), 0, 0, 0, 0, 0, 0, EQ(1), 0, 0, STA( 90), 0, 0, 0, 0, 0, 0 }, // Found a random ball { EQ( 11), 0, 0, 0, 0, 0, LT( 600), 0, 0, 0, STA( 20), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Sudden closer distance on the right, investigate { EQ( 11), 0, 0, 0, 0, LT( 200), 0, 0, 0, 0, STA(100), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Something's in the way, turn around // --- Precise search ----------------------------------------------------------------------------------------------------------------------------------------------- { EQ( 20), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 21), TMR(5000), DRV( 50, 50), 0, SEG(2), 0, 0 }, { EQ( 21), 0, 0, 0, 0, 0, 0, EQ(1), 0, 0, STA( 90), 0, 0, 0, 0, 0, 0 }, // Found a random ball { EQ( 21), 0, 0, 0, 0, LT( 200), 0, 0, 0, 0, STA(100), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Something's in the way, turn around { EQ( 21), EQ( 0), 0, 0, 0, 0, LT( 600), 0, 0, 0, STA( 22), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Suspected ball seems to be a wall instead { EQ( 21), EQ( 0), 0, 0, 0, 0, GT( 599), 0, 0, 0, STA( 10), 0, 0, 0, 0, 0, 0 }, // Didn't recognize a ball, return to search { EQ( 21), LT(4500), 0, 0, 0, 0, GT( 599), 0, 0, 0, STA( 30), 0, DRV( 0, 0), 0, 0, 0, true }, // Identified a ball, go get it { EQ( 22), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 23), 0, DRV(-100, 100), 0, 0, 0, true }, // Try to get away from the wall { EQ( 23), 0, 0, GT(18), 0, 0, 0, 0, 0, 0, STA( 24), 0, DRV( 100, 100), 0, 0, 0, 0 }, { EQ( 24), 0, CSB(750), CSB(750), 0, 0, 0, 0, 0, 0, STA( 25), 0, DRV( 100,-100), 0, 0, 0, 0 }, { EQ( 25), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 10), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Resume search // --- Turn to ball ------------------------------------------------------------------------------------------------------------------------------------------------- { EQ( 30), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 31), 0, DRV( 100, 100), ROL(1), SEG(3), 0, 0 }, { EQ( 31), 0, 0, 0, 0, 0, 0, EQ(1), 0, 0, STA( 90), 0, 0, 0, 0, 0, 0 }, // Found a random ball { EQ( 31), 0, GT(MTS(150)), GT(MTS(150)), 0, 0, 0, 0, 0, 0, STA( 32), 0, DRV( 100,-100), 0, 0, 0, 0 }, // Turn right { EQ( 32), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 33), 0, DRV( 75, 75), 0, 0, 0, 0 }, // Start driving towards the wall { EQ( 33), 0, 0, 0, 0, LT( 150), 0, 0, 0, 0, STA( 40), 0, DRV(-100, 100), ROL(0), 0, 0, 0 }, // Wall too close, turn around and get back to the center { EQ( 33), 0, 0, 0, 0, 0, LT( 300), 0, 0, 0, STA( 34), 0, DRV( 100, 100), 0, 0, 0, true }, // Spotted the ball { EQ( 34), 0, GT(MTS( 50)), GT(MTS( 50)), 0, 0, 0, 0, 0, 0, STA( 35), 0, DRV( 100,-100), 0, 0, 0, 0 }, // Turn towards the ball { EQ( 35), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 36), 0, DRV( 90, 90), 0, 0, 0, 0 }, { EQ( 36), 0, CSM(50), CSM(50), 0, 0, 0, EQ(1), 0, 0, STA( 90), 0, 0, 0, 0, 0, 0 }, // Caught the ball { EQ( 36), 0, CSM(50), CSM(50), 0, 0, 0, EQ(0), 0, 0, STA( 45), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Didn't get the ball { EQ( 40), 0, 0, GT(34), 0, 0, 0, 0, 0, 0, STA( 41), 0, DRV( 100, 100), 0, 0, 0, 0 }, { EQ( 41), 0, GT(MTS(700)), GT(MTS(700)), 0, 0, 0, 0, 0, 0, STA( 42), 0, DRV( 100,-100), 0, 0, 0, 0 }, { EQ( 42), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 10), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Resume search { EQ( 45), 0, 0, 0, 0, 0, LT( 801), 0, 0, 0, STA( 46), 0, DRV( 100,-100), 0, 0, 0, 0 }, // Drive back to the center { EQ( 45), 0, 0, 0, 0, 0, GT( 800), 0, 0, 0, STA( 47), 0, DRV( 100,-100), 0, 0, 0, true }, { EQ( 46), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 49), 0, DRV( 100,-100), 0, 0, 0, 0 }, { EQ( 47), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 48), 0, DRV( 100, 100), 0, 0, 0, 0 }, { EQ( 48), 0, CSB(800), CSB(800), 0, 0, 0, 0, 0, 0, STA( 46), 0, DRV( 100,-100), 0, 0, 0, 0 }, { EQ( 49), 0, GT(18), 0, 0, 0, 0, 0, 0, 0, STA( 10), 0, DRV( 0, 0), 0, 0, 0, 0 }, // Return to search // --- Locate the goal ---------------------------------------------------------------------------------------------------------------------------------------------- { EQ( 90), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 91), 0, DRV( 50, 50), ROL(1), SEG(4), 0, 0 }, { EQ( 91), 0, GT(MTS( 50)), GT(MTS( 50)), 0, 0, 0, 0, 0, 0, STA( 92), TMR(1000), DRV( -70, 70), 0, 0, 0, 0 }, { EQ( 92), 0, 0, 0, 0, 0, 0, 0, 0, LT(0), 0, 0, DRV( -70, 70), 0, 0, 0, 0 }, // Goal to the left { EQ( 92), 0, 0, 0, 0, 0, 0, 0, 0, GT(0), 0, 0, DRV( 70, -70), 0, 0, 0, 0 }, // Goal to the right { EQ( 92), EQ( 0), 0, 0, 0, 0, 0, 0, 0, EQ(0), STA( 95), 0, DRV( 100, 100), 0, 0, 0, 0 }, // Goal straight ahead // --- Score the goal ----------------------------------------------------------------------------------------------------------------------------------------------- { EQ( 95), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA( 96), 0, DRV( 100, 100), 0, SEG(5), 0, 0 }, { EQ( 96), 0, 0, 0, 0, LT( 300), 0, 0, 0, 0, STA(100), 0, DRV( 0, 0), ROL(0), 0, 0, 0 }, // Goal scored, turn around // --- Turn around -------------------------------------------------------------------------------------------------------------------------------------------------- { EQ(100), 0, 0, 0, 0, 0, 0, 0, 0, 0, STA(101), 0, DRV(-100, 100), 0, SEG(6), 0, 0 }, { EQ(101), 0, GT(34), 0, 0, 0, 0, 0, 0, 0, STA( 10), 0, DRV( 0, 0), 0, 0, 0, 0 } };
Järgnevalt on toodud roboti main funktsioon kus käivitatakse kõik katkestustel toimuvad protsessid ja täidetakse põhialgoritmi vastavalt olekutabelist loetud väärtustele. Selles funktsioonis asub lõputu tsükkel, mis kontrollib igal läbimisel kõigis tabeli ridades olevaid sisendeid. Kui mõne tabelirea kõigis määratud sisendites on vastav väärtus, siis täidetakse samas reas kirjeldatud väljundite väärtused. Näiteks roboti käivitamiseks nupust on tabeli alguses rida, mille ainsateks sisendtingimusteks on see, et robot on peatatud ning vastavat nuppu on vajutatud. Kui need tingimused on täidetud, määratakse olekuks “2” ning robot hakkab palliotsimisprotsessiga pihta.
Enne tabeli ridade kontrollimist loetakse puhvritest kõigi andurite väärtused ning uuendatakse ka LCD ekraanil olevat infot. Et vähendada ekraani uuendamisega kaasnevat viidet on uuendamine jagatud kuue tsükli vahel, millest igas tsüklis uuendatakse erineva anduri väärtust ekraanil.
// // Main program. // int main(void) { unsigned char i; unsigned short timer; unsigned short encoder_left; unsigned short encoder_right; unsigned short buttons; unsigned short infrared; unsigned short ultrasonic; unsigned short ball; signed char own_goal; signed char target_goal; // Initial state unsigned short state = 1; // LCD counter unsigned short lcdcount = 0; // Initialize hardware. init(); // Loop forever while (true) { // Read sensor values chassis_get_steps(&encoder_left, &encoder_right); timer = timeout_get_counter(); buttons = sensors_buttons(); infrared = sensors_infrared_distance(); ultrasonic = sensors_ultrasonic_distance(); ball = sensors_is_ball(); own_goal = beacon_locate_own_goal(); target_goal = beacon_locate_opponent_goal(); // Display ultrasonic distance. switch (lcdcount % 6) { case 0: lcd_alpha_write_stringf_to(0, 0, "U%04d ", ultrasonic); break; case 1: lcd_alpha_write_stringf_to(0, 1, "I%04d ", infrared); break; case 2: lcd_alpha_write_stringf_to(6, 0, "M%03d ", own_goal); break; case 3: lcd_alpha_write_stringf_to(6, 1, "O%03d ", target_goal); break; case 4: lcd_alpha_write_stringf_to(12, 0, "L%03d ", encoder_left); break; case 5: lcd_alpha_write_stringf_to(12, 1, "R%03d ", encoder_right); break; } lcdcount++; pin_set_to(led_green, !ball); //pin_toggle(led_green); // Decide state for (i = 0; i < NUM_LOGIC_LIST_ITEMS; i++) { // Check input conditions match if (input_check_value(logic_list[i].input_state, state) && input_check_value(logic_list[i].input_timer, timer) && input_check_value(logic_list[i].input_encoder_left, encoder_left) && input_check_value(logic_list[i].input_encoder_right, encoder_right) && input_check_value(logic_list[i].input_buttons, buttons) && input_check_value(logic_list[i].input_infrared, infrared) && input_check_value(logic_list[i].input_ultrasonic, ultrasonic) && input_check_value(logic_list[i].input_ball_sensor, ball) && input_check_value(logic_list[i].input_own_goal, own_goal) && input_check_value(logic_list[i].input_opponent_goal, target_goal)) { // Set new state ? if (logic_list[i].output_state) { state = logic_list[i].output_state & 0x7FFF; } // Set timer if (logic_list[i].output_timer) { timeout_start(logic_list[i].output_timer & 0x7FFF); } // Drive ? if (logic_list[i].output_drive) { chassis_tank_drive((signed char)((logic_list[i].output_drive >> 8) & 0xFF), (signed char)( logic_list[i].output_drive & 0xFF)); } // Use roller ? if (logic_list[i].output_roller) { chassis_use_roller(logic_list[i].output_roller & 0x01); } // Use red LED ? if (logic_list[i].output_led_red) { pin_set_to(led_red, !(logic_list[i].output_led_red & 0x01)); } // Use 7-segment display if (logic_list[i].output_segment) { segment_display_write(logic_list[i].output_segment & 0xFF); } // Remember current ultrasonic reading if (logic_list[i].remember_usonic) { usonic_memory = ultrasonic; } // Got match break; } } } }
Esimese sammuna kinnitatakse alusplaadile koodrid. Selleks läheb vaja:
Kõigepealt kinnitatakse poldid mutritega alusplaadi külge, seejärel paigutatakse koodrid poltidele ning kinnitatakse need mutritega. Sel viisil tagatakse, et optokatkesti on piisavalt lähedal hammasrattale ja suudab registreerida hammasrattas olevaid auke.
Koodrite täpsuse parandamiseks on hammasrattale sümmeetriliselt juurde puuritud 2 auku.
Teise sammuna kinnitatakse alusplaadi külge ultraheli kaugusandur. Selleks läheb vaja:
Kolmandana pannakse kokku rullimehhanism. Rullimehhanismi kokkupanekuks on vaja:
Esmalt kinnitatakse hing haaratsi külge. Haaratsi ja hinge vahel kasutatakse seibe, tagades sel viisil hinge vaba liikumise. Hilisem kinnitamine on raskendatud, kuna rull jääks ette.
Järgmise sammuna kinnitatakse haaratsi külge mootor (3b). Peale seda kinnitatakse kahepoolse teibi abil haaratsi külge optiline palliandur (3c).
Nüüd kinnitatakse mootorivõlli otsa rull, mis fikseeritakse võllile poldiga (3d). Seejärel pannakse rullile peale kummirõngad (3e). Rullimehhanism on nüüd kokku pandud.
Lõpuks kinnitatakse rullimehhanism alusplaadi külge.
Neljanda sammuna paigaldatakse alusplaadi külge andurite kinnitus koos infrapuna kaugusanduriga ja puksid, millele Kodulabori moodulid paigaldatakse. RC5 vastuvõtja paigaldatakse alles peale alusplaadi kinnitamist veermiku külge, kuna enneaegsel paigaldamisel saab ligipääs kruvikeerajaga raskendatud olema. Kinnituse ja pukside paigaldamiseks läheb vaja:
Viies samm on alusplaadi kinnitamine veermikule ja RC5 vastuvõtja paigaldamine andurite kinnitusele. Selleks läheb vaja:
Kuuendana kinnitatakse puksidele Kodulabori moodulid. Kinnitamiseks on vaja:
Seitsmenda sammuna ühendatakse roboti elektroonikaosade vahel kõik juhtmed. Alustada võiks toite harukaablist mis jagab Kontrollermoodulisse minema toite kaheks millest teine pistik tuleb ühendada Mootoite mooduliga.
RC5 vastuvõtja tuleb ühendada Kommunikatsioonimooduli välisesses EXT_UART pesasse:
Roomiku kaks mootorit tuleb ühendada Mootoritemooduli DC3 ja DC4 pesadesse. Koodrid lähevad sinnasamasse kõrvale ENC1 ja ENC2 pesadesse:
Edasi tuleks ühendada ultraheli- ja infrapuna kaugusandurid ning palliandur. Infrapuna kaugusanduri ja pallianduri jaoks on tarbis servode pikenduskaablit. Täpsemalt on pesad näidatud piltidel:
Viimasena on jäänud ühendada LCD kus kuvatakse programmi töö ajal kõiki andurite näitusid:
Kaheksas ja viimane etapp on robotisse akude või patareide laadimine ning selle tööle panek. Akud käivad spetsiaalsesse alusplatvormiga kaasatulevasse rakisesse. Ühendades toitekaabli ja akuploki läheb robot tööle ja sinna saab peale laadida programmi.
© TTÜ, MTÜ TTÜ Robotiklubi
~~DISCUSSION~~