2012
POLOLU 3pi Treball de recerca
Jordi Hinojosa Cirera Coral Santacruz G贸mez 09/01/2012
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
1. Introducció .................................................................................................................................. 3 2. Pololu 3Pi .................................................................................................................................... 5 3. Elements del robot ...................................................................................................................... 6 3.1 Motors .................................................................................................................................. 7 3.2 Bateria ................................................................................................................................... 9 3.3 Sensors ................................................................................................................................ 11 3.4 Microcontrolador ................................................................................................................ 12 3.5 Rodes .................................................................................................................................. 14 3.6 Indicadors LED ..................................................................................................................... 14 3.7 Pantalla LCD......................................................................................................................... 15 3.8 Altaveu ................................................................................................................................ 15 3.9 Botons ................................................................................................................................. 16 3.10 Connector de programació ................................................................................................ 16 3.11 Connector d’expansió ........................................................................................................ 17 3.12 Jumpers ............................................................................................................................. 18 4. Programació del robot ............................................................................................................... 19 5. El llenguatge C ........................................................................................................................... 20 5.1 Programa main(). ................................................................................................................. 21 5.2 Tokens ................................................................................................................................. 21 5.2.1 Paraules clau ................................................................................................................. 21 5.2.2 Identificadors ................................................................................................................ 22 5.2.3 Constants ...................................................................................................................... 22 5.2.4 Operadors ..................................................................................................................... 22 5.2.5 Comentaris ................................................................................................................... 22 5.3 Operadors ........................................................................................................................... 23 5.3.1 Operadors aritmètics .................................................................................................... 23 5.3.2 Operadors d’assignació ................................................................................................. 23 5.3.3 Operadors incrementals ................................................................................................ 23 5.3.4 Operadors relacionals ................................................................................................... 23 5.3.5 Operadors lògics ........................................................................................................... 23 5.4 Control del flux d’execució ................................................................................................... 24 5.4.1 Sentencia IF .................................................................................................................. 24 5.4.2 Sentencia IF – ELSE ....................................................................................................... 24 5.4.3 Sentencia IF – ELSE múltiple .......................................................................................... 24 5.5 Sentencia SWITCH ............................................................................................................... 25 5.6 Sentencia IF Anidada ........................................................................................................... 26 1
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5.7 Bucles .................................................................................................................................. 27 5.7.1 Bucle WHILE ................................................................................................................. 27 5.7.2 Bucle FOR ..................................................................................................................... 27 5.7.3 Bucle DO … WHILE ........................................................................................................ 28 5.7.4 Sentencia Break, continue i Goto .................................................................................. 28 6. Programa principal .................................................................................................................... 30 7 Conclusions ................................................................................................................................ 61 8 Fonts d’informació ..................................................................................................................... 63 9 Agraïments ................................................................................................................................. 64
2
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
1. Introducció Els nostres objectius del treball de recerca principalment han sigut introduir als nostres coneixements la robòtica, a tota la branca de muntatge i de programació amb llenguatge C per en un futur ser nosaltres mateixos capaços de programar i arribar a tenir uns coneixements sobre la robòtica que ens permetin ser autònoms i aconseguir sense ajut de ningú crear robots dissenyats per nosaltres. D'aquesta manera, al fer un treball pràctic i no teòric ens ha permès aprendre d'una forma diferent el tema de la robòtica i així poder-nos fixar en tot el que fem per poder aprendre més de tot això. L'objectiu principal del robot ha sigut simplement aplicar tot el que aprenem al curs de l'UPC ja que hem tingut la possibilitat d'anar-hi i així poder mostrar la nostra capacitat davant de la robòtica i aprendre tot el que implica la robòtica perquè és una tecnologia que haurem de saber controlar en un futur ja que tindrà moltes utilitats. També ha sigut important per desenvolupar la nostra capacitat de treball i la nostra autonomia davant del treball, és un objectiu important saber fer les coses a temps i treballar conjuntament al grup sense baralles i sense competitivitats i la responsabilitat davant de tot el material i de tot el que ens ofereix l'UPC. Un dels altres objectius que ens vam marcar al començar aquest treball va ser poder acabar el robot i el treball lo abans possible per així poder millorar el robot que ens ofereix la UPC i fer un robot més avançat i per això necessitàvem fer aquest treball per tenir més informació sobre el que faríem desprès. Com a objectius també volíem anar a la UPC, per conèixer les seves instal·lacions, el seu professorat, tota la organització que tenen i la manera d'explicar i d'ensenyat que tenen per si en un futur volem estudiar alguna enginyeria podríem conèixer tot el món de la UPC i així anar a estudiar allà amb més seguretat. Per que aquest treball surti be també hem hagut de posar de la nostra part, és a dir, treballar amb constància, amb esforç, tenir paciència a l'hora de treballar, voler aprendre i estar durant tot l'any disposat a treballar i acceptar totes les crítiques i a fer tot el que calgui perquè el treball surti bé.
3
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
En aquest treball principalment hem treballat amb el tema de la programació. Primerament vam haver de conèixer el vocabulari i el funcionament del llenguatge C, aquest coneixement el vam obtenir gracies al curs que vam fer a la UPC, ja que, mentre apreníem això també ho practicàvem i ens resultava molt més fàcil memoritzar-lo. Una vegada ja vam tenir aquests coneixements vam començar a conèixer el que havíem de programar, en aquest cas, el pololu 3pi. Va resultar fàcil treballar amb el pololu perquè ja estava muntat i és fàcil de tractar. Quan vam iniciar l’explicació de les parts del pololu, ens vam assabentar de que no era tan senzill com creiem al principi, perquè no hi ha gaire informació i tota es redueix a la guia de programació. També ens va costar la part de programació, ja que no era com l’havíem vist a les practiques de la UPC, per programar el pololu era molt més complex. Però un cop vam inicialitzar el nostre treball ja seriosament ens vam adonar que si buscàvem bé podíem trobar tota la informació necessària per al nostre treball, també vam necessitar l’ajuda del nostre tutor del treball que ens va indicar el que no sabíem i si el que fèiem era correcte. Al anar avançant el treball tot era relativament més fàcil i ja no ens costava tant saber si la informació era correcte i poder entendre-la i sintetitzar-la. Al acabar la part teòrica del treball vam començar a intentar fer l’ampliació que ens vam plantejar al principi del treball. Aquesta és bàsicament introduir al programa principal dues noves funcions, una d’elles el tancament i l’altre el laberint. La que més ens ha costat ha sigut la del tancament, ja que, el programa base, és a dir, el programa que ens ve als exemples de llibreries de l’atmega 328p tenia molts errors i això ens va dificultar, perquè hi havia errors que no sabíem solucionar al no tenir tampoc un gran coneixement del llenguatge C. Amb una mica d’ajuda i paciència hem aconseguit tots els nostres objectius, i també hem pogut acabar el nostre treball en el temps predeterminat.
4
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
2. Pololu 3Pi El pololu 3Pi és un robot petit i autònom dissenyat per realitzar el seguiment de línia així com també per poder sortir d'un laberint. És un robot autònom ja que està alimentat per quatre bateries AA de 1.5 V i la seva velocitat màxima es de 100 cm/s. El robot porta també 5 sensors de reflexió, una pantalla LCD de 8x2 caràcters, un timbre de petites dimensions, tres polsadors per poder configurar la seva elecció, etc. i tot això està connectat a un microcontrolador AVR, que es un circuit integrat que porta les tres unitats funcionals d'un ordinador: la unitat central de processament, memòria i Imatge 1. El pololu 3Pi
unitats d'entrada i sortida. El robot mesura
aproximadament 9,5 cm de diàmetre i pesa 83 g sense comptar les bateries. El pololu 3Pi s'ha construït al voltant del microcontrolador Atmega328P amb una freqüència de 20 MHz, amb 32 kBytes de memòria flash per carregar l'acció que realitzarà el robot i amb 2 kBytes de memòria RAM per carregar variables temporals. La programació del microcontrolador es farà amb llenguatge C i per realitzar-la es necessitarà el Programador AVR ISP, per poder carregar-lo mitjançant un port USB. Els seus elements són: –
Motors
–
Bateria
–
Sensors
–
Microcontrolador
–
Rodes
–
Indicadors LED
–
Pantalla LCD
–
Altaveu
–
Botons
–
Connectors de programació
–
Connector d’expansió
–
Jumpers 5
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
3. Elements del robot Els elements principals del robot són els motors, que ens permeten poder accionar les rodes a traves del eix que el uneix, però el seu funcionament l’explicarem en el següent punt. També trobem les bateries que són les que s’encarreguen de donar-li vida al nostre robot. Un altre element són els sensors que són els que li permeten al robot poder fer la funció del sensor, en aquest cas la de seguir una línia, a més a més també tenim el microcontrolador que és l’encarregat de fer funcionar tot el robot. Per un altre banda tenim les rodes que són les que fan moure’s al robot. També hi ha la pantalla que ens permet veure el programes i/o funcions, també el connector de programació amb la funció de connectar el nostre robot a l’ordinador. A més a més tenim els indicadors LEDs, botons, l’altaveu, el connector d’expansió i els jumpers.
Imatge 2. Parts del robot 3Pi.
6
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Imatge 3. Parts del robot 3pi.
3.1 Motors El nostre robot porta dos motors de corrent continua, per fer accionar les rodes i així poder moure’s. Un motor de corrent continua és aquell que converteix energia elèctrica en energia mecànica, normalment mediant el moviment rotatori. Aquests motors són molts versàtils, i gràcies al seu fàcil control de posició, par i velocitat han sigut molt demandats, però amb la electrònica, sobretot amb el robot de tipus asíncrono, la seva demanda ha disminuït ja que aquest y el motor DC són controlats de la mateixa manera i el asíncrono és més barat. Una de les principals característiques dels motors DC, és la possibilitat de regular la velocitat mentre esta funcionant el motor. I els inconvenients són el preu, el manteniment i la dificultat de fer-ho. Una altre pot ser que utilitza casi tota (90%) l’energia elèctrica que rep i la converteix en mecànica. També tenim que duran molt per la Imatge 4. Elements del motor. seva baixa inductivitat. Els motors que tenim al nostre robot pololu 3pi són els motors DC de escombretes. Al no tenir 7
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
retenció magnètica afavoreix les tasques de control de velocitat i posicionament. Aquest té una baixa inèrcia del rotor amb el qual facilita les altes frenades i acceleracions, necessàries per alguns circuits de línia. La funció de les escombretes és subministrar corrent des d’una part del bobinat a l’altre part, produint polsos magnètics, és a dir, emissions de energia electromagnètica d’alta intensitat en un període de temps curt, que permet el gir en la mateixa direcció. La velocitat és el primer valor que s’utilitza als motors i es representa en revolucions per minut(rpm) i el parell de força mesurat en (kg·cm) o (oz·in). Sabem la potencia que fa el motor multiplicant el parell per la velocitat. El motor disposa d’uns engranatges que fan reduir les revolucions i augmentar el par, ja que si no la velocitat seria massa alta pel robot. La equivalència de voltes de motor amb la roda és de 30 voltes de motor per cada volta de roda. La velocitat del robot s'aconsegueix canviant polsos alts i baixos. Per exemple si una de les entrades del motor té un voltatge alt i l'altre un voltatge baix, el motor funcionarà entre endavant i parar, i això farà que el robot disminueixi la seva velocitat. Al pololu 3pi, podem fer el control de velocitat a través de les sortides PWM del microcontrolador que generen els temporitzadors Timer0 i Timer2. Això vol dir que podem fer un cicle de treball per als dos motors a la vegada i independentment podrà estar atent a altres necessitats.
Imatge 5. Gràfica de senyal PWM.
El pololu 3pi té dos motors independents a cada costat que creen un mecanisme de conducció que s'anomena conducció diferencial. Girar amb aquest mètode consisteix en fer rodar els motors a diferents velocitats. Si la roda dreta gira mes ràpid que la roda esquerra es mourà cap a la dreta i a l’inrevés, si la roda dreta gira mes ràpid que la roda esquerra es mourà cap a l'esquerra. 8
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Si volem que el motor giri sobre si mateix hem de posar les mateixes velocitats per als dos motors però amb signe diferent, i així una roda gira amb un sentit i l'altre gira cap a l'altre sentit i aconseguim que rodi sobre si mateix.
3.2 Bateria Una alimentació elèctrica, també anomenada pila, és un dispositiu que genera energia elèctrica a través d'una reacció química. Les bateries treballen amb electrons que es mouen des de el pol positiu fins el pol negatiu. Per conèixer la quantitat d'electrons que es mouen d'un pol a l'altre utilitzem els volts (V) o el que es el mateix, la diferencia de potencial. També es pot conèixer la força de la bateria que són la quantitat d'electrons que es mouen per segon, que es mesura amb la Intensitat (A). La relació entre la intensitat i els electrons movent-se per segon és de 1A i 6x1018. Per qualsevol bateria en funcionament, el voltatge es redueix conforme passa el temps fins a arribar a perdre tota
Imatge 6. Piles que utilitza el pololu.
la seva energia. Per connectar mes d'una bateria es poden utilitzar dos maneres, en sèrie, quan es connecta el pol positiu d'una bateria amb el pol negatiu de l'altre i es suma la tensió, o en paral·lel quan es connecten tots els pols positius junts i tots els pols negatius, per tant la tensió serà el mateix però la potència es sumarà. Al cas del pololu 3pi les bateries estan connectades en sèrie ja que així podem augmentar la tensió de les piles. El voltatge de la bateria es pot reduir amb l'ús i el voltatge pot no ser constant, però existeixen uns tipus de regulador de voltatge que fan que el voltatge es mantingui constant. L'energia al pololu 3pi es gestiona de manera diferent amb dos tipus de reguladors de voltatge que augmenten o disminueixen el voltatge segons la part que necessitem utilitzar del robot en aquell moment. El pololu 3pi utilitza els dos tipus de reguladors que hi han. Un d'ells es el regulador lineal, que el que fa és disminuir la quantitat de voltatge que passa, per tant el valor del voltatge a la sortida del regulador serà mes petit que el de l'entrada. La diferència de potencial entre la sortida i l'entrada es perd en forma de calor, per tant no te cap utilitat. L'altre regulador que hi ha és el regulador switching, aquest utilitza la tensió i la alterna amb una freqüència mes alta i així aconseguir una major estabilitat en el voltatge, a més, també pot 9
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
convertir i regular els voltatges baixos i els transforma en alts. Aquests reguladors són mes eficaços que els lineals ja que porten un inductor que acumula tota l'energia i la deixa anar suaument. Al nostre robot l'inductor es troba al costat de la roda boja marcat amb un 100. Sistema de potència del pololu 3pi El voltatge total de les 4 piles AA hauria de ser de 6V tenint en compte alcalines.
que
les
Per
piles
connectar
són els
motors i els LEDs sensors IR en línia, que al diagrama estan marcats
com
VBOOST,
necessitem un voltatge més gran utilitzem un regulador switching que passa els 6V a 9.25V i així
Imatge 7. Circuit de les bateries del robot
poder-los alimentar bé. I per connectar el microcontrolador i les senyals digitals, marcades com VCC, la tensió que necessitem és mes baixa per tant utilitzem un regulador lineal que reduirà el voltatge a 5V. Al utilitzar el regulador switching (VBOOST) obtenim majors avantatges que si treballéssim amb motors que treballen amb bateries directament, com per exemple: el voltatge alt es reserva per als motors, els motors treballen a la mateixa velocitat tot i que el voltatge estigui regulat i els cinc LEDs sensors IR connectats en sèrie consumeixen menys energia. Les bateries del pololu tenen tres resistències que el que produeixen és una reducció de la tensió en una proporció de 2/3. El nostre robot no va disminuint la seva energia fins que s'esgota del tot si no que funcionarà amb el màxim rendiment fins que de cop es para.
10
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Imatge 8. Circuit de monitoratge de la bateria.
3.3 Sensors Els sensors de reflexió són una font de llum i un receptor de llum, que estan molt a prop un de l'altre i estan integrats en una mateixa peça. La font de llum emet un raig de llum el qual, si la superfície es blanca, es reflectirà i el receptor de llum rebrà llum. En canvi, si la superfície es negra, no es reflectirà cap tipus de llum. Aquests sensors es connecten a la unitat central o al microcontrolador segons l'esquema següent:
Imatge 9. Circuit del sensor connectat al microcontrolador.
Imatge 10. Sensors del robot 3pi.
11
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Imatge 11. Lectura dels sensors.
3.4 Microcontrolador La part més important del pololu és el microcontrolador, que és des d’on es controlen totes les entrades i sortides del robot. Un microcontrolador és un processador concentrat fins al punt de poder tenir un únic circuit integrat especialitzat en controlar equips electrònics, que inclou en un sol xip totes les unitats funcionals d’un ordinador. Al microcontrolador trobem la memòria, que és la que ho emmagatzema tot, també trobem pins d’entrada i sortida, que és on es connectaran tots els demés elements del robot per així poder funcionar i un microprocessador que es tot el que li dona la característica de microcontrolador. El microcontrolador del pololu 3pi és l’atmega328P que funciona amb una memòria Flash de 32KB, 2KB de memòria RAM i 1 KB de memòria EEPROM i té 32 pins d’entrada i sortida. Aquest funciona a la velocitat de 20 MHz.
Imatge 12. Microcontrolador.
12
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
A continuació veurem una taula on estan especificats els noms de cada pin, el seu numero i la funció que realitza cadascun d’ells dintre del nostre robot. ATmega328
Pin
Funció
PD3 (OC2B / INT1)
1
Motor driver
PD4 (XCK / TO)
2
LCD E
GND
3
Microcontrolador
VCC
4
Microcontrolador / senyals digitals
GND
5
Microcontrolador
VCC
6
Microcontrolador / senyals digitals
PB6 (XTAL1/TOSC1)
7
Oscil·lador
PB7 (XTAL2/TOSC2)
8
Oscil·lador
PD5 (OC0B / T1)
9
Motor driver
PD6 (OC0A / AIN0)
10
Motor driver
PD7 (AIN1)
11
LCD / LED verd
PB0 (CLKO/ICP1)
12
LCD R/W
PB1 (OC1A)
13
Botó A
PB2 (SS/OC1B)
14
Brunzidor
PB3 (MOSI/OC2A)
15
Motor driver/ connexió de programació
PB4 (MISO)
16
Botó B / connexió de programació
PB5 (SCK)
17
Botó C / connexió de programació
AVCC
18
Font de 9.25 V
ADC6
19
Voltatge de bateria
AVCC
20
Font de 9.25 V
GND
21
Microcontrolador
ADC7
22
VCC
PC0 (ADCO)
23
Sensors i control de IR LED
PC1 (ADC1)
24
Sensors i control de IR LED
PC2 (ADC2)
25
Sensors i control de IR LED
PC3 (ADC3)
26
Sensors i control de IR LED
PC4 (ADC4/SDA)
27
Sensors i control de IR LED
PC5 (ADC5 / SCL)
28
Alimentació infraroja
PC6 (RESET)
29
Reset / connexió de programació 13
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
PD0 (RXD)
30
Lliure
PD1 (TXD)
31
LED vermell
PD2 (INTO)
32
LCD Rs
3.5 Rodes El robot 3pi pololu porta 3 rodes, dues de elles són dues rodes de goma en silicona per poder tenir una millor atracció y que el robot no rellisqui. Aquestes estan agafades al eix del motor, i el seu pes és de 3.2 grams, el seu diàmetre es de 32mm i 7mm d’ample. Les rodes recorren 100,53 mm per cada una de les voltes que fa. A més d’aquestes dues, en la part inferior de la placa, tocant el terra porta una altre de plàstic que serveix per fer girar el robot amb més comoditat y per poder desplaçar el robot, ja que si no estigues tocaria la placa amb el terra, i és anomenada roda boja. El nostre Pololu a més, té un LED col·locat a la part on estan situats els sensor, que no fa cap funció de les que fan els LEDs normalment. Aquest, està posat de manera que toqui amb el terra i així el Pololu esta equilibrat, ja que abans de posar-li el LED estava desequilibrat perquè la roda boja tocava el terra i a l’altra banda res tocava el terra y llavors tocava la placa i es feia malbé.
Imatge 13. Rodes del pololu.
Imatge 14. Roda boja.
3.6 Indicadors LED El pololu consta de 4 indicadors LED: dos blaus, un vermell i un verd. Els LEDs són díodes semiconductors que emeten llum. S'utilitzen com a indicadors en molts dispositius i cada vegada amb més freqüència com a il·luminació. En aquest cas, al pololu 3Pi, s'utilitzen com a indicadors.
Imatge 15. Indicadors LED
14
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Els dos LEDs blaus la funció que tenen és encendre’s quan encenem el robot i es mantindran encesos fins que parem el Pololu, i el LED verd i vermell depenent de la funció que li donem en el programa poden fer una coses o una altra.
3.7 Pantalla LCD El robot porta una pantalla LCD en paral·lel de 8x2 caràcters per indicar el que nosaltres li diem al robot. Les pantalles LCD també es poden anomenar de cristall líquid. El cristall líquid consisteix en una agrupació de petits segments que s'anomenen píxels, que poden ser manipulats per presentar informació. Aquestes pantalles són molt importants per la mida i el seu pes, ja que només consten de dues plaques fines i entre Imatge 16. Pantalla LCD elles està el cristall líquid.
3.8 Altaveu L'altaveu és un transductor electroacústic que converteix un senyal elèctric en so. Es l'element que més determina la qualitat del so. El pololu porta incorporat un altaveu petit per poder reproduir la música o els sons que li apliquem. Aquest, té un voltatge de 1.5 V, té una resistència de 6 ohms i funciona a una velocitat de 3200Hz.
Imatge 17. Altaveu Pololu.
15
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
3.9 Botons El pololu 3Pi consta de 3 botons, el botó A, el botó B i el botó C, que estan connectats amb la pantalla LCD i ens permeten moure'ns pel menú del robot i accedir a cadascuna de les funcions que li vulguem introduir. També hi ha els botons de reset que el fem servir per tornar a l’inici del menú i el de power que el fem servir per encendre i apagar el robot.
Imatge 19. Botons power i reset.
Imatge 18. Botons A, B i C.
3.10 Connector de programació El connector de programació és un element que ens permet poder introduir i/o compilar programes des d’un ordinador. Consta per un cable USB connectat des de l’ordinador fins la targeta d’expansió, que aquesta té tres LEDs, un groc, un vermell i un verd per indicar la connexió, ja que si està en color vermell és que està connectat correctament. El robot està connectat a la placa d’expansió mitjançant un connector ISP.
Imatge 20. Connector de programació
16
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
3.11 Connector d’expansió El connector d’expansió són una sèrie de pins que permeten poder connectar una altre placa o una altra pantalla al robot. Els pins que formen part del connector d’expansió són: GND, PD0, PD1, ADC6, ADC7, PC5, VBST, VBAT, VCC, PC6, PB3, PD2, PD4, PB4, PD7, VO, PB0, PB1 i PB5. Hi ha diferents tipus de plaques, hi ha que tapen la pantalla LCD i aquest pins que deixa lliures la pantalla els utilitza per fer altres funcions com per exemple posar un altre microcontrolador, i l’altre tipus són els que es pot veure la pantalla LCD, ja que, està feta de manera de que es pugui veure.
Imatge 21. Placa d’expansió
Imatge 22. Placa d’expansió
Imatge 23. Connector d’expansió
17
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
3.12 Jumpers Un Jumper és un element que ens permet connectar dos terminals de manera temporal sense haver de efectuar cap operació addicional, aquesta unió tanca el circuit elèctric del que forma part. El pololu té tres jumpers, el primer serveix per interconnectar els sensors IR LEDs, el segon per poder puntejar el voltatge de la bateria de entrada i el tercer jumper, serveix per puntejar al trimmer d’usuari del canal Imatge 24. Jumpers d’entrada del potenciòmetre.
18
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
4. Programació del robot En primer lloc instal·lem el programa AVR Studio 4, una vegada instal·lat obrim el programa ens sortirà una finestra amb dues opcions, una de les opcions és crear un nou projecte i l'altre obrir un projecte que ja hem creat anteriorment i l'hem guardat. Si seleccionem l'opció d'obrir un projecte que ja tenim guardat apareixerà directament el que ja teníem guardat.
Imatge 25. Logotip AVR Studio 4
Per crear un nou projecte hem de seleccionar l'opció new project i ens apareixerà una finestra on haurem de seleccionar el tipus de projecte, project type, que surt amb el nom de AVR GCC i posem un nom al projecte. Cliquem a next i haurem d'escollir el tipus de plataforma i de dispositiu que utilitzarem. El tipus de plataforma que utilitzarem serà AVR simulator 2 i el dispositiu el ATmega328P i li donem a finish. Un cop creat el projecte veurem una finestra on podrem crear el codi que desprès podrem carregar al robot. Un cop creat el codi s'hauran d'afegir les llibreries, que es farà de la següent manera: hem d'anar a project i seleccionar l'opció de configuration options, cliquem a libraries i a l'opció Available Link Objects escollim libpololu_atmega328p.a i polsem add library i a continuació acceptar. Un cop afegides les llibreries al codi comprobem si està ben escrit polsant F7. A la finestra que apareix la part inferior de la pantalla on posa build, es podran veure els errors o les advertències que hi ha al codi que volem afegir al robot. Fet això si no hi ha cap error ni cap advertència introduirem el codi al robot. Connectem el robot a l'ordinador amb el cable USB i a l'opció tools de la barra d'eines clicarem a program AVR i a connect. Un cop fet això apareixerà una finestra on haurem de seleccionar la plataforma i el port de connexió per poder programar el robot. On posa platform escollim l'opció STK500 i on posa port l'opció COM9 i seguidament polsem connect. A l'apartat flash de la nova finestra que apareix seleccionem l’arxiu que volem carregar al robot Input HEX File i encenem el robot i cliquem a program i esperem a que es carregui el codi al robot. Un cop fet això ja podem desconnectar el robot de l'ordinador i provar si el nostre codi funciona correctament al robot.
19
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5. El llenguatge C És un llenguatge de programació, és a dir, un idioma artificial que és dissenyat expressar computacions que seran aplicades a màquines. Aquest llenguatge esta orientat per posar en funcionament els sistemes operatius, al ser un llenguatge molt flexible ens permet fer-ho amb estils diversos. La primera estandardització del llenguatge C va ser ANSI i la seva base procedeix del BCPL. Originalment es va desenvolupar per a programadors i per a incentivar la programació independent de les màquines, però ha aconseguit un nivell de popularitat enorme, i ha estat utilitzat per a contextos molt diferents de la programació de sistemes que era la funció per la qual va se creat aquest llenguatge. Té unes estructures d’un llenguatge d’alt nivell però inclús tenint aquestes estructures d’alt nivell que ens farien molt difícil de saber fer-lo funcionar, disposa d’unes construccions del llenguatge que en permet un control amb un nivell baix i un conjunt molt reduït de paraules claus, i aquest es un dels objectius del llenguatge C, que no calguin gaires instruccions però poder traduir cada element del llenguatge. També disposa de moltes plataformes, més que en quasi tots els demes llenguatges. Treballa amb dades que son directament tractables per el hardware de la majoria de computadores actuals. Aquestes dades poden ser manipulades per les operacions aritmètiques que proporciona la computadora, però no proporciona mecanismes per tractar dades que no siguin bàsiques, si no que a de ser el programador el que les desenvolupi, això fa que el codi que es genera sigui molt eficient, ja que el bàsic ho fa la computadora. Tampoc proporciona mecanismes d’emmagatzematge de dades que no siguin estàtiques, ja que es les úniques que tracta, ni tampoc de entrada ni de sortida. Totes això fa que aquest llenguatge, el llenguatge C sigui molt reduït i compiladors fàcils d’aplicar a diferents sistemes. Però aquesta carència la millora a partir de les funcions de les llibreries per realitzar totes aquestes tasques i així no dependre del sistema operatiu. Alguns dels inconvenients del llenguatge C es que si el comparem amb els llenguatges de tipus de dades dinàmic tenim la gran diferencia de velocitat de desenvolupament, ja que en el compilador C es limita només a traduir codi sense afegir res i això dona molta més feina. El manteniment també és molt més difícil i costós ja que el codi es presenta en sentències curtes i difícil d’interpretar i aquestes sentencies compliquen a revisió i manteniment d’aquest.
20
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5.1 Programa main(). Podem dir que tots el programes de llenguatge C han de tenir un programa principal que es on comença tot el programa. També es pot considerar una funció però es la funció que esta per sobre de les altres, és a dir, la més important. Aquesta es la main() que la veurem així als programes: main() { sentencia_1 sentencia_2 … }
Les claus serveixen per agrupar sentencies de manera que així només es comporten com una única sentencia. Tot el cos ha d’anar entre una clau d’apertura i una altra de tancament.
5.2 Tokens Hi ha sis tokens, que són components sintàctics, en el vocabulari C: 5.2.1 Paraules clau Al llenguatge C existeixen una sèrie de paraules claus que no podem utilitzar com identificadors, és a dir, com a nombres de variables o de funcions. Aquestes paraules serveixen per indicar a la computadora que realitzi tasca determinada i tenen un significat especial per al compilador. La sèrie de paraules clau del ANSI C són les següents 32: Auto
Double
int
Struct
Break
Else
long
Switch
Case
Enum
register
Typedef
Char
Extern
return
Union
Const
Float
short
Unsigned
Continue
For
signed
Void
Default
Goto
sizeof
volatile
Do
If
static
while
21
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5.2.2 Identificadors És un nom amb el que es fa referencia a una funció. Cada llenguatge te les seves pròpies normes per escollir el nom de les funcions i variables. A l’ANSI C són les següents: A.
Es pot formar amb una seqüencia de lletres minúscules i majúscules de l’ “A” fins la
“Z” i de números de 0 al 9. B.
El caràcter subratllat es considera una lletra més.
C.
No es poden posar espais en blanc.
D.
El primer caràcter mai pot ser un dígit.
E.
Les majúscules i minúscules es distingeixen.
F.
Permet definit identificadors de fins a 3 caràcters de longitud.
5.2.3 Constants Normalment s’utilitzen variables a l’hora de crear un programa però també existeixen les constants, és a dir, valors que sempre són els mateixos. Existeixen diferents tipus de constants: A.
Constants numèriques: Valors numèrics, enters o de punt flotant.
B.
Constants caràcter: Qualsevol caràcter individual tancat per apòstrof.
C.
Cadenes de caràcters: Conjunt de caràcters tancats entre cometes(exemple:“s”).
D.
Constants simbòliques: Tenen un nombre i no poden canviar al llarg del programa,
en el llenguatge C es defineixen mitjançant el processador o la paraula const. 5.2.4 Operadors Són signes especials que indiquen determinades operacions a realitzar amb variables i/o constants sobre les que actua en el programa. Al llenguatge C tenim varies tipus com aritmètica, d’assignació, relacionals, lògiques i altres. Separadors: Estan constituïts per un o més espais en blanc, tabuladors i caràcters de nova línia. La seva funció es ajudar al compilador a descompondre el programa font a cada un dels seus tokens. 5.2.5 Comentaris En aquest llenguatge ens esta permès introduir comentaries als fitxers font que conté el codi del seu programa. La seva funció es d’explicació o d’aclariment sobre com està fet el programa. El compilador no li fa gens de cas als comentaris.
22
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5.3 Operadors És un caràcter o grup de caràcters que actua sobre alguna o algunes variables per realitzar una funció determinada amb un resultat determinat. Poden ser unaris, binaris i ternaris segons si actuen sobre un, dos o tres operadors. Al llenguatge C hi ha molts operadors i de diversos tipus com: 5.3.1 Operadors aritmètics Són el més senzills d’entendre y d’utilitzar, y tots son binaris, i utilitzen : Suma +, Resta -, Multiplicació *, divisió / i rest %. Tots aquests operadors en poden aplicar a constants, variables i expressions, i el resultat l’aconseguim d’aplicar l’operació corresponent entre els dos operants. El més difícil d’entendre es el rest %, que només es aplicable a constants, variables o expressions int. 5.3.2 Operadors d’assignació Aquest operadors dipositen a la zona de memòria que li pertoca la variable, el resultat d’una expressió o el valor d’altre variable. 5.3.3 Operadors incrementals els operadors incrementals (++) i (--) son operadors unitaris que incrementen o disminueixen en una unitat el valor de la variable a la que afecta. 5.3.4 Operadors relacionals Els operadors relacionals permeten estudiar si es compleix o no les condicions i depenent si es compleixen les condicions o no tenen un resultat o un altre. En el llenguatge C hi ha varis operadors relacionals que son: igual que: == , menor que: < , major que: > , menor o igual que: <= , major o igual que: >= , diferent que: = . Tots aquest son binaris i la seva forma es: expressió1 op expressió2. Op vindria a ser un dels operadors anomenats abans i el funcionament es basa en avaluar expressió i expressió 2 i es comparen els resultats, si es compleix el resultat es 1 i si no es compleix es 0. 5.3.5 Operadors lògics Son binaris que permeten combinar els resultats dels racionals i comprovar que es compleixen varies condicions, hi ha dos tipus: operador Y(&&) i l’operador O(ll), que en angles son els operadors and i or. Si les expressions 1 i 2 son verdaderes l’operador && torna un 1 i si es al contrari l’operador ll torna un 1. Aquests dos operadors es poden combinar l’únic problema es que es més difícil d’interpretar. 23
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
5.4 Control del flux d’execució El llenguatge C te varies sentencies per modificar l’ordre de l’execució, i les més utilitzades s’agrupen en bifurcacions, que son les que permeten escollir entre dos o més opcions i els bucles que permet executar repetidament un conjunt d’instruccions tantes vegades com es vulgui, canviat o actualitzant alguns valors. 5.4.1 Sentencia IF Aquesta sentencia de control permet executar o no una sentencia segons es compleixi o no la condició. if ( expressió)
sentencia;
5.4.2 Sentencia IF – ELSE Aquesta sentencia permet realitzar una bifurcació, segons es compleixi o no alguna condició del programa. if (expressió)
sentencia_1;
else
sentencia_2;
5.4.3 Sentencia IF – ELSE múltiple Aquesta sentència permet realitzar una ramificació múltiple, executant una entre varies parts del programa depenent si es compleix una entre n condicions. if (expressió_1)
sentencia_1;
else if (expressió_2) 24
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
sentencia_2;
else if (expressió_3)
sentencia_3;
else if (...)
... [else sentencia_n;]
5.5 Sentencia SWITCH Es molt similar a la sentència if...else amb múltiples ramificacions, però són diferents, ja que tenen importants diferències. La forma general és: switch (expressió) { case expressió_cte_1: sentencia_1; case expressió_cte_2: sentencia_2; ... case expressió_cte_n: sentencia_n; [default: sentencia;] }
També podem executar la mateixa sentencia_i per a varis valors del resultat de que ens dóna expressió i ho podem fer posant varis case expressió_cte seguits. Com per exemple:
25
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
switch (expressió) { case expressió_cte_1: sentencia_1; break; case expressió_cte_2: case expressió_cte_3: sentencia_2; break; default: sentencia_3; }
5.6 Sentencia IF Anidada Anomenem sentència if anidades les que inclouen a altres if dintre del if, però van incloses a la part de la sentència. Per exemple: if (a >= b) if (b != 0.0) c = a/b;
Algunes vegades, poden haver-hi dificultats per interpretar amb sentencies if..else anidadas, com en aquest exemple: if (a >= b) if (b != 0.0) c = a/b; else c = 0.0;
El principal dubte seria quin dels dos if correspon a la part else. Però gracies als espais en blanc, ens indica que el else pertany al segon if, ja que la regla diu que el else pertany al if més proper, en aquest cas el segon. Però si nosaltres volguéssim que el else pertanyés al primer if, hauríem d’utilitzar les claus de la següent forma:
26
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
if (a >= b) { if (b != 0.0) c = a/b; } else c = 0.0;
5.7 Bucles Aquesta sentencia ens permet repetir una sèrie de vegades la execució de unes línies de codi. Es pot realitzar per un numero de vegades o fins que es compleixi una determinada condició de tipus lògic o aritmètic. Les tres construccions del llenguatge C per realitzar bucles son el while, el for y el do...while. 5.7.1 Bucle WHILE Aquesta permet executar repetidament, una sentencia o bloc de sentencies. La forma es la següent: while (expressió_de_control) sentencia;
La sentencia al ser certa s’executa, i si no es certa no s’executa, es torna a avaluar expressió_de_control i aquesta continua en la línia següent a sentencia. 5.7.2 Bucle FOR És el més utilitzat i versàtil del llenguatge C, i la seva forma general és: for (inicialització expressió_de_control actualització) sentencia inicialització; while (expressió_de_control) { sentencia; actualització; }
27
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Al principi executem inicialització i a continuació s’avalua expressió_de_control, i poden passar dues coses que sigui falsa o verdadera, si es el primer cas, segueix fent la sentencia següent a la construcció del for, i si es certa s’executa la sentencia i l’actualització i es torna a avaluar expressió_de_control fins que sigui falsa. El que fa l’actualització es actualitzar variables o incrementar comptadors. for (pe =0.0, i=1; i<=n; i++){
pe += a[i]*b[i];
}
En aquest poden veure que el bucle es repetirà n vegades.
5.7.3 Bucle DO … WHILE En aquesta l’avaluació de expressió_de_control es realitza al final del bucle, però això desprès d’haver executat al menys una vegada las sentencies entre claus i es tornen a executar mentre sigui true. La forma general es: Do sentencia; while(expressió_de_control);
5.7.4 Sentencia Break, continue i Goto La instrucció break interromp l’execució del bucle on s’ha inclòs i fa sortir al programa de ell. La sentencia continue fa que el programa comenci el cicle del bucle allà on estigui el continue. La sentencia goto fa saltar al programa a la sentencia on s’ha escrit. Per exemple:
28
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
sentencies ...
...
if (condició)
goto altre_lloc; /* salt al lloc indicat per l’etiqueta */
sentencia_1;
sentencia_2;
...
altre_lloc: // aquesta és la sentencia a la que salta
sentencia_3;
...
29
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
6. Programa principal Aquest robot està programat per poder seguir una línia i a més a més, fer el tancament i el laberint. Està distribuït en diferents menús per poder veure el funcionament de cadascuna de les parts per separat i així també poder moure’ns pel robot amb més facilitat i entendre-ho a l’hora de moure’ns per la pantalla. El nostre programa principal consta de dotze menús. El primer és el de les bateries, que té la funció d’indicar-nos el voltatge que tenen en aquell moment. Un altre menú és el de LEDs, que la seva funció es fer una combinació d’encendre i apagar el LED vermell i verd, per comprovar el seu funcionament. També tenim el menú de sensors, que ens indica la reflexió dels sensors. A més a més també hi ha el de motors, que el que fa es comprovar el que el seu funcionament sigui correcte. El següent menú és el de la música, que la seva funció és descriure una melodia de música i així es comprova el bon funcionament dels altaveus. Un altre menú és el trimpot, que ens mostra per pantalla el valor del potenciòmetre i també el menú del temporitzador. Els següents menús són els que fan la funció principal que són els menús de seguidor, turbo seguidor i seguidor PID, que tots tres fan la funció de seguidor de línia, però amb la diferencia que el segon millora la potència dels motors i el tercer l’ajusta amb un control adaptatiu PID. Els últims menús són els de tancament i laberint. A continuació explicarem part per part, els menús del nostre robot i totes les seves funcions: Llibreria del pololu, a més a més esta inclosa en el projecte la llibreria de l’atmega 328p. #include <pololu/3pi.h>
30
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Definició de constants, el “PROGMEM” s’utilitza com a identificador per introduir les dades. // Missatges d’introducció. El “PROGMEM” és l’identificador per introduir les dades per entrar en l’espai del programa. const char welcome_line1[] PROGMEM = " Pololu"; const char welcome_line2[] PROGMEM = "3\xf7 Robot"; // \xf7 is a greek pi character const char demo_name_line1[] PROGMEM = "CORAL"; const char demo_name_line2[] PROGMEM = "JORDI24"; const char dema_name_encierro_line1[] PROGMEM = "Programa"; const char dema_name_encierro_line2[] PROGMEM = "Encierro"; char path[100] = ""; unsigned char path_length = 0; // la longitud de la ruta. const char instructions_line1[] PROGMEM = " Usa B "; const char instructions_line2[] PROGMEM = " elegir"; const char instructions_line3[] PROGMEM = "Pulsa B"; const char instructions_line4[] PROGMEM = " :)! "; const char thank_you_line1[] PROGMEM = "Moltes "; const char thank_you_line2[] PROGMEM = "Gracies "; const char main_menu_intro_line1[] PROGMEM = " Menu"; const char main_menu_intro_line2[] PROGMEM = " ----"; const char menu_line2[] PROGMEM = "\x7f" "A \xa5" "B C\x7e"; const char back_line2[] PROGMEM = "\6B"; const char menu_line1_PID[] PROGMEM = "Seguidor"; const char menu_line2_PID[] PROGMEM = " PID "; const char menu_bat_test[] PROGMEM = "Bateria"; const char menu_led_test[] PROGMEM = "LEDs"; const char menu_lcd_test[] PROGMEM = "LCD"; const char menu_ir_test[] PROGMEM = "Sensors"; const char menu_motor_test[] PROGMEM = "Motors"; const char menu_music_test[] PROGMEM = "Musica"; const char menu_pot_test[] PROGMEM = "Trimpot"; const char menu_time_test[] PROGMEM = "Tempo."; constcharmenu_seguidor[] PROGMEM = "Seguidor"; constcharmenu_turbo_seguidor[] PROGMEM = "T.Seg"; constcharmenu_seguidor_PID[] PROGMEM = "Seg. PID"; constcharmenu_encierro[] PROGMEM = "Encierro"; const char menu_maze[] PROGMEM = "Laberint";
31
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Definició de les funcions que ha de realitzar el robot. voidbat_test(); voidled_test(); voidlcd_test(); voidir_test(); voidmotor_test(); voidmusic_test(); voidtime_test(); voidpot_test(); void seguidor(); voidturbo_seguidor(); voidseguidor_PID(); void encierro(); void maze(); typedef void (*function)(); const function main_menu_functions[] = { bat_test, led_test, pot_test, ir_test, motor_test, music_test, time_test, seguidor, turbo_seguidor, seguidor_PID, encierro, maze}; const char *main_menu_options[] = { menu_bat_test, menu_led_test, menu_pot_test, menu_ir_test, menu_motor_test, menu_music_test, menu_time_test, menu_seguidor, menu_turbo_seguidor, menu_seguidor_PID, menu_encierro, menu_maze}; const char main_menu_length = sizeof(main_menu_options)/sizeof(main_menu_options[0]);
Definició de constant de so. // Un parell de melodies senzilles que estan emmagatzemades en l’espai del programa. const char welcome[] PROGMEM = ">g32>>c32"; const char thank_you_music[] PROGMEM = ">>c32>g32"; const char beep_button_a[] PROGMEM = "!c32"; const char beep_button_b[] PROGMEM = "!e32"; const char beep_button_c[] PROGMEM = "!g32"; const char timer_tick[] PROGMEM = "!v8>>c32"; Definició de constant. constchar dema_name_seguidor_line1[] PROGMEM = "Seguidor"; constchar dema_name_seguidor_line2[] PROGMEM = "Linea";
32
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Definició de constant per gràfic en pantalla. const char go[] PROGMEM = "L16 cdegreg4"; // Dades per la generació dels caràcters utilitzats en load_custom_character // I display_readings. Per readinglevels[] a partir de les diverses // compensacions, que poden generar tots els 7 caràcters addicionals necessaris per a un // gràfic de barres. També s’emmagatzema a l’espai del programa. const char levels[] PROGMEM = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 }; Definició de constants per música. // Aquest caràcter és una nota musical. constprog_char note[] PROGMEM = { 0b00100, 0b00110, 0b00101, 0b00101, 0b00100, 0b11100, 0b11100, 0b00000, };
33
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Definició de constant per dibuixar la fletxa en pantalla LCD. // Aquest caràcter és una fletxa cap enrere. constprog_charback_arrow[] PROGMEM = { 0b00000, 0b00010, 0b00001, 0b00101, 0b01001, 0b11110, 0b01000, 0b00100, }; Funció que controla les barres de la pantalla LCD. // Aquesta funció fa la càrrega de caràcters personalitzats a la pantalla LCD. Es poden carregar fins a 8 caràcters // els fem servir per a 6 nivells d’un gràfic de barres, més una fletxa cap enrere I un caràcter musical. void load_custom_characters() { lcd_load_custom_character(levels+0,0); // no offset, e.g. one bar lcd_load_custom_character(levels+1,1); // two bars lcd_load_custom_character(levels+2,2); // etc... lcd_load_custom_character(levels+4,3); // skip level 3 lcd_load_custom_character(levels+5,4); lcd_load_custom_character(levels+6,5); lcd_load_custom_character(back_arrow,6); lcd_load_custom_character(note,7); clear(); // the LCD must be cleared for the characters to take effect } Constant que defineix els valors de la barra de la gràfica. // 10 nivells de caràcters gràfics de barres. const char bar_graph_characters[10] = {' ',0,0,1,2,3,3,4,5,255};
34
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funci贸, veure el valor de la bateria en pantalla. // Mostra el voltatge de la bateria. void bat_test() { int bat = read_battery_millivolts(); print_long(bat); print("mV"); Funci贸: esperar 250 ms o polsar el bot贸 B. delay_ms(100); } char wait_for_250_ms_or_button_b() { inti; for(i=0;i<25;i++) { delay_ms(10); if(button_is_pressed(BUTTON_B)) return 1; } return 0; } Funci贸: parpelleig dels LEDs vermell i verd. // Parpelleja el LED. void led_test() { play("c32"); print("Red "); red_led(1); if(wait_for_250_ms_or_button_b()) return; red_led(0); if(wait_for_250_ms_or_button_b()) return; play(">c32"); lcd_goto_xy(0,0); print("Green"); green_led(1); if(wait_for_250_ms_or_button_b()) return; green_led(0); if(wait_for_250_ms_or_button_b()) return; } 35
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funció: mostrar el valor que emeten els sensors mitjançant la barra a la pantalla LCD. void ir_test() { unsigned int sensors[5]; // an array to hold sensor values if(button_is_pressed(BUTTON_C)) read_line_sensors(sensors, IR_EMITTERS_OFF); else read_line_sensors(sensors,IR_EMITTERS_ON); unsigned char i; for(i=0;i<5;i++) { // Inicialitzar el conjunt de caràcters que utilitzarem al gràfic. Utilitzant l’espai, //una copia extra del caràcter d’un bar i el caràcter 255 (un quadre negre ple) obtenim // 10 caràcters de la matriu // La variable c tindrà valors de 0 a 9, ja que els valors estan en el rang de 0 a 2000, // i 2000/201 és 9 amb nombre enter. char c = bar_graph_characters[sensors[i]/201]; print_character(c); // Display the bar graph characters. } // Display an indicator of whether IR is on or off if(button_is_pressed(BUTTON_C)) print("IR-"); else print(" C"); delay_ms(100); } Funció: prova de motors m1 i m2 amb ajust de la velocitat. int m1_speed = 0; int m2_speed = 0; voidmotor_test() { static char m1_back = 0, m2_back = 0; char m1_char, m2_char; if(button_is_pressed(BUTTON_A)) { if(m1_speed == 0)
36
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
{ delay_ms(200); // Si es prem el botó ràpidament quan el motor esta apagat, canviar de direcció. if(!button_is_pressed(BUTTON_A)) m1_back = !m1_back; } m1_speed += 10; } else m1_speed -= 20; if(button_is_pressed(BUTTON_C)) { if(m2_speed == 0) { delay_ms(200); // Si es prem el botó ràpidament quan el motor esta apagat, canviar de direcció. if(!button_is_pressed(BUTTON_C)) m2_back = !m2_back; } m2_speed += 10; } else m2_speed -= 20; if(m1_speed < 0) m1_speed = 0; if(m1_speed > 255) m1_speed = 255; if(m2_speed < 0) m2_speed = 0; if(m2_speed > 255) m2_speed = 255;
37
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// 255/26 = 9, així que això dona valors en el rang de 0 a 9. m1_char = bar_graph_characters[m1_speed / 26]; m2_char = bar_graph_characters[m2_speed / 26]; print_character(m1_char); print_character(m1_back ? 'a' : 'A'); print_character(m1_char); lcd_goto_xy(5,0); print_character(m2_char); print_character(m2_back ? 'c' : 'C'); print_character(m2_char); set_motors(m1_speed * (m1_back ? -1 : 1), m2_speed * (m2_back ? -1 : 1)); delay_ms(50); } Definició d’una melodia de musica. const char fugue[] PROGMEM = "! T120O5L16agafaea dac+adaeafa<aa<bac#adac#adaea f" "O6dcd<b-d<ad<g d<f+d<gd<ad<b- d<dd<ed<f+d<g d<f+d<gd<ad" "L8MS<b-d<b-d MLe-<ge-<g MSc<ac<a MLd<fd<f O5MSb-gb-g" "ML>c#e>c#e MS afaf ML gc#gc# MS fdfd ML e<b-e<b-" "O6L16ragafaea dac#adaea fa<aa<bac#adac#adaeafaeadaca" "<b-acadg<b-g egdgcg<b-g <ag<b-gcf<afdfcf<b-f<af" "<gf<af<b-e<ge c#e<b-e<ae<ge <fe<ge<ad<fd" "O5e>ee>ef>df>d b->c#b->c#a>df>d e>ee>ef>df>d" "e>d>c#>db>d>c#b>c#agaegfe fO6dc#dfdc#<b c#4"; const char fugue_title[] PROGMEM = "
\7 Fugue in D Minor - by J.S. Bach \7
";
Funció: treure una melodia per l’altaveu. voidmusic_test() { static char fugue_title_pos = 0; static long last_shift = 0; charc,i; if(get_ms() - last_shift> 250) { for(i=0;i<8;i++) { c = pgm_read_byte(fugue_title + fugue_title_pos + i); print_character(c); }
38
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
last_shift = get_ms(); fugue_title_pos ++; if(fugue_title_pos + 8 >= sizeof(fugue_title)) fugue_title_pos = 0; } if(!is_playing()) { play_from_program_space(fugue); } delay_ms(100); } Funció: treure per pantalla el valor predeterminat (està a la part inferior del robot). voidpot_test() { long start = get_ms(); charelapsed_ms; int value; set_analog_mode(MODE_10_BIT); print_long(read_trimpot()); print(" "); // to clear the display while((elapsed_ms = get_ms() - start) < 100) { value = read_trimpot(); play_frequency(value, 200, 15); if(value <elapsed_ms*10) { red_led(0); green_led(1); } else { red_led(1); green_led(0); } } }
39
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funciรณ: temporitzador. void time_test() { static long elapsed_time = 0; static long last_read = 0; static long is_ticking = 0; static char a_is_pressed = 0; static char c_is_pressed = 0; static char last_seconds = 0; long current_time = get_ms(); if(is_ticking) elapsed_time += current_time - last_read; last_read = current_time; if(button_is_pressed(BUTTON_A) && !a_is_pressed) { // reajustar a_is_pressed = 1; is_ticking = 0; elapsed_time = 0; if(!is_playing()) // only play once play_from_program_space(beep_button_a); } // Trobar el final de la pulsaciรณ del botรณ sense parar. if(!button_is_pressed(BUTTON_A)) a_is_pressed = 0; if(button_is_pressed(BUTTON_C) && !c_is_pressed) { // start/stop c_is_pressed = 1; is_ticking = !is_ticking; play_from_program_space(beep_button_c); } // Trobar el final de la pulsaciรณ del botรณ sense parar. if(!button_is_pressed(BUTTON_C)) c_is_pressed = 0;
40
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
print_long((elapsed_time/1000/60/10)%10); // tens of minutes print_long((elapsed_time/1000/60)%10); // minutes print_character(':'); print_long((elapsed_time/1000)%60/10); // tens of seconds char seconds = ((elapsed_time/1000)%60)%10; print_long(seconds); // seconds print_character('.'); print_long((elapsed_time/100)%10); // tenths of seconds print_long((elapsed_time/10)%10); // hundredths of seconds // xiulet cada segon if(seconds != last_seconds && elapsed_time != 0 && !is_playing()) play_from_program_space(timer_tick); last_seconds = seconds; } Funció: mostrar els valors de les barres. //*************************************************************************** ********* // Aquesta funció mostra les lectures del sensor utilitzant un gràfic de barres. void display_readings(const unsigned int *calibrated_values) { unsigned char i; for(i=0;i<5;i++) { // Inicialitzar la matriu de caràcters que utilitzarem per al //gràfic. Utilitzant l’espai, una còpia addicional de la barra // de caràcter ide 255 caràcters (un quadre negre ple), s’obtenen 10 // caràcters a la matriu. const char display_characters[10] = {' ',0,0,1,2,3,4,5,6,255}; // La variable c tindrà valors de 0 a 9, ja que // els valors calibrats estan en el rang de 0 a 1000, i // 1000/101 és 9 enter. char c = display_characters[calibrated_values[i]/101]; // Display the bar graph character. print_character(c); } }
41
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funció: robot en mode seguidor. void seguidor() { // Aquesta es la funció principal on el codi s’inicia. Tots els programes de C // ha de tenir una funció main() definida en algun lloc. // configurar el 3pi unsigned int counter; // used as a simple timer unsigned int sensors[5]; // an array to hold sensor values // Això ha de ser anomenat al començament del codi 3pi, per establir els // sensors. Nosaltres fem server un valor de 2000 per al temps d’espera, que // correspon a 2000*0.4 us = 0.8 ms en el nostre processador de 20 MHz. pololu_3pi_init(2000); load_custom_characters(); // load the custom characters // Reproduir música de benvinguda I mostrar un missatge print_from_program_space(welcome_line1); lcd_goto_xy(0,1); print_from_program_space(welcome_line2); play_from_program_space(welcome); delay_ms(1000); clear(); print_from_program_space(dema_name_seguidor_line1); lcd_goto_xy(0,1); print_from_program_space(dema_name_seguidor_line2); delay_ms(1000); // Visualització de la tensió de la bateria i esperar que premi el botó while(!button_is_pressed(BUTTON_A)) { int bat = read_battery_millivolts(); clear(); print_long(bat); print("mV"); lcd_goto_xy(0,1); print("Pulsa A"); delay_ms(100); }
42
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Esperar sempre que el botó sigui publicat per tal que no el 3pi // comenci a moure’s fins que la vostra mà estigui lluny d’ell. wait_for_button_release(BUTTON_A); delay_ms(1000); // Auto-calibració: girar a l’esquerra I a la dreta mentre es calibren els // sensors. for(counter=0;counter<80;counter++) { if(counter < 20 || counter >= 60) set_motors(40,-40); else set_motors(-40,40); // Aquesta funció registra una sèrie de lectures del sensors I manté // els valors de seguiment mínim i màxim trobat. // IR_EMITTERS_ON vol dir que els LEDs IR // s’activin Durant la lectura, que sol ser el que tu vols. calibrate_line_sensors(IR_EMITTERS_ON); // Des de el nostre comptador funciona a 80 el retard total és de // 80*20 = 1600 ms. delay_ms(20); } set_motors(0,0); // Mostra els valors de calibratge com un gràfic de barres. while(!button_is_pressed(BUTTON_A)) { // Llegir els valors dels sensors i obtenir el mesurament de la posició. unsigned int position = read_line(sensors,IR_EMITTERS_ON); // Mostra el mesurament de la posició, que serà de 0 // (quan el sensor de l'esquerra és sobre la línia) i 4000 (quan // el sensor de la dreta està sobre la línia) al 3pi, al llarg de // un gràfic de barres de les lectures del sensor. Això li permet // assegurar-se que el robot està llest per anar. clear(); print_long(position); lcd_goto_xy(0,1); display_readings(sensors); delay_ms(100); }
43
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
wait_for_button_release(BUTTON_A); clear(); print("Go!"); // Reproducció de música i esperar que acabi abans de començar a conduir. play_from_program_space(go); while(is_playing()); // Aquest és el "bucle principal" - s'executarà sempre. while(1) { // Obtenir la posició de la línia. Tingueu en compte que s'ha de proporcionar // als "sensors" el read_line () aquí, tot i que // No estan interessats en les lectures del sensor individual. unsigned int position = read_line(sensors,IR_EMITTERS_ON); if(position>500 && position<2000) { // Estem molt a la dreta de la línia: girar a l'esquerra. // Establir el motor dret a 100 i el motor esquerre a zero, // per fer un gir brusc a l'esquerra. Tingueu en compte que el màxim // valor de qualsevol velocitat del motor és de 255, de manera que la conducció és // gairebé el 40% del màxim. set_motors(0,75); // Només per diversió, indiquen la direcció que s'estan convertint en els LED. left_led(1); right_led(0); } else if(position>2000 && position<3000) { // Estem una mica a prop de ser centrat en la línia: seguir recte. set_motors(75,75); left_led(1); right_led(1); }
44
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
else if (position>3000 && position<4000) { // Estem molt a l'esquerra de la línia: giri a la dreta. set_motors(75,0); left_led(0); right_led(1); } //Si els 5 sensors del davant marquen línia negra s'atura o fora zona blanca: seguretat. if (sensors[1]>600 && sensors[2]>600 && sensors[3]>600 && sensors[4]>600){ set_motors(0,0);} } } Funció: robot en mode seguidor però amb valors més alts de potència dels motors. void turbo_seguidor() { // Aquesta és la funció principal, on el codi s'inicia. Tots els programes de C // han de tenir una funció main() definit en algun lloc. // configurar el 3pi unsigned int counter; // used as a simple timer unsigned int sensors[5]; // an array to hold sensor values // Això ha de ser cridat al començament del codi 3pi, per establir els // sensors. Nosaltres fem servir un valor de 2000 per al temps d'espera, que // correspon a 2000 * 0,4 = 0,8 ms en el nostre processador de 20 MHz. pololu_3pi_init(2000); load_custom_characters(); // load the custom characters //Reproduir música de benvinguda i mostrar un missatge print_from_program_space(welcome_line1); lcd_goto_xy(0,1); print_from_program_space(welcome_line2); play_from_program_space(welcome); delay_ms(1000); clear(); print_from_program_space(dema_name_seguidor_line1); lcd_goto_xy(0,1); print_from_program_space(dema_name_seguidor_line2); delay_ms(1000);
45
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Visualització de la tensió de la bateria i esperar que es premi el botó while(!button_is_pressed(BUTTON_C)) { int bat = read_battery_millivolts(); clear(); print_long(bat); print("mV"); lcd_goto_xy(0,1); print("Pulsa C"); delay_ms(100); } // Esperar sempre que el botó es publiqui per tal que el 3pi no // comenci a moure's fins que la seva mà està lluny d'ella. wait_for_button_release(BUTTON_C); delay_ms(1000); // Auto-calibratge: giri a la dreta i l'esquerra, mentre es fa el calibratge dels // sensors. for(counter=0;counter<80;counter++) { if(counter < 20 || counter >= 60) set_motors(40,-40); else set_motors(-40,40); // Aquesta funció registra una sèrie de lectures dels sensors i manté // el registre dels valors mínim i màxim trobat. // IR_EMITTERS_ON això significa que els LEDs IR // s'activen durant la lectura, que sol ser el que nosaltres volem. calibrate_line_sensors(IR_EMITTERS_ON); // El nostre comptador funciona a 80, el retard total és // 80*20 = 1600 ms. delay_ms(20); } set_motors(0,0); // Mostra els valors de calibratge com un gràfic de barres. while(!button_is_pressed(BUTTON_C)) { // Llegir els valors del sensor i obtenir el mesurament de la posició. unsigned int posicion = read_line(sensors,IR_EMITTERS_ON);
46
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa // Mostra el mesurament de la posició, que serà de 0 // (quan el sensor de l'esquerra és sobre la línia) i 4000 (quan // el sensor de la dreta està sobre la línia) all 3pi, al llarg de // d'un gràfic de barres de les lectures del sensor. Això li permet // assegurar-se que el robot està llest per anar. clear(); print_long(posicion); lcd_goto_xy(0,1); display_readings(sensors); delay_ms(100);
} wait_for_button_release(BUTTON_C); clear(); print("Go!"); // Reproduir música i esperar que acabi abans de començar a conduir. play_from_program_space(go); while(is_playing()); // Aquest és el "bucle principal" - s'executarà sempre. while(1) { // Obtenir la posició de línia. Tingueu en compte que s'ha de proporcionar // als "sensors" l'argument read_line () aquí, tot i que // no estan interessats en les lectures del sensor individual. unsigned int posicion = read_line(sensors,IR_EMITTERS_ON); // Depenent de la posició de la línia varia la velocitat del motor del robot if (posicion<500){ set_motors(-150,150);} else if (posicion>500 && posicion<1000){ set_motors(-40,150);} else if (posicion>1000 && posicion<1500){ set_motors(75,150);} else if (posicion>1500 && posicion<1800){ set_motors(30,150);} else if (posicion>1800 && posicion<2200){ set_motors(150,150);} else if (posicion>2200 && posicion<2500){ set_motors(150,30);} else if (posicion>2500 && posicion<3000){ set_motors(150,75);} else if (posicion>3000 && posicion<3500){ set_motors(150,-40);}
47
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
elseif (posicion>3500){ // Si la línia es troba entre PC3+ i PC4 set_motors(150,-150);} //Si els 5 sensors del davant marquen linia negra s'atura o fora zona blanca: seguretat. if (sensors[1]>600 && sensors[2]>600 && sensors[3]>600 && sensors[4]>600){ set_motors(0,0);} } }
Funció: robot en mode seguidor però amb ajust de la potència dels motors amb un control adaptatiu PID. voidseguidor_PID() { unsigned int counter; unsigned int sensors[5]; // an array to hold sensor values unsigned int last_proportional=0; long integral=0;
delay_ms(500); for(counter=0;counter<80;counter++) { if(counter < 20 || counter >= 60) set_motors(40,-40); else set_motors(-40,40); // Aquesta funció registra una sèrie de lectures dels sensors i manté // el registre dels valors mínim i màxim trobat. // l'argument IR_EMITTERS_ON significa que els LEDs IR // s'activen durant la lectura, que sol ser el que nosaltres volem. calibrate_line_sensors(IR_EMITTERS_ON); // Desde el nostre contador funciona a 80, el retard total és // 80*20 = 1600 ms. delay_ms(20); } set_motors(0,0); clear(); print_from_program_space(menu_line1_PID); lcd_goto_xy(0,1); print_from_program_space(menu_line2_PID);
48
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Aquest és el "bucle principal" - s'executarà sempre. while(1) { // Obtenir la posició de la línia. Tingueu en compte que s'ha de proporcionar // als "sensors" l'argument read_line () aquí, tot i que // no estan interessats en les lectures del sensor individual. unsigned int position = read_line(sensors,IR_EMITTERS_ON); // El termini "proporcional" ha de ser 0 quan estem en la línia. intproportional = ((int)position) - 2000; // Calcular la derivada (canviar) i integral (suma) de la // posició. int derivative = proportional - last_proportional; integral += proportional; // Recordar la ultima posició. last_proportional = proportional; // Calcular la diferència entre els dos nivells de potència del motor, // M1 - m2. Si això és un nombre positiu, el robot al seu torn // gira a la dreta. Si es tracta d'un nombre negatiu, el robot // gira a l'esquerra, i determina la magnitud del nombre // i la nitidesa de la corba. intpower_difference = proportional/20 + integral/10000 + derivative*3/2; // Calcular els valors del motor real. Mai conjunt o bé de motor a un valor negatiu. const int max = 100; // Velocidadmáxima if(power_difference> max) power_difference = max; if(power_difference< -max) power_difference = -max; if(power_difference< 0) set_motors(max+power_difference, max); else set_motors(max, max-power_difference); } }
49
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funció: robot en mode tancament. void encierro() { // Aquesta és la funció principal, on comença el codi. Tots els programes C // tenen una funcio main() definida. // configurar el 3pi unsigned int counter; // un simple cronometre unsignedintsensors[5]; // una serie de valors del sensor // Això ha de ser anomenat al principi del codi 3pi per ajustar // els sensors. Usem el valor 2000 per quan el temps s'acaba, amb el seu // corresponent de 2000*0.4 us = 0.8 ms en el nostreprocessador de 20 mHz. pololu_3pi_init(2000); load_custom_characters(); // load the custom characters // Encén musica i mostra el missatge print_from_program_space(welcome_line1); lcd_goto_xy(0,1); print_from_program_space(welcome_line2); play_from_program_space(welcome); delay_ms(1000); clear(); print_from_program_space(dema_name_encierro_line1); lcd_goto_xy(0,1); print_from_program_space(dema_name_encierro_line2); delay_ms(1000); // Mostra el valor de la bateria i espera que premin el botó. while(!button_is_pressed(BUTTON_A)) { int bat = read_battery_millivolts(); clear(); print_long(bat); print("mV"); lcd_goto_xy(0,1); print("Pulsa A"); delay_ms(100); } // Sempre esperem al botó per encendre el 3pi per que // no s'encengui quan la teva ma no esta a prop. wait_for_button_release(BUTTON_A); delay_ms(1000);
50
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Auto-calibratge: un gir a la dreta i un altre a l'esquerra mentre s'ajusten // els sensors. for(counter=0;counter<80;counter++) { if(counter < 20 || counter >= 60) set_motors(40,-40); else set_motors(-40,40); // Aquesta funció grava un set de lectures del sensor i mantenia // els valors màxims i mínims trobats. El // IR_EMITTERS_ON significa que si el IR LED es troba // girat durant el calibratge, que es usualment el que // volem. calibrate_line_sensors(IR_EMITTERS_ON); // El nostre comptador comença a 80, per tant, el temps total serà // 80*20 = 1600 ms. delay_ms(20); } set_motors(0,0); // Mostra el valor del calibratge en un gràfic. while(!button_is_pressed(BUTTON_A)) { // Llegeix el valor dels sensors i calcula la seva posició.. unsigned int position = read_line(sensors,IR_EMITTERS_ON); // Mostra la posició, que pot ser de 0 // (quan el sensor més a l'esquerra llegeix línia) a 4000 (quan // el sensor més a la dreta llegeix línia) en el 3pi, al llarg // amb el gràfic del valors mostrats pels sensors. Això et permet // estar segur de si el robot esta preparat per començar. clear(); print_long(position); lcd_goto_xy(0,1); display_readings(sensors); delay_ms(100); } wait_for_button_release(BUTTON_A); clear(); print("Tancat!"); // Encén musica i espera a que acabi per iniciar el robot. play_from_program_space(go); while(is_playing());
51
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Aquest es el programa principal, funcionarà sempre. while(1) { // Aconsegueix la posició de la línia. Nota quan ha de proporcionar // el valor dels sensors al read_line() aquí, sempre pensa que // no estem interessats en una lectura de sensors individual. unsigned int position = read_line(sensors,IR_EMITTERS_ON); set_motors(100,100); //delay_ms(50); if(position>500 && position<2000) { set_motors(0,100); left_led(0); right_led(1); delay_ms(50); } else if(position>2000 && position<3000) { set_motors(-50,-50); left_led(1); right_led(0); delay_ms(100); set_motors(50,-50); delay_ms(100); } else if (position>3000 && position<4000) { set_motors(100,0); left_led(1); right_led(0); delay_ms(50); } } } Funció: robot en mode laberint. // Mostra el "path" (camí) al LCD, utilitzantdues files si es necessari. // Mostra la ruta actual a la pantalla LCD, amb dues línies en cas necessari. void display_path() { // Establir el caràcter últim de la ruta a un 0, de manera que la funció print () // es pot trobar al final de la cadena. Així és com la cadena // s'acaba, normalment, al C. path[path_length] = 0; clear(); print(path); 52
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
if(path_length > 8) { lcd_goto_xy(0,1); print(path+8); } } // Aquesta funció decideix quin camí prendre durant la fase d'aprenentatge de // laberint. Utilitza el found_left variables, found_straight, i // found_right, que indiquen si hi ha una sortida en cadascuna de les // tres adreces, l'aplicació de la "mà esquerra a la paret" estratègia. char select_turn(unsigned char found_left, unsigned char found_straight, unsigned char found_right) { // Prendre una decisió sobre com activar. El següent codi // implementa una esquerra-a la paret d'estratègia, on sempre // al seu torn el més a l'esquerra com sigui possible. if(found_left) return 'L'; else if(found_straight) return 'S'; else if(found_right) return 'R'; else return 'B'; } // Mostra el "path" (camí) al LCD, utilitzant dues files si es necessari. void simplify_path() { // només simplifiquen el camí si la segona volta-al-passat va ser una 'B' if(path_length < 3 || path[path_length-2] != 'B') return; int total_angle = 0; int i; for(i=1;i<=3;i++) { switch(path[path_length-i]) { case 'R': total_angle += 90; break; case 'L': total_angle += 270; break;
53
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa case 'B': total_angle += 180; break; }
} // Obtenir l'angle com un nombre entre 0 i 360 graus. total_angle = total_angle % 360; // Torneu a col·locar tots els torns amb un sol. switch(total_angle) { case 0: path[path_length - 3] = 'S'; break; case 90: path[path_length - 3] = 'R'; break; case 180: path[path_length - 3] = 'B'; break; case 270: path[path_length - 3] = 'L'; break; } // El camí està ara a dos passos més curts. path_length -= 2; } void maze() { // Bucle fins que tinguem resolt el laberint. while(1) { // Primer cos del bucle principal follow_segment(); // Seguiu recte una mica. Això ens ajuda en cas de que va entrar a // la intersecció en angle. // Tingueu en compte que s'estan desaccelerant - això evita que el robot // s'inclini massa cap endavant. set_motors(50,50); delay_ms(50);
54
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
// Aquestes variables registren si el robot ha vist una línia a la // l'esquerra, cap endavant, i la dreta, envoltat per examinar l'actual // intersecció. unsigned char found_left=0; unsigned char found_straight=0; unsigned char found_right=0; // Ara llegeix els sensors i comprova el tipus d'intersecció. unsigned int sensors[5]; read_line(sensors,IR_EMITTERS_ON); // Comproveu les sortides esquerra i dreta. if(sensors[0] > 100) found_left = 1; if(sensors[4] > 100) found_right = 1; // Seguiu recte una mica més - això és suficient per alinear les nostres // rodes en la intersecció. set_motors(40,40); delay_ms(200); // Comproveu si hi ha una sortida recte. read_line(sensors,IR_EMITTERS_ON); if(sensors[1] > 200 || sensors[2] > 200 || sensors[3] > 200) found_straight = 1; // Comproveu el punt final. // Si els tres sensors de mitjana estan en color negre fosc, tenim // resolt el laberint. if(sensors[1] > 600 && sensors[2] > 600 && sensors[3] > 600) break; // Intersecció d'identificació s'ha completat. // Si el laberint ha estat resolt, podem seguir els existents // camins. En cas contrari, hem d'aprendre la solució. unsigned char dir = select_turn(found_left, found_straight, found_right); // Fer girar l'indicat pel camí. turn(dir); // la variable PATH. path[path_length] = dir; path_length ++; // Has de verificar per assegurar-te que path_length no // supera els límits de la matriu. Anem a ignorar que en aquest // exemple. 55
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa // Simplificar el camí aprés. simplify_path(); // Mostra la ruta a la pantalla LCD. display_path();
} // Resolt el laberint! // Ara entrar en un bucle infinit - que pot tornar a executar el laberint les // vegades que vulguem. while(1) { // Xiulet per demostrar que hem acabat el laberint set_motors(0,0); play(">>a32"); // Espereu que l’usuari prengui un botó, mentre es mostra // la solució. while(!button_is_pressed(BUTTON_B)) { if(get_ms() % 2000 < 1000) { clear(); print("Solved!"); lcd_goto_xy(0,1); print("Press B"); } else display_path(); delay_ms(30); } while(button_is_pressed(BUTTON_B)); delay_ms(1000); // Torneu a executar el laberint No es necessari identificar les // interseccions, de manera que aquest circuit és molt més senzill. int i; for(i=0;i<path_length;i++) { // Segon cos del bucle principal follow_segment();
56
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa // Segueix recte, mentre la desacceleració. set_motors(50,50); delay_ms(50); set_motors(40,40); delay_ms(200); // Fer un gir d’acord amb la instrucció emmagatzemada a // path[i]. turn(path[i]); } // Seguiu l’últim segment fins al final. follow_segment(); // Ara deuríem estar al final. Refés el cicle.
} }
Funció: escriure les dues línies a la pantalla LCD. //*************************************************************************** ******************* void print_two_lines_delay_1s(const char *line1, const char *line2) { // Engega musica I espera l missatge clear(); print_from_program_space(line1); lcd_goto_xy(0,1); print_from_program_space(line2); delay_ms(1000); }
57
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funció: emetre un so quan polsem un dels tres botons. // Espera que un botó, toca el so adequat, i torna el botó o botons que van ser pressionats. charwait_for_button_and_beep() { char button = wait_for_button_press(ALL_BUTTONS); if(button & BUTTON_A) play_from_program_space(beep_button_a); else if(button & BUTTON_B) play_from_program_space(beep_button_b); else play_from_program_space(beep_button_c); wait_for_button_release(button); returnbutton; } Funció: inicialització del robot i mostra les dues línies en pantalla. // Inicialitza el 3pi, mostra un missatge de benvinguda, calibra, i // reprodueix la música inicial. void initialize() { // Això ha de ser cridat al començament del codi 3pi, per configurar els sensors. Nosaltres fem servir un valor // de 2000 per al temps d'espera, el que correspon a 2000 * 0,4 = 0,8 ms en el nostre processador de 20 MHz. pololu_3pi_init(2000); load_custom_characters(); // load the custom characters play_from_program_space(welcome); print_two_lines_delay_1s(welcome_line1,welcome_line2); print_two_lines_delay_1s(demo_name_line1,demo_name_line2); print_two_lines_delay_1s(instructions_line1,instructions_line2); clear(); print_from_program_space(instructions_line3); lcd_goto_xy(0,1); print_from_program_space(instructions_line4); while(!(wait_for_button_and_beep() & BUTTON_B)); play_from_program_space(thank_you_music); print_two_lines_delay_1s(thank_you_line1,thank_you_line2); } 58
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
Funció: selecció dels diferents menús. voidmenu_select() { static int menu_index = 0; print_two_lines_delay_1s(main_menu_intro_line1,main_menu_intro_line2); while(1) { clear(); lcd_goto_xy(0,1); print_from_program_space(menu_line2); lcd_goto_xy(0,0); print_from_program_space(main_menu_options[menu_index]); lcd_show_cursor(CURSOR_BLINKING); // El cursor canviarà mentre final del nom de l'opció // esperar que tots els botons per ser alliberat, després d'una premsa. while(button_is_pressed(ALL_BUTTONS)); char button = wait_for_button_press(ALL_BUTTONS); if(button & BUTTON_A) { play_from_program_space(beep_button_a); menu_index --; } else if(button & BUTTON_B) { lcd_hide_cursor(); clear(); play_from_program_space(beep_button_b); wait_for_button_release(button); while(!button_is_pressed(BUTTON_B)) { lcd_goto_xy(0,1); print_from_program_space(back_line2); lcd_goto_xy(0,0); main_menu_functions[menu_index](); }
59
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
set_motors(0,0); stop_playing(); m1_speed = 0; m2_speed = 0; red_led(0); green_led(0); play_from_program_space(beep_button_b); return; } else if(button & BUTTON_C) { play_from_program_space(beep_button_c); menu_index ++; } if(menu_index< 0) menu_index = main_menu_length-1; if(menu_index>= main_menu_length) menu_index = 0; } }
Programa principal. Inicialització del robot amb la funció initialize();. Fa un bucle infinit per que sempre s’executi la funció de la selecció de menús: menú_select();. // Aquesta és la funció principal, on el codi s'inicia. Tots els programes C han de tenir una funció main () definida en algun lloc. int main() { // configurar el 3pi initialize(); // Aquest és el "bucle principal" - s'executarà sempre. while(1) { menu_select(); } }
60
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
7 Conclusions El pololu 3pi bé a ser un robot de petites dimensions i autònom, que pot realitzar varies funcions, en el nostre cas fa la funció de seguidor de línia, tancament i laberint. Aquest funciona gracies a 4 piles AA de 1.5V connectades en sèrie, per augmentar la tensió de les piles. Aquesta energia que rep la gestiona de dos maneres diferents, una de ella es amb el regulador lineal que el que fa es disminuir la quantitat de voltatge que passa i l’altre manera es la del regulador switching, que al contrari de la lineal, el que fa es estabilitzar el voltatge i pot convertir voltatges baixos en alts. El regulador switching s’utilitza per connectar els motors i els LEDs sensors IR en línia, i el lineal per connectar el microcontrolador i senyals digitals. Una gran part de l’energia anomenada va dirigida als motors. El pololu 3pi utilitza dos motors de corrent continua de escombretes. Els motors funcionen amb la senya PWM, que el que fa es en un temps molt curt, és a dir, mil·lèsimes de segon variar el voltatge del mínim al màxim i això serveix perquè els motors funcionin amb la major suavitat possible. El pololu té dos motors independents que giren amb un mecanisme de conducció diferencial, aquest mecanisme consisteix en fer rodar els motors en diferents velocitats, i ens permet que giri sobre si mateix i inclús a la velocitat i l’angle que li programem. Tot el que fa el robot pololu 3pi esta controlat pel microcontrolador, què és el atmega 328p. Aquest funciona amb una memòria Flash de 32KB, 2KB de memòria RAM i 1 KB de memòria EEPROM de memòria i té 32 pins d’entrada i sortida, també cal dir que té una velocitat de 20MHz. Cada pin fa una funció dins del robot. El que permet al robot guiar-se i poder seguir la línia o fer altres funcions són els sensors, què en aquest cas hi ha 5 i són sensors de reflexió, aquests funcionen amb la emissió de llum i la recepció de llum. Quan parlem, parlem també de l’estabilitat del robot, per això, porta un LED que en aquest cas no fa la funció d’un LED normal, si no que fa la funció de mantenir equilibrat al robot. A part d’aquest LED, porta 3 rodes, dues als costats que són de goma en silicona i la tercera roda està situada a la part inferior de la placa i permet girar al robot i també estabilitzar-lo, i aquesta s’anomena roda boja. Al robot hi ha 4 LEDs, dos blaus que fan la funció de indicar que el robot esta encès, un vermell i un verd que són amb els que podem jugar en al funció de LEDs del nostre robot. Per veure el menú i les funcions del robot, tenim un pantalla LCD en paral·lel de 8x2 caràcters. L’altaveu que porta el robot, serveix per reproduir música o sons que li apliquem, aquest té un 61
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
voltatge de 1.5 V, una resistència de 6 ohms i funciona a una velocitat de 320Hz. El que ens permet accedir als menús, encendre o apagar el robot o moure’ns pel menú són els botons, que en aquest robot en tenim 5. Els botons A, B i C estan connectats a la pantalla LCD i ens permeten indicar les funcions del menú, a més a més, tenim el de reset i el de power, el primer, ens permet tornar al inici del menú, i el segon, ens permet encendre i apagar el pololu. Per poder compilar els programes al robot, necessitem el connector de programació, que consta d’un cable USB connectat des de l’ordinador fins la targeta d’expansió i es connecta a la targeta gracies al connector ISP. Si volguéssim ampliar el nostre robot o canviar-li la estètica necessitarem
un connector
d’expansió, que són una sèrie de pins que ens permeten connectar un altre placa a sobre de la ja existent, hi ha varis tipus de placa. El robot té 3 jumpers, que aquets serveixen per connectar dos terminals de manera temporal, sense fer cap operació. El llenguatge que utilitza el nostre robot és el llenguatge C. Aquest llenguatge inicialment, esta orientat expressament per sistemes operatius, però va aconseguir un grau tan alt de popularitat al ser tan fàcil d’utilitzar, que ha estat utilitzat per a contextos molt diferent pel qual va ser creat. Una de les avantatges que té es que té unes estructures d’un llenguatge complex, però tal i com esta fet per fer-lo funcionar es senzill i sense saber-ne gaire pots utilitzar-lo sense cap problema. Totes les dades que no siguin bàsiques han de ser manipulades pel programador, i les bàsiques no poden ser manipulades, així el codi basic serà molt eficient, ja que el fa la computadora. I algun defecte que té es que si el compares amb un llenguatge de dades dinàmic, varia molt la velocitat, es bastant més baixa la del C, i el manteniment es difícil també. La nostre opinió sobre el treball que hem fet, és que ha sigut un treball al que no estem acostumats, ja què combina part teòrica amb part practica, almenys el nostre, i per la durada que ha tingut. Però creiem que és una gran experiència perquè el treball de final de carrera és semblant a aquest però a un altre escala, i això ens ajudarà a poder organitzar-nos millor, fer primer una cosa o una altra, és a dir, aprendre dels petits errors de principiant que hem tingut en aquest treball, però que hem sabut arreglar amb esforç i sacrifici. Una altra cosa que hem de dir que el nostre tutor ens ha ajudat molt i ens a motivat que sempre és important, ja què en algunes coses de programació o teòriques del treball no sabíem com explicarles o no les enteníem o no les sabíem fer. Però ens portem una molt bona experiència que la aplicarem a treballs posteriors. 62
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
8 Fonts d’informació Pololu 3pi i característiques dels seus elements. http://www.pololu.com/catalog/product/975 Elements del robot i informació de microcontrolador. Guia d’usuari pololu: http://www.pololu.com/file/0J137/Pololu3piRobotGuiaUsuario.pdf Elements del robot. http://www.pololu.com/docs/0J21 Informació general del robot. http://www.bricogeek.com/shop/106-seguidor-de-lineas-pololu-3pi.html Elements del robot i pins. http://www.pololu.com/docs/0J17/2.c Microcontrolador. http://www.atmel.com/dyn/products/product_card.asp?part_id=4198 LEDs. http://es.wikipedia.org/wiki/Led Sensors. http://robots-argentina.com.ar/Sensores_reflectivos.htm Característiques del llenguatge C. http://ca.wikipedia.org/wiki/Llenguatge_C Imatges del pololu. www.google.es/imatges Vocabulari del llenguatge C. Pràctiques 2i 3 de la UPC. Programació del robot. AVR Studio 4.
63
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
9 Agraïments Principalment volíem agrair al nostre tutor del treball de recerca, el Fernando Hernandez, la seva implicació en el nostre treball i tot el que ens ha ajudat, a més a més el haver estat disponible a cada moment per qualsevol dubte i la seva disposició per ajudar-nos en tot el que calgués. Nosaltres pensem que sense ell no ens hagués sigut possible arribar al dia d’avui entenent tot el que hem fet i amb el treball acabat. També agrair l’oportunitat que ens va donar la UPC i especialment al Néstor Berbel, per explicarnos el funcionament del llenguatge C i per haver resolt els nostres dubtes durant els dies que va durar el curs de la UPC.
64
Pololu 3Pi
Coral Santacruz i Jordi Hinojosa
65