abel tarragó aguilar muntatge d’un sistema fpv sobre un...

108
Abel Tarragó Aguilar MUNTATGE D’UN SISTEMA FPV SOBRE UN AVIÓ TELEDIRIGIT AMB HEADTRACKER TREBALL DE FI DE GRAU Dirigit pel Dr. Albert Oller Grau d’enginyeria electrònica industrial i automàtica Tarragona 2018

Upload: others

Post on 27-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Abel Tarragó Aguilar

MUNTATGE D’UN SISTEMA FPV SOBRE UN AVIÓ TELEDIRIGIT AMB HEADTRACKER

TREBALL DE FI DE GRAU

Dirigit pel Dr. Albert Oller

Grau d’enginyeria electrònica industrial i automàtica

Tarragona

2018

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

3

Índex Índex de figures ........................................................................................................................ 5

Índex de taules .......................................................................................................................... 7

1. Introducció ....................................................................................................................... 8

2. Objectius .......................................................................................................................... 9

3. Necessitats...................................................................................................................... 10

3.1 Funcionament de l’acceleròmetre .................................................................. 11

3.2 Tecnologia MEMS ........................................................................................ 14

3.3 Projectes actuals i camps d’aplicació ............................................................. 17

4. Especificacions dels components utilitzats ...................................................................... 19

4.1 Característiques de l’avió Opterra ................................................................. 20

4.1.1 Electrònica ............................................................................................. 21

4.1.2 Dimensions ............................................................................................ 21

4.1.3 Sistema Tx/Rx ....................................................................................... 21

4.2 Components First Person Vision FPV ........................................................... 22

4.2.1 Càmera .................................................................................................. 23

4.2.2 Transmissor de vídeo ............................................................................. 24

4.2.3 Receptors de vídeo ................................................................................. 25

4.2.4 Ulleres FPV ........................................................................................... 25

4.2.5 Pantalla en pantalla (OSD) ..................................................................... 26

4.2.6 Antenes.................................................................................................. 28

4.2.7 Servos digitals ....................................................................................... 33

4.3 Components headtracker ............................................................................... 35

4.3.1 MPU6050 .............................................................................................. 35

4.3.2 Arduino NANO ..................................................................................... 36

4.4 Resultat ......................................................................................................... 37

5. Simulació headtracker .................................................................................................... 38

5.1 Hardware ...................................................................................................... 38

5.2 Software ....................................................................................................... 39

5.2.1 Llibreries ............................................................................................... 39

5.2.2 Arduino ................................................................................................. 39

5.2.3 Processing ............................................................................................. 40

5.3 Resultat ......................................................................................................... 40

6. Headtracker .................................................................................................................... 43

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

4

6.1 Protocol de comunicació entre l’avió i Arduino ............................................. 43

6.1.1 PPM o modulació de posició de punts .................................................... 44

6.1.2 Característiques protocol ........................................................................ 46

6.2 Desenvolupament ......................................................................................... 48

6.2.1 Hardware ............................................................................................... 48

6.2.2 Software ................................................................................................ 49

6.3 Resultat ......................................................................................................... 52

7. Mètodes de verificació i obtenció de dades ..................................................................... 55

7.1 APP GPS tracker........................................................................................... 56

7.2 Resultats prova de vol ................................................................................... 56

8. Conclusions .................................................................................................................... 60

Referències ............................................................................................................................. 61

9. Annexes ......................................................................................................................... 62

9.1 Codi APP GPS tracker .................................................................................. 62

9.2 Codi simulació del headtracker ..................................................................... 63

9.2.1 Simulació Arduino ................................................................................. 64

9.2.2 Simulació Processing ............................................................................. 68

9.3 Codi del headtracker ..................................................................................... 71

9.3.1 GUI ....................................................................................................... 71

9.3.2 Arduino ................................................................................................. 93

9.4 Altres conceptes d’interès .................................................................... 106

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

5

Índex de figures Figura 1. Eixos headtracker. ................................................................................................................. 10

Figura 2. Diagrama disseny Headtracker .............................................................................................. 10

Figura 3. Centre de coordenades.......................................................................................................... 11

Figura 4. Acceleròmetre a gravetat 0. .................................................................................................. 11

Figura 5. Força eix X acceleròmetre. .................................................................................................... 12

Figura 6. Força eix Z- acceleròmetre..................................................................................................... 12

Figura 7. Força resultat. ....................................................................................................................... 13

Figura 8. Comparació mida d’un acceleròmetre MEMS ........................................................................ 14

Figura 9. Equació capacitància ............................................................................................................. 15

Figura 10. Sensor en repòs (dalt). Sensor sotmès a acceleració (baix). ................................................. 15

Figura 11. Curiosity. ............................................................................................................................. 17

Figura 12. Robot humanoide. ............................................................................................................... 17

Figura 13. Headtracker per a jocs. ........................................................................................................ 18

Figura 14. Avió teledirigit Opterra . ...................................................................................................... 19

Figura 15. Ala volant. ........................................................................................................................... 20

Figura 16. Sistema d'enlairament ......................................................................................................... 20

Figura 17. Emissora Tx ......................................................................................................................... 21

Figura 18. Exemple FPV i muntatge ulleres amb antena. ...................................................................... 22

Figura 19. Càmera FPV. ........................................................................................................................ 23

Figura 20. Emissor de vídeo. ................................................................................................................ 25

Figura 21. Ulleres FPV amb receptor de vídeo incorporat (Eachine ev800). .......................................... 26

Figura 22. Exemple sistema OSD. ......................................................................................................... 26

Figura 23. OSD-3. ................................................................................................................................. 27

Figura 24. Patró de radiació ideal. ....................................................................................................... 28

Figura 25. Patró de radiació ideal. ........................................................................................................ 29

Figura 26. Antena polarització lineal. ................................................................................................... 29

Figura 27. Patró de propagació lineal. .................................................................................................. 30

Figura 28. Patró propagació circular. .................................................................................................... 30

Figura 29. Antena polarització circular. ................................................................................................ 31

Figura 30. Propagació omni-direccional i direccional. .......................................................................... 31

Figura 31. Tipus d'antena. .................................................................................................................... 32

Figura 32. Tipus connectors. ................................................................................................................ 32

Figura 33. Servomotor digital. .............................................................................................................. 33

Figura 34. Sistema Pan/Tilt. ................................................................................................................. 34

Figura 35. MPU6050 ............................................................................................................................. 35

Figura 36. Arduino NANO ..................................................................................................................... 36

Figura 37. Diagrama de components .................................................................................................... 37

Figura 38. Simulació avió 3D ................................................................................................................ 38

Figura 39. Connexió Arduino en MPU6050. .......................................................................................... 38

Figura 40. Carpetes de les Llibreries ..................................................................................................... 39

Figura 41. Posició inicial simulació ....................................................................................................... 40

Figura 42. Gir avall simulació ............................................................................................................... 41

Figura 43. Gir amunt simulació ............................................................................................................ 41

Figura 44. Gir dreta simulació .............................................................................................................. 42

Figura 45. Gir esquerra simulació ......................................................................................................... 42

Figura 46. Connector jack 2.1mm PortTrainer ...................................................................................... 44

Figura 47. Exemple funcionament PPM................................................................................................ 44

Figura 48. Exemple protocol PPM ........................................................................................................ 45

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

6

Figura 49. Diferència entre PWM i PPM. .............................................................................................. 45

Figura 50. Període senyal PPM Tx ........................................................................................................ 46

Figura 51. Mínim temps de durada de canal ........................................................................................ 46

Figura 52. Màxim temps de durada de canal ........................................................................................ 47

Figura 53. Connexions entre Arduino, MPU6050 i Tx. .......................................................................... 48

Figura 54. Interfície gràfica .................................................................................................................. 50

Figura 55. Període senyal PPM headtracker ......................................................................................... 50

Figura 56. Màxim temps de durada de canal ........................................................................................ 51

Figura 57. Mínim temps de durada de canal ........................................................................................ 51

Figura 58. Moviment produït pels alerons ........................................................................................... 52

Figura 59. Direcció normal headtracker ............................................................................................... 52

Figura 60. Direcció amunt headtracker ................................................................................................ 53

Figura 61. Direcció avall headtracker ................................................................................................... 53

Figura 62. Direcció dreta headtracker .................................................................................................. 54

Figura 63. Direcció dreta headtracker .................................................................................................. 54

Figura 64. Logo App inventor. .............................................................................................................. 55

Figura 65. App Runtastic. ..................................................................................................................... 55

Figura 66. Pantalla inicial App GPS tracker ........................................................................................... 56

Figura 67. Fitxers de dades generats .................................................................................................... 56

Figura 68. Altitud registrada per la App GPS tracker ............................................................................ 57

Figura 69. Altitud GPS Tracker App ...................................................................................................... 57

Figura 70. Angle Pitch GPS Tracker App................................................................................................ 58

Figura 71. Recorregut registrada per la App GPS tracker ...................................................................... 58

Figura 72. Longitud GPS Tracker App ................................................................................................... 59

Figura 73. Angle Roll GPS Tracker App ................................................................................................. 59

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

7

Índex de taules Taula 1. Taula avantatges i inconvenients freqüències......................................................................... 24

Taula 2. Pinout entre Arduino i MPU6050 ............................................................................................ 49

Taula 3. Taula connexions entre Arduino i Tx ....................................................................................... 49

Taula 4. Comparació PPM entre emissora i headtracker ...................................................................... 51

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

8

1. Introducció

Avui en dia el concepte del FPV1 guanya cada cop més interès en els sectors de joguines radio control, videojocs, sanitari o militar. El fet de poder veure imatges en directe des d’on la vista humana no pot arribar obre un gran ventall de possibilitats. Concentrar el camp de visió amb unes ulleres virtuals permet veure imatges més còmodament per realitzar segons quines tasques. Per tant no és estrany que alguns sectors estiguin invertint en el desenvolupament i millores de sistemes FPV.

Un concepte que cal introduir en aquest primer capítol és el headtracking2. Aquest consisteix en moure un objecte en funció del moviment del cap. S’utilitza sensors per detectar el moviment en tres eixos i mecanismes per transformar o enviar aquest moviment a un altre lloc. Encara que ja existeixen sistemes similars capaços de detectar moviment d’una part del cos, el headtracking està en desenvolupament i encara queden possibles utilitats per descobrir.

En el món de l’aeromodelisme sovint es combinen el FPV i el headtracking. El pilot és capaç de veure imatges en directe provinents de l’aparell radiocontrol degut a que hi ha una càmera muntada sobre aquest. Les imatges capturades per la càmera s’envien via radiofreqüència a unes ulleres de visió, aquest sistema es coneix com FPV. A més la càmera es pot muntar sobre una estructura que s’anomena Pan/Tilt composta per dos servos que permeten el gir horitzontal i vertical. Aquest moviment es produeix gràcies a un acceleròmetre incorporat a les ulleres capaç de detectar el moviment del cap.

El plantejament d’aquest treball es basa en utilitzar el mateix funcionament de un headtracker però en aquest cas controlar l’aparell radiocontrol enlloc de l’estructura Pan/Tilt formada per la càmera i dos servos. Per tant realitzarem la construcció d’un sistema de FPV sobre un avió controlat amb headtracking. D’aquesta manera farem servir el FPV per veure en directe el que es veu des de l’avió i utilitzarem el headtracking per dirigir-lo allà on es mogui el cap seguint la mateixa direcció. Combinarem el sistema FPV, el sistema radio control i el sistema headtracking per construir un sistema conjunt capaç de controlar l’avió.

Dividirem el projecte en 3 parts principals, la primera part consisteix en fer una simulació del projecte, en la segona part es parlarà del disseny i el desenvolupament del headtracker i per últim veurem la creació d’una APP per al mòbil per verificar els resultats.

1 (First Person Vision) Sistema que permet veure en temps real les imatges provinents d’una càmera a certa distància via radiofreqüència. 2 (Seguiment del cap) Dispositiu que permet moure un objecte en funció del moviment del cap.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

9

2. Objectius

Aquest projecte té dos objectius principals: el muntatge d’un sistema FPV i la construcció d’un sistema headtracking.

Per muntar un sistema headtracking es necessari tenir coneixements del seu funcionament. Per exemple com funciona el sensor de moviment que incorpora i com podem utilitzar-lo per controlar un avió teledirigit.

D’altra banda per fer un muntatge FPV hem d’assolir coneixements bàsics d’aquest món i escollir els components adequats per a les nostres necessitats. Per exemple saber quins elements necessitem, el seu funcionament, el preu, potències de treball, tensions, consums, o interferències.

Tot plegat caldrà saber com combinar aquestes dues parts per fer volar un avió controlat amb el cap. Degut a que no es vol profunditzar tant considerarem adquirits coneixements i conceptes bàsics sobre l’aeromodelisme com també la programació amb Arduino.

Un cop feta la construcció del conjunt es faran proves per verificar el seu funcionament i veure la fiabilitat. Finalment, podrem extreure conclusions per determinar possibles millores i viabilitat per a projectes més complexos.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

10

3. Necessitats

En aquest capítol parlarem de les necessitats i els requeriments que afecten al projecte.

En primer lloc necessitem un sensor que tingui la capacitat d’obtenir el moviment produït pel nostre cap per més endavant poder calcular els angles i utilitzar aquests angles per moure l’avió com mostra la següent imatge.

Figura 1. Eixos headtracker. Imatge extreta de: https://www.instructables.com/id/Gyroscopic-Arduino-Head-Tracking-Unit/

Existeixen uns mòduls Arduino que incorporen un acceleròmetre i un giroscopi. Aquests sensors tenen la funció que requereix el projecte i per tant podem seleccionar aquest tipus de mòdul. Hi ha diferents models en el mercat però més endavant veurem quin s’ha seleccionat finalment i explicarem més detalladament la seva funció. El preu ronda els vint euros i el funcionament aproximat és el següent:

Figura 2. Diagrama disseny Headtracker

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

11

3.1 Funcionament de l’acceleròmetre

Per entendre com podem arribar a obtenir un angle a partir d’una força mitjançant un acceleròmetre cal saber com funciona. En aquest apartat veurem detalladament el funcionament i també quins càlculs haurem de fer per obtenir els angles.

Una característica molt important dels acceleròmetres és que detecten la gravetat i, com a tal, permeten saber on està el centra de la Terra. Això té un paper important a l'hora de que l'avió mantingui la seva estabilitat. L'acceleròmetre s'ha de muntar on està el centre de gravetat de l’avió perquè coincideixi el centre de coordenades

Figura 3. Centre de coordenades. Imatge extreta de: http://www.starlino.com/imu_guide.html

Per comprendre el seu funcionament ens podem imaginar una caixa en forma d'un cub amb una bola dins d'ella.

Figura 4. Acceleròmetre a gravetat 0. Imatge extreta de: http://www.starlino.com/imu_guide.html

Si agafem aquesta caixa en un lloc sense camps de gravitació la pilota simplement flotarà al centre de la caixa. Si movem de sobte la caixa a l'esquerra amb una acceleració de 9.8 m/s2 o 1g1, la pilota xocarà contra la paret X-.

1 acceleració causada per la gravetat a la superfície de la Terra a nivell del mar amb un valor de 9.80665 m/s2.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

12

Figura 5. Força eix X acceleròmetre. Imatge extreta de: http://www.starlino.com/imu_guide.html

L'acceleròmetre mesuraria la força de pressió que aplica la bola a la paret i s’obtindria un valor de -1g en l'eix X, és a dir detectarà una força que es dirigeix en la direcció oposada del vector d'acceleració. Per tant un acceleròmetre mesura l'acceleració indirecta de la força aplicada a la paret oposada d’on s’aplica la força. Aquesta força pot ser causada per l'acceleració, però com veurem en el següent exemple, no sempre és causada per l'acceleració.

Si agafem el nostre model i el posem a la Terra, la pilota caurà a la paret Z- i aplicarà una força de 1G com es mostra a la imatge següent:

Figura 6. Força eix Z- acceleròmetre. Imatge extreta de: http://www.starlino.com/imu_guide.html

En aquest cas la caixa no es mou, però lectura és de -1g a l'eix Z causada per la força de gravitació.

Podria ser un tipus de força diferent, per exemple, si imaginem que la bola és metàl·lica, i col·loquem un imant al costat de la caixa la bola tocaria una altra paret degut a la força magnètica. Per tant, les mesures de l'acceleròmetre no són exactament acceleració sinó que són mesures de forces inercials capturades per un mecanisme de detecció de pressió o força de l'acceleròmetre.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

13

3.1.1.1 Càlcul dels angles utilitzant les mesures de l’acceleròmetre

En el següent exemple el vector R és un vector de força resultant sent Rx, Ry, Rz projecció del vector R en els eixos X, Y, Z. Utilitzant el teorema de Pitàgores obtenim la següent relació:

Figura 7. Força resultat. Imatge extreta de: http://www.starlino.com/imu_guide.html

(equació 1)

R2 = Rx2 + Ry2 + Rz2

Per calcular les components Rx, Ry, Rz hem de tenir en compte que els acceleròmetres digitals incorporen mòduls ADC integrats que proporcionen un valor de tensió en un rang determinat per a cada eix (DeltaVoltsXx). Aquest valor és la informació que necessitem transformar per obtenir les components anteriors:

(equació 2)

Rx = DeltaVoltsRx / Sensitivity1 Ry = DeltaVoltsRy / Sensitivity Rz = DeltaVoltsRz / Sensitivity

Un cop tenim les components ja podem calcular els angles utilitzant la següent equació:

(equació 3)

angleX = acos (𝑅𝑥

𝑅)

angleY = acos (𝑅𝑦

𝑅)

angleZ = acos (𝑅𝑧

𝑅)

1 (Sensibilitat) cada ADC té una sensibilitat varia en funció del nombre de bits i s’ha de mirar al datasheet del component.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

14

3.2 Tecnologia MEMS

El mòdul Arduino que nosaltres utilitzarem fa servir aquesta tecnologia. Així doncs considero important dedicar un apartat per parlar sobre aquest tema.

Les sigles MEMS fan referència a sistemes micro-electromecànics, i en el cas particular dels sensors de mesura d'acceleració designen el mètode de fabricació d'alguns acceleròmetres.

Bàsicament un sistema MEMS és un circuit integrat amb característiques tridimensionals i que pot contenir peces mòbils. Amb la tecnologia MEMS s'ha aconseguit miniaturitzar la fabricació dels acceleròmetres, el que ha permès integrar-los en multitud de dispositius de mida reduïda com telèfons mòbils o càmeres digitals.

Figura 8. Comparació mida d’un acceleròmetre MEMS. Imatge extreta de: https://howtomechatronics.com/how-it-works/electrical-engineering/mems-accelerometer-

gyrocope-magnetometer-arduino/

Igual que la majoria de circuits integrats el Silici és el material més usat en la seva fabricació. Els tres tipus d'acceleròmetres que s'implementen amb aquesta tecnologia són el acceleròmetre capacitiu de silici, el piezoresistius i els acceleròmetres tèrmics.

Els acceleròmetres capacitius de silici han estat els més utilitzats tradicionalment, especialment en la indústria de l'automoció, encara que en els últims anys hi ha hagut un auge dels altres dos tipus.

Entre les seves característiques principals estan una bona linealitat, alta sensibilitat i bona precisió a un cost relativament baix.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

15

3.2.1 Acceleròmetres capacitius

Nosaltres fem servir el tipus capacitiu ja que és el que incorpora el mòdul Arduino que utilitzarem, així doncs explicarem el seu funcionament encara que és informació addicional, és a dir, no cal saber-ho per realitzar aquest projecte.

Utilitzen l'efecte capacitiu com transductor, mesuren la variació de les plaques d'un microcondensador quan el sensor és sotmès a una acceleració.

El microcondensador està format per dues plaques conductores paral·leles separades per un material dielèctric i mesura la variació de capacitància de tal forma:

Figura 9. Equació capacitància

A la pràctica quan l’acceleròmetre està en repòs les dues capacitats són iguals, quan s'aplica una acceleració, es produeix un augment en una de les capacitàncies i una disminució en l'altra, un cop detectada aquesta diferència de capacitat es procedeix a la seva transformació per obtenir la tensió de sortida.

Figura 10. Sensor en repòs (dalt). Sensor sotmès a acceleració (baix). Imatge extreta de: https://howtomechatronics.com/how-it-works/electrical-engineering/mems-accelerometer-

gyrocope-magnetometer-arduino/

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

16

Matemàticament, si es denomina Ca i Cb a les plaques dels extrems del sensor i C0 de la placa central, amb ζ, distància relativa entre la placa central i les situades en els extrems, es té:

(equació 4)

Habitualment es comercialitza com un circuit integrat en un xip de silici que permet reduir diferents problemàtiques causades per la temperatura, condicions d'humitat, capacitats paràsites, o alta impedància d'entrada.

Actualment els models en comercialització mesuren rangs entre ±1g i ±100g, sent els primers els idonis per a mesuraments de baixa freqüència a alta precisió i cost raonable, per a rangs de mesura superiors s'utilitza la tecnologia piezoelèctrica.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

17

3.3 Projectes actuals i camps d’aplicació

El headtracking o seguiment del cap és bàsicament un sistema de seguiment del moviment que en el cas del headtracking segueix el moviment del cap.

Com he dit abans un dels usos més habituals dels headtrackers es al món dels aparells radio control, quan es munten sobre unes ulleres FPV i formen un sistema Pan/Tilt amb una càmera sobre l’avió. Però en àmbits com el militar, aeroespacial, científic... també existeixen sistemes similars que tenen un altre ús. En aquest apartat veurem diferents exemples i ens farem una idea dels usos que se li pot donar.

Figura 11. Curiosity. Extreta de: https://www.albedomedia.com/tecnologia/curiosity-icuriosidad-por-las-camaras/

El seguiment del cap coincideix sovint amb el seguiment ocular o facial, on s’utilitza característiques facials com el nas, la boca i els ulls per rastrejar l'usuari. Es pot aconseguir utilitzant una càmera bàsica o un programa de seguiment de rostres i un dels objectius es millorar la interacció entre humans i robots.

Figura 12. Robot humanoide. Extreta de: https://www.albedomedia.com/tecnologia/curiosity-icuriosidad-por-las-camaras/

El seguiment del moviment s'utilitza en diverses aplicacions, com ara jocs, domòtica i sanitat.

Les dades es digitalitzen i s'envien a l'aplicació per dur a terme les tasques necessàries segons els moviments.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

18

Figura 13. Sistema Quirúrgic Da Vinci. Extreta de: https://www1.hospitalitaliano.org.ar/#!/home/cirugiarobotica/seccion/1191

En la tecnologia de seguiment del cap, es fa un seguiment dels moviments del rostre i del cap de l'usuari mitjançant la captura de dades a través de càmeres, o pot ser que es requereixi un equip especial que es porti al cap per capturar els moviments. Les característiques facials es reconeixen per separat.

És possible fer un seguiment dels moviments del cap des d'una determinada distància amb l'ús de càmeres web a portàtils. Es poden realitzar determinades accions mitjançant aplicacions amb els moviments del cap corresponents. També és possible el moviment directe i els comportaments dels personatges dins de les aplicacions mitjançant controls facials. El seguiment del cap pot ser usat juntament amb la realitat augmentada.

El concepte de rastreig de capçal s'utilitza habitualment en els jocs on es realitzen els moviments del cap del jugador i es realitzen canvis en els controls del joc segons els moviments del cap. El seguiment principal ja es veu en la integració amb els telèfons intel·ligents per donar suport a diversos jocs i autenticació d'usuaris. Serveix com una altra capa de seguretat per a l'autenticació de nom d'usuari i contrasenya tradicionals. Un usuari pot personalitzar certs moviments per garantir la seva identitat. El seguiment del cap també s'utilitza en la captura automàtica de fotografies basades en les poses i les funcions de cara.

Figura 13. Headtracker per a jocs. Extreta de: https://www.pinterest.es/pin/320740804703085059/

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

19

4. Especificacions dels components utilitzats L’objectiu d’aquest apartat és descriure tots els dispositius que s’han utilitzat per dur a terme amb èxit l’abast d’aquest treball.

En primer lloc utilitzarem un avió teledirigit anomenat Opterra de la casa Horizon Hobby. Aquest incorpora únicament el motor de propulsió, els servos digitals que permeten el gir de l’avió i una centraleta que rep la senyal de comunicació i controla la posició dels servos.

En segon lloc explicarem les característiques i quin paper tenen els components del sistema FPV, el qual ens permet veure les imatges en directe des de l‘avió i fer més real l’experiència de pilotar-lo.

Finalment parlarem del mòdul Arduino que utilitzem per controlar l’avió amb el cap, és a dir per fer un headtracking. Serà necessari també, veure les característiques de la placa Arduino que utilitzem per tractar les dades del mòdul i fer el control de l’avió. Més endavant veurem quin protocol de comunicació s’utilitza.

Figura 14. Avió teledirigit Opterra . Extreta de: http://www.horizonhobby.com

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

20

4.1 Característiques de l’avió Opterra En aquest primer apartat es descriurà les característiques principals de l’Opterra de la companyia americana Horizon Hobby. Aquest avió és de tipus ala volant i només té dos alerons per realitzar els moviment a esquerra, dreta, amunt i avall. Disposa també d’un motor amb un hèlix que es troba a la part posterior (per permetre que la càmera es munti a la part davantera i no es vegi l’hèlix a la imatge) . Aquest tipus d’avió és ideal per la seva simplicitat, estabilitat i perquè tendeixen a planejar durant més temps.

Figura 15. Ala volant. Extreta de: https://www.robotshop.com/blog/en/how-to-make-a-drone-uav-lesson-7-fpv-long-range-17518

L’Opterra no disposa de tren d’aterratge per tant el despagament ha de ser del tipus llançament amb la mà. Existeix però, la possibilitat de fer un llançament de tipus catapulta o amb pista d’aterratge. Per l’aterratge disposa d’un protector amb un material més resistent a la part inferior del cos que permet aterrar al paviment sense deteriorar-se.

Figura 16. Sistema d'enlairament. Extreta de: https://www.robotshop.com/blog/en/how-to-make-a-drone-uav-lesson-7-fpv-long-range-17518

A més aquest avió té avantatges sobre altres models ja que permet l’opció d’incorporar un sistema de vista en primera persona (FPV). Al tenir una superfície alar elevada pot suportar una carga alar major el que significa que un sistema FPV s’integra molt bé ja que pot suportar més pes del normal.

Com hem comentat abans, el sistema FPV permet obtenir una perspectiva totalment diferent (una "visió d'ocell") de la nostra terra i implica muntar una càmera de vídeo sobre ell que envia imatge de vídeo en temps real al pilot

Encara que afegir una càmera a un avió RC no és una cosa nova, el baix preu i el gran ventall de productes dels components han fet que sigui assequible muntar sistema FPV sobre un aeromodel no tripulat (UAV).

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

21

4.1.1 Electrònica

- Receptor Spektrum AS3X amb tecnologia SAFE Select - Motor Brushless - Servos digitals metàl·lics instal·lats

No inclou: - Bateria LiPo 3S 11,1V 2200 mA - Emissora Tx 8 canals - Emissor FPV - Ulleres FPV - Cámara FPV - Sensors de temperatura, GPS, altímetre

4.1.2 Dimensions

Llargada 1036 mm Amplada 1989 mm Pes 1899 g

4.1.3 Sistema Tx/Rx

El sistema de Tx/Rx consisteix en una emissora/comandament radio control el qual té un transmissor (Tx) que envia senyals de radiofreqüència al receptor (Rx) amb les ordres que hem donat mitjançant les palanques o joysticks de l'emissora. El receptor rep aquests senyals i les transforma en moviments dels servos que fan pujar o baixar els alerons controlant així l'avió.

Els sistemes més utilitzats són els de 2,4 GHz ja que són els més comercialitzats actualment, són sistemes que poden tenir un abast mitjà i fiabilitat davant interferències, encara que sempre s'ha de tenir visió directa entre el Tx i el Rx ja que en aquesta freqüència tan alta afecten molt els obstacles.

En el nostre cas farem servir una Spektrum DXe, és una emissora amb 8 canals (nosaltres en fem servir 3), té opcions de configuració per a canals auxiliars i altres recursos que necessitarem en un futur.

Figura 17. Emissora Tx

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

22

4.2 Components First Person Vision FPV

Per entendre com funciona el FPV en aquest apartat explicarem les parts que el composen i la seva funció. Segons la seva complexitat i nombre de components, es pot dividir en tres categories: equip bàsic, equip mitjà i equip professional.

Amb l’equip bàsic tenim el mínim equip per volar en FPV. Es pot utilitzar per volar al principi sense arriscar molt equip, però no és molt aconsellable perquè no tens recursos per orientar-te i si no es coneix molt bé el terreny és fàcil perdre’t.

El següent nivell és l’equip mitjà, és el més recomanable per començar. És un equip senzill però a la vegada pràctic i manejable, és com l'equip bàsic amb alguns components més que faciliten el vol, l'orientació i milloren l'abast.

El nivell professional és el més avançat: requereix molta experiència amb FPV i molts diners. Els equips són cars i difícils de trobar. Aquest tipus de vols són per a persones que els hi agrada volar a varis quilòmetres de distància.

Nosaltres utilitzarem el nivell mitjà ja que permet un vol segur i suficient pel aconseguir el nostre objectiu.

Figura 18. Exemple FPV i muntatge ulleres amb antena. Extreta de: https://www.robotshop.com/blog/en/how-to-make-a-drone-uav-lesson-7-fpv-long-range-17518

En qualsevol cas, el sistema FPV s’encarrega d’enviar les imatges capturades per la càmera via radiofreqüència perquè el pilot tingui la sensació d'anar sobre a l'avió. El transmissor de vídeo es connecta a la càmera i a una font d'alimentació, que pot ser la bateria utilitzada per al motor o una bateria de menor capacitat usada solament per això. És aconsellable la segona opció, ja que si s’alimenta amb la bateria utilitzada pel motor podria interferir en el funcionament del transmissor de vídeo ja que és molt sensible a sorolls elèctrics i interferències.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

23

4.2.1 Càmera

La càmera és el component bàsic per qualsevol sistema FPV, ja que sense la càmera no podrem capturar les imatges que es veuen des de l’avió. Hi ha molts tipus de càmeres i varien segons les característiques.

El més important és que sigui mida petita i un pes, entre 5 i 40gr, s’alimenten amb 5V o 12V depenent de la càmera, tenen un cable de vídeo que es connecta al transmissor de vídeo per enviar el senyal de vídeo.

Les característiques principals que s’han de tenir en compte són:

Tipus de sensor: poden ser CCD o CMOS, les CCD solen ser més barates i toleren millor els canvis de lluminositat. En canvi, les CMOS poden ser més cares i toleren menys els canvis de llum però donen una millor qualitat d'imatge.

Sistema PAL o NTSC: a Espanya s'utilitza el sistema PAL, així que la nostra càmera serà PAL.

Resolució horitzontal: Indica la resolució de la càmera, una càmera que tingui entre 420 i 600TVL1, és suficient per començar.

A més d'aquestes característiques tècniques, ens podem fixar en si té micròfon incorporat, el tipus de sortida de la imatge, voltatge de treball i consum. Aquestes característiques ja són a gust del consumidor.

Nosaltres utilitzarem una càmera Eachine de 1000TVL com la que mostra la figura 19, aquesta es senzilla però amb qualitat suficient per poder volar a gust i amb una mínima qualitat d'imatge.

Figura 19. Càmera FPV. Extreta de: https://www.rcocio.com/camara-fpv-600tvl-1-4-1-8mm-cmos-fpv-170-de-angulo

La càmera normalment es col·loca a la part davantera de l'avió, la posició en la qual aniria una cabina real per tenir una bona perspectiva.

1 TVL (línies de televisió) és el que els fabricants fan servir per mesurar la resolució de la càmera analògica FPV.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

24

És recomanable allunyar-la uns centímetres de la punta de l'avió per protegir-la de possibles accidents. A més s’ha d’assegurar bé al fuselatge perquè no surti disparada en cas d’estavellar-se l’avió. Més endavant explicarem en què consisteix un mecanisme que es pot afegir per donar més realisme anomenat “Pan/Tilt”.

4.2.2 Transmissor de vídeo

Els transmissors de vídeo o VTx tenen una antena la qual la seva mida varia segons la freqüència de treball. De manera que més alta és la freqüència, més petita pot ser l'antena i viceversa. Per a un equip bàsic amb les antenes de sèrie es suficient, però per millorar les prestacions és necessari canviar d'antena.

Els VTx usats en FPV tenen un pes aproximat d'entre 20 i 100 grams, on principalment el pes depèn de la potència de transmissió, que es mesura en mW. El normal és utilitzar potències entre 200 mW i 1500 mW i la conseqüència és que com més potència més distància però major consum i escalfament.

Les freqüències utilitzades per a la transmissió de vídeo són: 900 MHz, 1,3 GHz, 2,4 GHz i 5,8 GHz. Cal tenir present la legislació de la zona ja que depenent del país algunes freqüències poden estar prohibides o restringides per a altres usos.

Per seleccionar una freqüència hem de tenir en compte les següents característiques bàsiques:

Freqüència més baixa Freqüència més alta Abast Gran Petit Tolerància objectes Gran Petit Mida antenes Gran Petit Sensibilitat interferències Gran Petit

Taula 1. Taula avantatges i inconvenients freqüències

Altres dades tècniques importants és que la majoria de VTx disposen d'una pantalla on es mostra el número de canal i un polsador que permet canviar el canal de transmissió. El canal numèric ha de coincidir en el VTx i VRx per sintonitzar la imatge. Els canals s'utilitzen per variar la freqüència i així poder volar més d'un avió FPV al mateix temps.

El VTx s’ha de col·locar en un lloc de l'avió on rep un bon flux d'aire perquè amb el funcionament s'escalfa. Si no està refrigerat podria arribar a cremar-se i perdre la connexió amb el consegüent perill d’estavellar-se o perdre’s.

També és recomanable allunyar-lo del receptor de comandament (Rx). Entre el transmissor de vídeo el receptor de radiofreqüència es produeixen interferències i es redueix l'abast dels dos notablement.

Nosaltres utilitzarem un transmissor com el que mostra la figura següent amb una freqüència de 5.8 GHz i una potència de 600 mW.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

25

Figura 20. Emissor de vídeo. Extreta de: https://produto.mercadolivre.com.br/MLB-888562538-transmissor-video-fpv-58g-600mw-ts832-qav250-audiovideo-_JM

4.2.3 Receptors de vídeo

El Receptor o VRx s'encarrega de rebre el senyal que envia el VTx. També té una antena i s’ha de col·locar en una posició alta en la qual l'antena estigui lliure d'obstacles per tenir una bona recepció. L'abast d'un equip de FPV també depèn del receptor, depenent la qualitat d'aquest i el tipus d’antena que utilitza tindrà mes o menys sensibilitat.

Els VRx també necessiten alimentació, que podrà ser proporcionada amb una bateria lipo. En el nostre cas les ulleres ja disposen de VRx integrat i ens estalviem aquest pas.

4.2.4 Ulleres FPV

Aquest component potser sigui el que depèn més dels gustos de cadascú, pot ser amb un monitor, amb ulleres o amb l’ordenador. En el nostre cas utilitzarem les ulleres.

Amb les ulleres gaudirem de la millor manera d’un vol FPV, ja que només tens la visió del que veu la càmera posada damunt de l’avió, és una immersió total ja que sembla realment que estiguis a l'avió.

El principal desavantatge és el seu preu que pot ser entre 200 i 400 €, pot haver versions més barates però s’ha de tenir molta cura a l'hora de comprar-les, ja que hi ha una sèrie de coses que poden afectar a la seguretat de la nostra vista. Una d'elles, per exemple, és la distància de la pantalla amb la pupil·la, i és que no tothom té les pupil·les dels ulls a la mateixa distància entre si i unes ulleres que no s'adaptin a la distància pot danyar la vista.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

26

Un altre desavantatge és haver de treure i posar les ulleres ja que no és tan ràpid com pot ser per exemple, el monitor. Sobretot per a les fases d'enlairament, aterratge i en cas de desorientació, ja que en els segons que es triguen a retirar les ulleres pots desorientar-te, perdre l'avió de vista o estavellar-te en aquest moment d'absència de control sobre l’aeromodel.

Jo he optat per un model d’ulleres (figura 21) que inclou un receptor de vídeo integrat i una bateria externa. També hagués sigut vàlida un monitor LCD ja que la qualitat del vídeo que ofereix sol ser més alta i així obtindríem una millor experiència global pel mateix preu.

Figura 21. Ulleres FPV amb receptor de vídeo incorporat (Eachine ev800). Extreta de: https://www.banggood.com/es/Eachine-EV800-5-Inches-800x480-FPV-Goggles-5_8G-40CH-

Raceband-Auto-Searching-Build-In-Battery-p-1053357.html

4.2.5 Pantalla en pantalla (OSD) És un component molt important per poder volar en FPV amb una mínima seguretat, la seva missió és la de mostrar a la pantalla dades de l'avió, com són la posició, alçada, velocitat, rumb etc. El OSD es connecta entre la càmera i el VTx de vídeo, perquè pugui injectar les dades a la pantalla i puguem veure'ls còmodament al monitor o les ulleres mentre volem, normalment els OSD incrusten les dades a les vores de la pantalla per tenir una visió més clara del centre. L'OSD necessita un mòdul GPS perquè pugui proporcionar dades com la distància, alçada, velocitat, rumb o altres. El GPS ha d’estar en una posició on no tingui cap objecte a sobre per a què tingui bona cobertura amb els satèl·lits i pugui calcular la posició. És recomanable allunyar-lo de qualsevol component electrònic ja que pot interferir en aquest.

Figura 22. Exemple sistema OSD. Extreta de: https://www.youtube.com/watch?v=zHq0E5FM_XU

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

27

Un altre component que es pot connectar a un OSD és l'amperímetre que s'encarrega de mesurar la intensitat que passa pels cables de la bateria, per saber el consum instantani i l'acumulat. És molt útil per saber quan deixa de volar, ja que sense aquesta dada no podrem saber de quanta càrrega disposem en cada moment. Normalment també incorpora voltímetre que ens donarà el voltatge de la bateria amb la mateixa finalitat.

Gairebé tots els OSD disposen també de la “fletxa de retorn” cap a casa, que serveix per si ens desorientem: només haurem de fixar-nos en la fletxa i veure on ens diu que som. Normalment aquest punt s'estableix en engegar l'OSD, és a dir, quan es connecta a l’alimentació amb la bateria.

Una altra característica que pot tenir un OSD és l'anomenat RTH (Return To Home) i la seva fi és portar automàticament l'avió a punt d'enlairament. Normalment aquesta opció s'activa o mitjançant un interruptor o per pèrdua de senyal. Quan l'avió deixa de rebre el senyal de l'emissora perquè s'ha allunyat massa o per altres causes el RTH s'activa segons aquest configurat, controlant l'avió automàticament fins al punt d'enlairament. Un cop arribi al punt s'ha de posar a donar voltes en cercles segons la configuració establerta.

Els preus dels OSD ronden entre els 30 € un de senzill amb mínima informació i 250 € que aporten totes les dades possibles, estabilitzador, sensor baromètric per l'altura i moltes opcions de configuració.

En el nostre cas farem servir el OSD-3 de Hobbyking (figura 23) que disposa del mòdul GPS(altímetre, velocímetre, coordenades GPS, fletxa de casa), amperímetre, voltímetre i nivell de senyal.

Figura 23. OSD-3. Extreta de: https://hobbyking.com/es_es/hobbyking-g-osd-3-mini-osd-system-w-gps-module.html

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

28

4.2.6 Antenes

4.2.6.1 Factors de rendiment de les antenes

Hi ha molts paràmetres que afecten al rendiment d'una antena, d’entre altres:

El guany El patró de radiació La ràtio axial L'amplada de banda de la freqüència La freqüència sintonitzada La impedància

En aquest apartat nomes parlarem dels 3 primers ja que són els més importants.

Guany de l'antena El guany és un indicador de l'abast i l'angle de cobertura en una antena direccional. Un guany més alt generalment vol dir més abast però una amplada del feix de ràdio més estreta. El guany de l'antena pot alterar el patró de radiació com veurem en el següent apartat.

Patró de radiació El patró de radiació (Radiation Chart) mostra la forma de la radiació emesa per l'antena, aquests patrons ajuden a veure com i perquè es perd el senyal.

Una antena de 0dB de guany és una antena totalment omnidireccional, és a dir que té un patró de radiació gairebé esfèric. En la següent imatge es mostra el patró de radiació per a una antena de 3 dB de guany, s’observa que en els plans horitzontal i vertical l’estret del raig es totalment esfèric.

Figura 24. Patró de radiació ideal. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

Però en el món real, les antenes omnidireccionals pateixen de pèrdua de senyal per sobre i per sota i el patró de radiació s'assemblaria més a un dònut que a una esfera.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

29

Figura 25. Patró de radiació ideal. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

Les antenes de baix guany poden semblar menys desitjables si parlem de l'abast però ofereixen més fiabilitat gràcies a un patró de radiació més esfèric, i es pot obtenir un bon senyal apuntant amb l'antena al receptor.

Ràtio axial En termes pràctics, el que es mesura amb el Ràtio Axial és com de susceptible és l'antena de patir interferències. Les antenes amb millor capacitat per rebutjar interferències fan molt més fàcil volar en llocs on hi han moltes freqüències. Com més proper a 1 sigui el Ràtio Axial de l'antena, millor.

4.2.6.2 Tipus d’antenes

Antenes de polarització lineal

Són les més comunes i segurament tots tenim una antena d'aquest tipus al nostre router o WIFI, són les antenes amb les quals vénen de sèrie amb tots els sistemes de transmissió de vídeo o recepció de vídeo.

Figura 26. Antena polarització lineal. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

La seva característica fonamental és el seu patró de propagació lineal. En la figura 27 es veu la propagació en vermell d'una antena en posició horitzontal i en verd d'una antena en posició vertical.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

30

Figura 27. Patró de propagació lineal. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

Aquest tipus de propagació en un sol pla permet que tinguem més abast, però requereix que tant l'antena transmissora com la receptora estiguin alienades en la mateixa posició, ja sigui de manera horitzontal o vertical.

El desavantatge principal és que en un aeromodel aquesta condició no es dóna sempre, ja que pot canviar de pla realitzant un gir i per tant tindrem una pèrdua de senyal. A més tenen una gran facilitat de rebotar contra objectes i generen interferències o imatges fantasma.

Antenes de polarització circular

Generalment es fa servir aquest tipus d'antenes per a FPV degut a la seva forma de propagació circular com es pot veure en la següent a la imatge.

Figura 28. Patró propagació circular. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

31

Un avantatge és que eviten que tinguem pèrdues de senyal quan l’aeromodel estigui completament desalineat amb el pla del pilot. Amb el patró circular és com si coexisteixen simultàniament el patró lineal horitzontal i el vertical, de manera que sempre tindrem bon senyal. Un altre avantatge d'aquest tipus de polarització és que tenim menys interferències o senyals fantasmes quan el senyal rebota contra un objecte.

Com a desavantatge és que en generar una polarització circular, es gasta més energia i per tant el seu abast serà menor amb una mateixa antena del mateix guany de tipus lineal.

Figura 29. Antena polarització circular. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

Antenes omnidireccionals/direccionals

Una antena omnidireccional és aquella que emet tota la seva potència en tota la seva circumferència, és a dir en 360 graus "idealment", mentre que una antena direccional és aquella que s'ha modificat perquè tota la potència sigui tramesa en una sola direcció.

Figura 30. Propagació omni-direccional i direccional. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

La imatge anterior ens serveix d’exemple ja que la bombeta en aquest cas seria una antena omnidireccional, degut a que la llum s'escampa en 360º, mentre que la llanterna es una antena direccional perquè només emet la seva llum en un sentit.

Com més lluny volem volar les antenes han de ser millors, una bona opció són les antenes de polarització circular, que tenen l'avantatge de que pots volar en qualsevol direcció i segueixen

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

32

funcionant bé. L'antena direccional té el desavantatge de que necessita estar enfocada cap a l'avió, encara que depenent de l'antena pot tenir més angle d'enfocament o menys.

Aquest angle va directament relacionat amb el guany de l'antena, com més guany més abast tindrà, però necessitarem reduir l’angle respecte l'antena. El guany es mesura en decibels (dB), quants més decibels té millor escolta el senyal. Cada 3 dB de guany l’antena duplica l'abast, per exemple, una antena amb 3 dB de guany amb un rang de 3 km, la mateixa antena però amb 6 dB augmentarà la distància a 6 km.

En aquest projecte utilitzarem una antena direccional pel receptor de vídeo i una antena omnidireccional pel emissor de vídeo.

Figura 31. Tipus d'antena. Extreta de: https://www.dronetrest.com/t/the-complete-guide-to-fpv-antennas-for-your-drone/1473

4.2.6.3 Tipus de connectors

Normalment s’utilitzen els SMA i els RP-SMA. Són de disseny diferent i no són compatibles entre ells. En general és més còmode utilitzar SMA ja que és el més comú encara que no hi ha diferència pel que fa al comportament.

Figura 32. Tipus connectors. Extreta de: http://www.dronedron.com/es/antenas-fpv/746-immersionrc-fatshark-spironet-58ghz-lhcp-antenna-set-sma-2pcs.html

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

33

4.2.7 Servos digitals

Un servo és un conjunt de components mecànics, elèctrics i electrònics. Consta d’una placa amb un microprocessador que és l'encarregat de realitzar les tasques de regulació del servo. També incorpora un petit motor de contínua que és l'encarregat de produir el moviment.

Els motors de contínua es mouen a altes velocitats i tenen molt poc parell. Per això, a la part superior, hi ha una petita caixa d'engranatges que realitza una reducció molt alta per aconseguir transformar altes revolucions per minut i poc parell de motor a un moviment angular continu i amb molta força . A un dels engranatges ja reduïts està unit mecànicament un potenciòmetre (o encoder), que és l'element de mesura que utilitza el xip per conèixer la posició angular actual i comparar-la amb la consigna per saber en quin sentit ha de fer girar el motor.

El sistema de control de la posició del motor està basat en l'ample d'un pols. Aquest pols que normalment és de 1,5 ms manté el servo en posició centrada. Si el pols és mes curt, per exemple 1 ms el servo gira a l'esquerra, si el pols és més gran, per exemple 2 ms, el servo gira a la dreta. El moviment del servo és proporcional al pols que se li aplica.

Figura 33. Servomotor digital. Extreta de: http://www.electrontools.com/Home/WP/2016/03/09/servo-motor-arduino/

En el nostre avió ja estan instal·lats de sèrie, és a dir tenen les característiques apropiades per aquest aeromodel i per tant no cal modificar-los. L’objectiu d’aquest treball és moure aquests servos però la consigna enlloc de venir de l’emissora vindrà del headtracker.

4.2.7.1 Pan/Tilt

El sistema “Pan/Tilt” està compost per una càmera i una estructura mecànica amb dos servos, un per moure verticalment l’estructura i l’altre que serveix per fer el moviment horitzontal. També consta d’un sensor de moviment que envia dades a un microcontrolador i interpreta les dades com a angles. Aquest sistema es coneix com headtracker i el nostre treball està basat amb aquesta idea.

La funció principal d’aquest sistema consisteix en fer més real el pilotatge de l’avió de manera que s’instal·la una càmera mòbil sobre l’aeromodel per donar un altra perspectiva del paisatge i

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

34

fer més real el vol. Simula els moviments de gir del cap que faria el pilot per mirar cap a tots costats sense tenir que girar tot l’aeromodel. Aquest sistema es coneix amb el nom de “headtracking” (seguiment del cap).

El sistema per accionar el servos és el mateix en un servo per moure els alerons o controlar l’avió. Es necessiten dos canals disponibles de la emissora per enviar la trama PPM que conté la informació dels polsos del Pan i del Tilt.

Figura 34. Sistema Pan/Tilt. Extreta de: https://www.gearbest.com/fpv-system/pp_236231.html

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

35

4.3 Components headtracker

En aquest apartat es descriuran els diferents elements en que esta constituït el headtracker. El headtracker estarà fet amb components Arduino perquè són assequibles, tenen els requisits necessaris i existeix llibreries que ens ajudaran a assolir l’objectiu.

Pel que fa a la detecció de moviment existeix un mòdul anomenat MPU6050 que conté un acceleròmetre i es capaç de donar-nos informació del moviment del nostre cap.

També necessitarem la placa Arduino Nano que tindrà la finalitat de comunicar-se amb el mòdul MPU6050 i amb l’emissora de manera que obtindrà dades del mòdul i enviarà el senyal PPM a l’emissora en funció de les dades obtingues.

4.3.1 MPU6050

El sensor MPU6050 conté dues parts, l'acceleròmetre i el giroscopi. La MPU6050 és un 6 DOF (graus de llibertat) o un sensor IMU de sis eixos, el que significa que dóna sis valors com a sortida. Tres valors de l'acceleròmetre i tres del giroscopi. La MPU6050 és un sensor basat en la tecnologia MEMS (Micro Electro Mechanical Systems). Tant l'acceleròmetre com el giroscopi estan integrats dins d'un sol xip. Aquest xip utilitza el protocol I2C (Inter-Integrated Circuit) per a la comunicació.

4.3.1.1 Característiques

Acceleròmetre de 3 eixos ADXL345 Giroscopi de 3 eixos ITG3205 Magnetòmetre HMC5883L Consum 23 μA en mode de mesura. Resolució fixa 10 bits Interval de tensió d'alimentació 3,0 V a 5,0 V Comunicació I2C

Figura 35. MPU6050. Extreta de: http://www.arduino.com

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

36

4.3.2 Arduino NANO

La placa Arduino NANO, és un dispositiu electrònic reprogramable de molt baix cost econòmic, emprat per a desenvolupar aplicacions simples relacionades amb l’electrònica. Aquesta disposa d’entrades i sortides digitals i també d’entrades i sortides analògiques. Això permet desenvolupar una gran varietat d’aplicacions tan simples com complexes. Des d’encendre i apagar un LED a construir un robot.

Figura 36. Arduino NANO . Extreta de: http://www.arduino.com

A diferència d’altres plaques, aquesta ha estat preprogramada mitjançant un “Bootloader5”, això permet que aquesta placa no hagi de fer ús d’un programador extern i per tant, tan sols faci falta un simple ordenador per programar-la. A continuació, descriurem el Hardware i el Software que farem ús:

4.3.2.1 Característiques

Microcontrolador ATmega328 Voltatge d’operació 5 V Voltatge d’entrada (recomanat) 7-12 V Voltatge d’entrada (límit) 6-20 V Pins E/S Digitals 14 (6 dels quals són sortides PWM) Pins E Analògics 6 Corrent CC per a pins de E/S 40 mA Corrent CC per a pins de 3,3 V 50 mA Memòria Flash 32 kB, 0,5 kB ocupats pel Bootloader SRAM 2 kB EEPROM 1 kB Freqüència de rellotge 16 MHz

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

37

4.4 Resultat

La solució consisteix en aprofitar l’emissora per comunicar amb l’avió però enlloc de controlar-lo amb els potenciòmetres utilitzaré el headtracking. L’emisora doncs, en servirà de pont de comunicació entre el headtracker i l’avió.

Figura 37. Diagrama de components

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

38

5. Simulació headtracker

Abans de començar amb el disseny del headtracker he considerat important fer una representació virtual del funcionament d’aquest. En aquest capítol explicaré el mètode que he utilitzat per fer una simulació 3D en temps real del control de l’avió amb un sensor.

Per fer-ho hem utilitzat dos entorns de programació els quals són Arduino i Processing. El Processing és una aplicació que utilitza un llenguatge basat amb Java per a la programació d'imatges, animació, i so. Aquesta aplicació permet dibuixar en aquest cas un avió amb figures geomètriques en tres dimensions. També he utilitzat l’Arduino per carregar el software que permet la interacció entre el sensor i el Processing.

Figura 38. Simulació avió 3D

5.1 Hardware

- Sensor MPU6050 - Arduino NANO - Cables de connexió

La connexions entre el sensor MPU6050 i la placa Arduino, en el meu cas Arduino Nano estan representades en la següent imatge. El protocol de comunicació que utilitzen és I2C.

Figura 39. Connexió Arduino en MPU6050. Extreta de: https://www.rcgroups.com/forums/showthread.php?1677559-DIY-Headtracker-(Easy-

build-No-drift-OpenSource)

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

39

Configurem el pin digital 2 d'Arduino com a pin d’interrupció, és a dir, connectarem aquest pin al pin anomenat com INT de la MPU6050. També cal configurar el pin analògic 4 d’Arduino com a SDA i el pin analògic 5 com a SCL per a la comunicació I2C.

Vin Vcc GND GND A4 SDA A5 SCL D2 INT

5.2 Software 5.2.1 Llibreries

- I2CDev per Arduino - MPU6050 per Arduino - Toxiclib per Processing

5.2.2 Arduino

En aquest apartat explicarem com programar el microcontrolador ATmega328 d’Arduino per a que hi hagi comunicació amb el mòdul MPU6050.

Un cop instal·lat el software oficial d’Arduino (Arduino IDE) ens descarreguem les llibreries I2Cdev i MPU6050 i connectem la placa al ordinador amb un cable mini USB.

Figura 40. Carpetes de les Llibreries

Per afegir aquestes llibreries al IDE i carregar-les al micro hem de seguir els següent passos:

1. Iniciar l’Arduino IDE 2. Anar a Programa > Inclou llibreria > Afegeix llibreria Zip 3. Localitzar el fitxer Zip amb les llibreries i fer clic a Obre 4. Per carregar el codi 5. Fitxer > Exemple > MPU6050 > MPU6050_DMP6 6. Botó Programar

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

40

5.2.3 Processing

Un cop programat el microcontrolador ens descarreguem la llibreria Toxiclib i ja podem utilitzar el Processing per fer la simulació en 3D.

1. Copiem la llibreria C: \ Users \ admin \ Documents \ Processing \ libraries 2. Click a Obre > MPUTeapot. 3. Configurem el port COM on tenim connectat l’Arduino. 4. Click al botó Run.

5.3 Resultat

En les següents imatges podem observar el resultat de la simulació, l’avió gira en funció del moviment del sensor MPU6050 i ens podem fer una idea del funcionament del headtracker.

Figura 41. Posició inicial simulació

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

41

Figura 42. Gir avall simulació

Figura 43. Gir amunt simulació

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

42

Figura 44. Gir dreta simulació

Figura 45. Gir esquerra simulació

Podem dir que la lectures del moviment en els 3 eixos són molt precises i ràpides. Per tant la conclusió és que aquest mòdul és viable per pilotar un avió ja que detecta el moviment perfectament.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

43

6. Headtracker

L’objectiu principal d’aquest capítol és explicar el desenvolupament i la construcció del headtracker. Per fer-ho dividirem aquest capítol en diferents parts on parlarem dels dubtes que es generen inicialment fins els detalls més concrets que van sorgint. He volgut fer-ho així ja que és la situació real en que em vaig trobar quan vaig començar aquest projecte i es necessari per entendre la complexitat d’aquest.

El primer dubte que es genera és saber com enviar la informació des de el headtracker fins a l’avió. A priori hi han dues opcions, desenvolupar un sistema propi de radiofreqüència o utilitzar la mateixa emissora. El problema del sistema propi es que hauria de ser capaç d’emetre exactament a la mateixa freqüència que la emissora o fer un software capaç de sincronitzar o vincular el receptor de l’avió amb el nostre sistema.

D’altra banda la emissora ja esta vinculada al receptor de l’avió i l’abast d’aquesta ens permet volar a una distància prou gran per satisfer les nostres necessitats, a més és convenient que es pugui controlar l’avió amb l’emissora ja que si falla el headtracker o es fes molt difícil controlar l’avió amb el cap evitaríem unes conseqüències desastroses.

Per tant, la millor manera per establir comunicació entre l’avió i el headtracker és aprofitar la emissora com a mètode principal de control i programar d’alguna forma el fet de transferir el control al cap quan nosaltres volguéssim.

En primer lloc és necessari comprendre el protocol que utilitza l’emissora per comunicar-se amb l’avió. El primer que farem doncs és analitzar aquest mètode de comunicació per entendre el funcionament i saber com ha de ser el software per lligar amb aquest sistema.

El segon pas es analitzar el funcionament d’altres headtracker i veure diferents aplicacions per veure en què ens podem basar o veure possibles solucions. Per tant farem una breu recerca sobre altres productes per resoldre qüestions sobre la manera d’utilitzar el headtracker. Com per exemple el lloc ideal on col·locar el sensor o la que sensibilitat que tindrà.

Finalment parlarem del hardware i software utilitzats per a que tot funcioni correctament.

6.1 Protocol de comunicació entre l’avió i Arduino

La comunicació de l’emissora amb l’avió es fa via radiofreqüència. En aquest apartat explicarem quina informació viatja a través de la radiofreqüència i com utilitzar les dades obtingudes pel sensor per enviar-les.

Les emissores RC funcionen amb un protocol de comunicació específic, aquest protocol s’anomena PPM i en aquest apartat explicarem en que consisteix.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

44

Per saber les característiques d’aquest senyal que utilitza la nostra emissora hem aprofitat un port que s’anomena Trainer. Aquest port permet connectar un altra emissora mitjançant un cable i transferir o commutar el control de l’aparell radio control de una emissora a l’altra. La idea es connectar un cable per fer creure a l’emissora que l’estem utilitzant però aprofitarem per analitzar el senyal connectant un oscil·loscopi en l’altre extrem.

Figura 46. Connector jack 2.1mm PortTrainer

Per tant connectarem el cable de comunicació a l’emissora per un extrem i l’oscil·loscopi per l’altre i observem que la senyal es del tipus PPM(modulació de posició de punts).

6.1.1 PPM o modulació de posició de punts

Les emissores de radiofreqüència en aparells de radio control funcionen generalment a una freqüència de 2.4GHz. Aquesta banda permet enviar informació a molta distància, apareixen poques interferències i té capacitat de travessar objectes. LA informació que s’envia en aquesta freqüència és del mateix tipus i s’anomena PPM (modulació de posició de punts).

Figura 47. Exemple funcionament PPM. Extreta de: https://www.rcgroups.com/forums/showthread.php?2040789-Tutorial-Getting-

Dragonlink-12ch-PPM-to-work-with-MultiWii

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

45

En les emissores RC aquest sistema de comunicació té l'avantatge que només s'utilitza un cable per enviar informació de diversos canals. Els canals en el món radio control signifiquen el nombre de moviments que pot fer l’aparell, per exemple avant, enrere, esquerra, dreta, amunt, avall... que es tradueixen a channel1, channel2, etc.

Figura 48. Exemple protocol PPM. Extreta de: https://www.rcgroups.com/forums/showthread.php?2040789-Tutorial-Getting-

Dragonlink-12ch-PPM-to-work-with-MultiWii

Aquest senyal es sembla al PWM (modulació per amplada de polsos) i de fet, però està modulat de forma diferent. Es segueix transformant un senyal analògic en un senyal digital i la informació de cada pols s’envia un rere l'altre. La diferència és que en el PWM el cicle de treball és en funció de la variació del nivell del pols (eix Y) mentre que en el PPM és la variació del temps que hi ha entre pols i pols (eix X).

Figura 49. Diferència entre PWM i PPM. Extreta de: https://www.rcgroups.com/forums/showthread.php?2040789-Tutorial-Getting-

Dragonlink-12ch-PPM-to-work-with-MultiWii

Per tant hem de tenir en compte que per fer el software hem d’obtenir les mesures del sensor de moviment i transformar-les en aquest tipus de senyal tenint en compte que el cicle de treball és en funció del temps.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

46

6.1.2 Característiques protocol

Un cop sabem que s’utilitza el PPM com a protocol de comunicació, cal saber les característiques del senyal(canals, altura, amplada, freqüència) per a que la emissora entengui la informació que volem enviar. En aquest apartat podem veure el senyal provinent de la emissora amb les següent imatges capturades amb l’oscil·loscopi.

Figura 50. Període senyal PPM Tx

Figura 51. Mínim temps de durada de canal

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

47

Figura 52. Màxim temps de durada de canal

L’objectiu d’aquest anàlisis es veure quin canal de la emissora correspon a l’acceleració de l’avió, quin al gir de dreta i esquerra i quin al gir amunt i avall. També veure quin és el màxim i el mínim període quan es mou el joystick de l’emissora a una banda i a l’altra.

Els resultats són els següents:

Acceleració Channel 1 Tilt Channel 3 Roll Channel 2 Cicle de treball normal 1000 ms Màxim cicle de treball 1400 ms Mínim cicle de treball 660 ms

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

48

6.2 Desenvolupament

El primer pas per fer la construcció del headtracker és tenir el hardware amb les connexions correctes. Com ja s’ha dit anteriorment utilitzarem el mòdul MPU6050 i un placa Arduino Nano que connectarem amb la emissora amb un cable des de un pin digital (sortida PPM) fins el port Trainer de l’emissora. Utilitzarem aquest cable per verificar amb l’oscil·loscopi si s’ha reproduit un senyal PPM compatible amb l’emisora.

6.2.1 Hardware

- Sensor MPU6050 - Arduino NANO - Cable d’alimentació - Cable comunicació jack 2.1mm - Emissora

El cable de comunicació tindrà una connector de tipus jack 2.1mm a un extrem i soldarem connectors tipus Arduino a l’altre.

Figura 53. Connexions entre Arduino, MPU6050 i Tx. Extreta de: https://www.rcgroups.com/forums/showthread.php?1677559-DIY-Headtracker-(Easy-

build-No-drift-OpenSource)

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

49

MPU6050 Pin Arduino

Vcc_in 5 volts

GND Ground/GND

SCL A5

SDA A4

Taula 2. Pinout entre Arduino i MPU6050

Tx Arduino

PPM_IN D9

Ground Ground/GND

Taula 3. Taula connexions entre Arduino i Tx

6.2.2 Software

En el tercer capítol hem vist el funcionament de l’acceleròmetre arribant a la conclusió que el bucle principal del programa ha de fer el següent:

1. Llegir els valors de l'acceleròmetre en V 2. Transformar aquests valors en força G 3. Transformar els valors en angles 4. Normalitzar els valors obtinguts 5. Calcular els angles Pitch i Roll

L’entorn de programació que utilitzarem per desenvolupar el software és el IDE Arduino. Aquest software s’ha utilitzat per obtenir dades de l’entorn, tractar-les i fer possible la comunicació entre l’Arduino i l’avió per dirigir-lo amb el cap.

A més utilitzem una interfície gràfica desenvolupada amb Visual Studio que ens ajuda a interactuar amb el headtracker. Es tracta d’un panell de control on podem veure gràficament els valors mesurats per l’acceleròmetre.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

50

Figura 54. Interfície gràfica

En la imatge anterior podem veure les opcions que permet com per exemple:

Casella de selecció del port COM on està connectat l’Arduino Connect: inicia la comunicació Disconnect: finalitza la comunicació Start Plot: incia representació gràfica de dades Stop Plot: atura representació gràfica de dades Clear Plot: Neteja el gràfic

6.2.1.1 Proves

Un cop dissenyat el software s’ha procedit a verificar el funcionament utilitzant un oscil·loscopi per veure la senyal del pin digital assignat com a sortida PPM (D9). El que s’ha fet és punxar la sonda de l’oscil·loscopi al pin D9 del Arduino i els resultats han estat els següents:

Figura 55. Període senyal PPM headtracker

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

51

Figura 56. Màxim temps de durada de canal

Figura 57. Mínim temps de durada de canal

La conclusió de les proves és que s’ha pogut reproduir un protocol PPM molt semblant al de l’emissora i per tant s’ha verificat que funciona correctament.

Emissora Headtracker Tilt Canal 3 Canal 3 Roll Canal 2 Canal 2 Cicle de treball standby 1000 1100 Màxim cicle de treball 1400 1600 Mínim cicle de treball 660 600

Taula 4. Comparació PPM entre emissora i headtracker

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

52

6.3 Resultat

En aquest apartat s’ha conectat la sortida digital Arduino D9 amb l’emissora utilitzant el cable amb el jack 2.1 mm. Abans de fer una prova de vol s’ha verifcat que hi ha comuniació entre el headtracker i l’avió observant si es mouen els alerons.

En el següent capítol es realitzarà una prova de vol utilitzant aquest sistema i s’explicarà quins mètodes s’han utilitzat per verificar els resultats.

Al tractar-se d’un avió amb sol dos alerons el moviment que es produeix al moure els alerons provoca que l’avió es mogui com indica la figura 58.

Figura 58. Moviment produït pels alerons. Extreta de: http://visitarelcielo.blogspot.com/2018/02/la-guinada-adversa.html

En les següents imatges podem observar el moviment dels alerons amunt i avall en funció del moviment del cap.

Figura 59. Direcció normal headtracker

Aleró dret: recte

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

53

Aleró esquerre: recte

Figura 60. Direcció amunt headtracker

Aleró dret: pujat

Aleró esquerre: pujat

Figura 61. Direcció avall headtracker

Aleró dret: baixat

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

54

Aleró esquerre: baixat

Figura 62. Direcció dreta headtracker

Aleró dret: baixat

Aleró esquerre: pujat

Figura 63. Direcció dreta headtracker

Aleró dret: pujat

Aleró esquerre: baixat

Per tant s’ha verificat que hi ha comunicació i s’ha aconseguit moure els alerons amb el headtracker. Aixó implica que ja es pot fer una prova de vol per veure el resultat final.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

55

7. Mètodes de verificació i obtenció de dades

En aquest apartat explicaré el procés que he seguit per verificar els resultats del projecte. La idea que s’ha implementat per demostrar el funcionament del headtracker ha sigut posar el mòbil sobre l’avió durant el vol com a enregistrador de dades.

Per fer-ho s’ha desenvolupat una aplicació de mòbil capaç d’obtenir dades del GPS (sistema de posicionament global) de manera que es pot saber en tot moment la longitud, latitud, altitud del mòbil. També s’utilitza els sensors de posició incorporats al mòbil per determinar en graus la posició vertical i horitzontal.

Aquesta informació es guarda a un Excel a la memòria interna del mòbil on després es pot analitzar les dades.

L’entorn de programació utilitzat és l’App Inventor.

Figura 64. Logo App inventor. Extreta de: https://blog.aulaformativa.com/manual-base-para-mit-app-inventor-2/

A més, s’utilitza un altra aplicació mòbil per a ciclistes més coneguda com Runtastic per a contrastar el resultats. S’ha decidit fer així per tenir dos fonts de dades amb orgien diferent i veurem si les dades agafes de la nostra APP són correctes.

La funció és molt semblant ja que permet fer un seguiment GPS del dispositiu i permet saber el recorregut exacte, a més dona altres tipus d’informació com la durada, els metres de desnivell i la velocitat.

Figura 65. App Runtastic. Extreta de: https://www.mediavida.com/foro/ofertas/runtastic-mountain-bike-pro-gratis-592630

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

56

7.1 APP GPS tracker

Aquesta és la pantalla principal de l’aplicació (figura 66). Com es pot observar consta de tres botons:

START Inicia l’enregistrament i guarda les dades un cop per segon a un Excel en format (.csv)

END Acaba l’enregistrament de dades CLEAN Borra el document Excel creat de la memòria interna

Un cop pres START els valors de latitud, longitud, altitud, pitch i roll es mostren per pantalla al mateix temps que es guarden.

Figura 66. Pantalla inicial App GPS tracker

7.2 Resultats prova de vol

En el cas dels angles es guarda un valor cada segon en un Excel independent. En el cas de les coordenades GPS i l’altitud les dades es guarden també en un Excel independent però en aquest cas no es cada segon sinó que es fa quan hi ha hagut un canvi del valor. Els excels són independents ja que és mes senzill tractar les dades per separat.

Figura 67. Fitxers de dades generats

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

57

Les següent imatges són gràfics que representen els valors registrats amb l’app GPS tracker durant el vol utilitzant ja el headtracker. També hi han dues imatges on podem observar l’altitud i el recorregut registrat per l’app Runtastic. A més hem registrat les dades del sensor headtracker per contrastar les 3 informacions i veure que la resposta de l’avió es en funció del moviment del cap.

En la figura 68 podem observar la altitud registrada per l’aplicació Runtastitc.

Figura 68. Altitud registrada per la App GPS tracker

La figura 68 mostra l’altitud registrada per la APP GPS tracker

Figura 69. Altitud GPS Tracker App

Com s’ha pogut observar la forma dels gràfics coincideix suficient per dir que l’altitud a l’APP GPS tracker funciona correctament.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

58

En la següent imatge podem observar l’angle Pitch mesurat del sensor de posicionament del mòbil a traves de l’APP GPS tracker.

Figura 70. Angle Pitch GPS Tracker App

S’observa que la forma també coincideix bastant. Això es degut a que quan l’angle pitch es positiu l’avió agafa alçada i quan es negatiu baixa. D’altra banda s’observa molts pics, una hipòtesi que l’avió s’incline en determinats moments degut a les ràfegues de vent. També es pot observar els canvis bruscos d’inclinació degut a la sobtada inclinació del headtracker. En aquest cas doncs, podem dir que l’angle Pitch de la nostra APP també funciona bé.

A continuació s’ha registrat el recorregut durant el vol per contrastar els resultats enregistrats de Roll i longitud.

Figura 71. Recorregut registrada per la App GPS tracker

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

59

Figura 72. Longitud GPS Tracker App

En aquest cas costa interpretar les dades ja que estàn amb graus però si es fa l’interpretació correctament es veu hi ha coincidència. Per fer-ho s’ha d’observar la figura 71 i partint del punt incial quan l’avió va a l’esquerra el gràfic baixa però si gira a la dreta el gràfic puja.

Per tant podem dir que la longitud enregistrada també es correcta i concorda amb la lectura del recorregut.

El següent gràfic mostra les dades enregistrades de l’angle roll de l’APP GPS tracker.

Figura 73. Angle Roll GPS Tracker App

En aquest cas l’angle Roll registrat per l’app GPS tracker no té sentit i no coincideix en res amb els altres gràfics per tant no podem demostrar que l’app funciona bé. Per tant no ens serveix per mostrar resultats de forma correcta.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

60

8. Conclusions

Amb aquest treball s’ha treballat en el funcionament de l’acceleròmetre per mesurar l’inclinació i en el disseny d’un software per transformar el moviment de gir del cap amb moviment de l’avió.

S’ha fet el muntatge d’un sistema complex de FPV amb components determinats per a les nostres necessitats. S’ha vist que és complicat escollir ja que el món del aeromodelisme és un món molt gran, hi ha molts productes i molta varietat de components. El més complicat es escollir un que vagi bé i que s’adapti a les nostres necessitats. S’ha de tenir en compte que és un hobby car i si no estàs segur de que el component serà útil, es poden gastar molts diners inútilment. Pot ser que hi hagi un consum massa elevat, una tensió de treball massa petita, un connector diferent i no puguis aprofitar el component. A més s’ha d’adaptar cada component per fer-los compartibles entre ells, tècnicament no és complicat però es requereix temps per localitzar components compatibles i soldar-los.

La verificació dels resultats no és senzilla perquè el fet de tenir connectat el headtracker a l’emissora i al ordinador al mateix temps ha fet difícil manipular els programes d’obtenció de dades. També la coordinació entre les APPs alhora de l’obtenció de dades mitjançant l’APP GPS tracker i la Runtastic, és a dir, estar pendent de 4 mètodes de verificació alhora és bastant estressant alhora de fer el setup i recompilar dades.

Respecte el clima de Flix, on he fet les proves. S’ha vist que és complicat trobar dies amb les condiciones òptimes per fer un vol amb seguretat. Han sigut pocs dies que des del Gener s’han considerat un dia òptim degut a un vent massa fort els altres dies.

Pel que fa a millores per una part es possible millorar aquest projecte si li afegim una brúixola digital o magnetòmetre ja que també tindrem l'orientació respecte als pols magnètics. En un futur m’agradaria dissenyar un sistema que pogués retornar automàticament l’avió al lloc de sortida en cas de pèrdua de comunicació, baix nivell de bateria o un altra condició. Tot això es faria tenint en compte les coordenades GPS i fent ús dels sensors acceleròmetre, giroscopi i magnetòmetre.

Per altra part m’he adonat que hi ha un retràs des de que faig el gir amb el cap fins que es trasllada la informació a l’avió. Per tant es podria millorar el projecte escurçant aquest temps el màxim possible. Una possible solució seria utilitzar un altre hardware amb un microcontrolador i components més potents.

En general estic molt content del resultat, han sigut moltes hores informant-me i buscant per entendre bé les meves necessitat i he aprés molt. Estic satisfet del resultat i la millor sensació és en ple vol quan veig les meves terres des de el cel com si fos un ocell i em sento lliure d’anar allà on vull, és una sensació única.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

61

Referències

https://www.horizonhobby.com/opterra-2m-wing-bnf-basic-p-efl11150.[components]

https://es.gearbest.com.[components] Juny 2017

https://www.banggood.com.[components] Juny 2017

https://rcmadrid.com.[components] Juny 2017

http://www.forodrones.com/threads/tutorial-conceptos-basicos-fpv-p-principiantes-novatos-aprendices.74/.[consells FPV] Juny 2017

http://www.starlino.com/imu_guide.html.[funcionament giroscopi i acceleròmetre]

https://hackaday.io/project/2465-manucon-a-glove-based-controller/log/8254-ppm-output.[funcionament ppm]

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

62

9. Annexes

Aquest apartat inclou els codis utilitzats en aquest projecte. A més, es poden trobar imatges capturades des de l’avió mentre es feia servir el headtracker.

9.1 Codi APP GPS tracker

El codi del programa principal d’aquesta aplicació ha estat desenvoulpat per mi. Aquest llenguatge és d’alt nivell i bastant intuïtiu. De totes formes explicarem com funciona:

1. Inicialització de variables globals 2. Pujem flag start quan prenem el botó START 3. Bucle principal: cada segon llegeix els valors pitch i roll obtinguts del sensor de

posicionament del mòbil i els guarda a Excels separats 4. En el cas de les coordenades GPS sols guarda la informació de la altitud i

longitud quan el valor ha canviat.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

63

Codi 1. Codi APP GPS tracker

9.2 Codi simulació del headtracker

Els següents codis fan referència a la simulació que s’ha utilitzat per fer una demostració virtual del projecte. Aquests codi formen part de llibreries extretes de les següents pàgines web:

Arduino: http://www.mediafire.com/file/8uxwgi21m4sv3v1/i2cdevlib-MPU6050.zip

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

64

Processing: http://www.mediafire.com/file/pe219ag7eanvnk1/Toxiclib.zip

9.2.1 Simulació Arduino

#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

#include "Wire.h"

#endif

#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)

bool blinkState = false;

// MPU control/status vars

bool dmpReady = false; // set true if DMP init was successful

uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU

uint8_t devStatus; // return status after each device operation

(0 = success, !0 = error)

uint16_t packetSize; // expected DMP packet size (default is 42

bytes)

uint16_t fifoCount; // count of all bytes currently in FIFO

uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars

Quaternion q; // [w, x, y, z] quaternion container

VectorInt16 aa; // [x, y, z] accel sensor

measurements

VectorInt16 aaReal; // [x, y, z] gravity-free accel

sensor measurements

VectorInt16 aaWorld; // [x, y, z] world-frame accel

sensor measurements

VectorFloat gravity; // [x, y, z] gravity vector

float euler[3]; // [psi, theta, phi] Euler angle container

float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll

container and gravity vector

// packet structure for InvenSense teapot demo

uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00,

0x00, '\r', '\n' };

// ================================================================

// === INTERRUPT DETECTION ROUTINE ===

// ================================================================

volatile bool mpuInterrupt = false; // indicates whether MPU

interrupt pin has gone high

void dmpDataReady() {

mpuInterrupt = true;

}

// ================================================================

// === INITIAL SETUP ===

// ================================================================

void setup() {

// join I2C bus (I2Cdev library doesn't do this automatically)

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

65

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

Wire.begin();

Wire.setClock(400000); // 400kHz I2C clock. Comment this line

if having compilation difficulties

#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE

Fastwire::setup(400, true);

#endif

// initialize serial communication

// (115200 chosen because it is required for Teapot Demo output,

but it's

// really up to you depending on your project)

Serial.begin(115200);

while (!Serial); // wait for Leonardo enumeration, others continue

immediately

// NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or

Ardunio

// Pro Mini running at 3.3v, cannot handle this baud rate reliably

due to

// the baud timing being too misaligned with processor ticks. You

must use

// 38400 or slower in these cases, or use some kind of external

separate

// crystal solution for the UART timer.

// initialize device

Serial.println(F("Initializing I2C devices..."));

mpu.initialize();

pinMode(INTERRUPT_PIN, INPUT);

// verify connection

Serial.println(F("Testing device connections..."));

Serial.println(mpu.testConnection() ? F("MPU6050 connection

successful") : F("MPU6050 connection failed"));

// wait for ready

Serial.println(F("\nSend any character to begin DMP programming

and demo: "));

while (Serial.available() && Serial.read()); // empty buffer

while (!Serial.available()); // wait for data

while (Serial.available() && Serial.read()); // empty buffer again

// load and configure the DMP

Serial.println(F("Initializing DMP..."));

devStatus = mpu.dmpInitialize();

// supply your own gyro offsets here, scaled for min sensitivity

mpu.setXGyroOffset(220);

mpu.setYGyroOffset(76);

mpu.setZGyroOffset(-85);

mpu.setZAccelOffset(1788); // 1688 factory default for my test

chip

// make sure it worked (returns 0 if so)

if (devStatus == 0) {

// turn on the DMP, now that it's ready

Serial.println(F("Enabling DMP..."));

mpu.setDMPEnabled(true);

// enable Arduino interrupt detection

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

66

Serial.println(F("Enabling interrupt detection (Arduino

external interrupt 0)..."));

attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN),

dmpDataReady, RISING);

mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows

it's okay to use it

Serial.println(F("DMP ready! Waiting for first

interrupt..."));

dmpReady = true;

// get expected DMP packet size for later comparison

packetSize = mpu.dmpGetFIFOPacketSize();

} else {

// ERROR!

// 1 = initial memory load failed

// 2 = DMP configuration updates failed

// (if it's going to break, usually the code will be 1)

Serial.print(F("DMP Initialization failed (code "));

Serial.print(devStatus);

Serial.println(F(")"));

}

// configure LED for output

pinMode(LED_PIN, OUTPUT);

}

// ================================================================

// === MAIN PROGRAM LOOP ===

// ================================================================

void loop() {

// if programming failed, don't try to do anything

if (!dmpReady) return;

// wait for MPU interrupt or extra packet(s) available

while (!mpuInterrupt && fifoCount < packetSize) {

// other program behavior stuff here

// .

// .

// .

// if you are really paranoid you can frequently test in

between other

// stuff to see if mpuInterrupt is true, and if so, "break;"

from the

// while() loop to immediately process the MPU data

// .

// .

// .

}

// reset interrupt flag and get INT_STATUS byte

mpuInterrupt = false;

mpuIntStatus = mpu.getIntStatus();

// get current FIFO count

fifoCount = mpu.getFIFOCount();

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

67

// check for overflow (this should never happen unless our code is

too inefficient)

if ((mpuIntStatus & 0x10) || fifoCount == 1024) {

// reset so we can continue cleanly

mpu.resetFIFO();

Serial.println(F("FIFO overflow!"));

// otherwise, check for DMP data ready interrupt (this should

happen frequently)

} else if (mpuIntStatus & 0x02) {

// wait for correct available data length, should be a VERY

short wait

while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

// read a packet from FIFO

mpu.getFIFOBytes(fifoBuffer, packetSize);

// track FIFO count here in case there is > 1 packet available

// (this lets us immediately read more without waiting for an

interrupt)

fifoCount -= packetSize;

#ifdef OUTPUT_TEAPOT

// display quaternion values in InvenSense Teapot demo

format:

teapotPacket[2] = fifoBuffer[0];

teapotPacket[3] = fifoBuffer[1];

teapotPacket[4] = fifoBuffer[4];

teapotPacket[5] = fifoBuffer[5];

teapotPacket[6] = fifoBuffer[8];

teapotPacket[7] = fifoBuffer[9];

teapotPacket[8] = fifoBuffer[12];

teapotPacket[9] = fifoBuffer[13];

Serial.write(teapotPacket, 14);

teapotPacket[11]++; // packetCount, loops at 0xFF on

purpose

#endif

// blink LED to indicate activity

blinkState = !blinkState;

digitalWrite(LED_PIN, blinkState);

}

}

Codi 2. Codi simulació Arduino

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

68

9.2.2 Simulació Processing

import processing.serial.*;

import processing.opengl.*;

import toxi.geom.*;

import toxi.processing.*;

ToxiclibsSupport gfx;

Serial port; // The serial port

char[] teapotPacket = new char[14]; // InvenSense Teapot packet

int serialCount = 0; // current packet byte position

int synced = 0;

int interval = 0;

float[] q = new float[4];

Quaternion quat = new Quaternion(1, 0, 0, 0);

float[] gravity = new float[3];

float[] euler = new float[3];

float[] ypr = new float[3];

void setup() {

// 300px square viewport using OpenGL rendering

size(300, 300, OPENGL);

gfx = new ToxiclibsSupport(this);

// setup lights and antialiasing

lights();

smooth();

// display serial port list for debugging/clarity

println(Serial.list());

// get the first available port (use EITHER this OR the specific

port code below)

//String portName = Serial.list()[0];

// get a specific serial port (use EITHER this OR the first-

available code above)

String portName = "COM9";

// open the serial port

port = new Serial(this, portName, 115200);

// send single character to trigger DMP init/start

// (expected by MPU6050_DMP6 example Arduino sketch)

port.write('r');

}

void draw() {

if (millis() - interval > 1000) {

// resend single character to trigger DMP init/start

// in case the MPU is halted/reset while applet is running

port.write('r');

interval = millis();

}

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

69

// black background

background(0);

pushMatrix();

translate(width / 2, height / 2);

float[] axis = quat.toAxisAngle();

rotate(axis[0], -axis[1], axis[3], axis[2]);

// draw main body in red

fill(255, 0, 0, 200);

box(10, 10, 200);

// draw front-facing tip in blue

fill(0, 0, 255, 200);

pushMatrix();

translate(0, 0, -120);

rotateX(PI/2);

drawCylinder(0, 20, 20, 8);

popMatrix();

// draw wings and tail fin in green

fill(0, 255, 0, 200);

beginShape(TRIANGLES);

vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30);

vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30);

vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70);

vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70);

endShape();

beginShape(QUADS);

vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80);

vertex( 0, 2, -80);

vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80);

vertex( 0, 2, -80);

vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30);

vertex(100, 2, 30);

vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98);

vertex(-2, -30, 98);

vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70);

vertex(-2, 0, 70);

vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70);

vertex(-2, 0, 70);

endShape();

popMatrix();

}

void serialEvent(Serial port) {

interval = millis();

while (port.available() > 0) {

int ch = port.read();

if (synced == 0 && ch != '$') return;

synced = 1;

print ((char)ch);

if ((serialCount == 1 && ch != 2)

|| (serialCount == 12 && ch != '\r')

|| (serialCount == 13 && ch != '\n')) {

serialCount = 0;

synced = 0;

return;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

70

}

if (serialCount > 0 || ch == '$') {

teapotPacket[serialCount++] = (char)ch;

if (serialCount == 14) {

serialCount = 0; // restart packet byte position

q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16

384.0f;

q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16

384.0f;

q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16

384.0f;

q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16

384.0f;

for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 +

q[i];

quat.set(q[0], q[1], q[2], q[3]);

}

}

}

}

void drawCylinder(float topRadius, float bottomRadius, float tall, int

sides) {

float angle = 0;

float angleIncrement = TWO_PI / sides;

beginShape(QUAD_STRIP);

for (int i = 0; i < sides + 1; ++i) {

vertex(topRadius*cos(angle), 0, topRadius*sin(angle));

vertex(bottomRadius*cos(angle), tall,

bottomRadius*sin(angle));

angle += angleIncrement;

}

endShape();

// If it is not a cone, draw the circular top cap

if (topRadius != 0) {

angle = 0;

beginShape(TRIANGLE_FAN);

vertex(0, 0, 0);

for (int i = 0; i < sides + 1; i++) {

vertex(topRadius * cos(angle), 0, topRadius * sin(angle));

angle += angleIncrement;

}

endShape();

}

if (bottomRadius != 0) {

angle = 0;

beginShape(TRIANGLE_FAN);

// Center point

vertex(0, tall, 0);

for (int i = 0; i < sides + 1; i++) {

vertex(bottomRadius * cos(angle), tall, bottomRadius *

sin(angle));

angle += angleIncrement;

}

endShape();

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

71

}

}

Codi 3. Codi simulació Processing

9.3 Codi del headtracker

En aquest apartat parlarem dels codis utilitzats pel funcionament del headtracker. S’ha de tenir en compte que aquesta part s’ha agafat de la pàgina web: https://code.google.com/archive/p/open-headtracker/. La funció original d’aquest codi era moure una estructura Pan/Tilt amb un càmera incorporada i el que s’ha fet és modificar el codi per moure l’avió.

Per una banda hem adaptat el codi que grabem al micro del Arduino. La funció d’aquest software és agafar dades del sensor i transformar-les amb moviment. A més interactua amb la GUI per configurar alguns paràmetres mitjançant el port COM.

D’altra banda utilitzem el codi per utilitzar una interfície gràfica dissenyada per interactuar amb la placa Arduino. De totes les funcionalitats originals sol s’ha utilitzat la representació gràfica de les dades obtingudes del sensor.

9.3.1 GUI

Pel que fa al codi de la GUI s’ha modificat el panell de control amb Visual Studio 2015. Anteriorment disposava de botons per modificar la posició de la trama la qual s’envia l’informació de cada canal. A més tenía l’opció de configurar paràmetres de 3 canals diferents (Pan ,Tilt, Roll). En aquest projecte no és necessari modificar la posició de cap canal ja que s’ha investigat amb l’oscil·loscopi i s’ha observat que el Tilt és el canal 2 i el Roll és el canal 3. Tampoc ha sigut necessari configurar paràmetres de cap canal ja que les fórmules emprades en tot el procés están ajustades.

#include "stdafx.h"

#include "MainForm.h"

#include "HeadTrackerHardware.h"

#include "CalWizard.h"

using namespace HeadTrackerGUI;

using namespace System::Windows::Forms;

using namespace System;

HTSETTINGS HTSettings;

int serialbyte = 0;

unsigned char linecount = 0;

float SerialData[25];

int Serialindex = 0;

long i = 0;

//--------------------------------------------------------------------

------------------

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

72

// Func: main

// Desc: Called by system at app startup. Program entry point.

//--------------------------------------------------------------------

------------------

[STAThreadAttribute]

int main(array<System::String^>^ args)

{

TrackerWrap::Tracker = gcnew HeadTracker();

// Enabling Windows XP visual effects before any controls are

created

Application::EnableVisualStyles();

Application::SetCompatibleTextRenderingDefault(false);

// Create the main window and run it

Application::Run(gcnew Form1());

return 0;

}

//--------------------------------------------------------------------

------------------

// Func: Form1_Load

// Desc: Form initialization handler

//--------------------------------------------------------------------

------------------

System::Void Form1::Form1_Load(System::Object^ sender,

System::EventArgs^ e)

{

// Disable resizing

//this->FormBorderStyle = ::FormBorderStyle::FixedDialog;

// Serial ports

array<String^>^ ports = TrackerWrap::Tracker->Port-

>GetPortNames();

dd_comport->Items->Clear();

for each(String^ port in ports)

{

dd_comport->Items->Add(port);

}

}

//--------------------------------------------------------------------

------------------

// Func: RetrieveSettings

// Desc: Retrieves the settings from the tracker, and stores them in a

local structure

//--------------------------------------------------------------------

------------------

System::Void Form1::RetrieveSettings()

{

HTSettings = TrackerWrap::Tracker->RetrieveSettings();

}

//--------------------------------------------------------------------

------------------

// Func: UpdateUIFromSettings

// Desc: Updates the UI state with the specified settings

//--------------------------------------------------------------------

------------------

System::Void Form1::UpdateUIFromSettings(HTSETTINGS& Settings)

{

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

73

try

{

textBox_LP_value->Text =

Convert::ToString(Settings.LPTiltRoll, 10);

textBox_LP_valuePan->Text = Convert::ToString(Settings.LPPan,

10);

GyroWeight_tiltRoll->Text =

Convert::ToString(Settings.GyroWeightTiltRoll, 10);

GyroWeight_pan->Text =

Convert::ToString(Settings.GyroWeightPan, 10);

servoGainPan->Text = Convert::ToString(Settings.ServoGainPan,

10);

servoGainTilt->Text =

Convert::ToString(Settings.ServoGainTilt, 10);

servoGainRoll->Text =

Convert::ToString(Settings.ServoGainRoll, 10);

// Channels

inputPanCh->SelectedIndex = Settings.PanCh;

inputTiltCh->SelectedIndex = Settings.TiltCh;

inputRollCh->SelectedIndex = Settings.RollCh;

chk_tilt->Checked = ((Settings.ServoReverse &

HT_TILT_REVERSE_BIT) != 0);

chk_roll->Checked = ((Settings.ServoReverse &

HT_ROLL_REVERSE_BIT) != 0);

chk_pan->Checked = ((Settings.ServoReverse &

HT_PAN_REVERSE_BIT) != 0);

// Pulse values

inputPanCenter->Text = Convert::ToString(Settings.PanCenter,

10);

inputPanTravlMin->Text = Convert::ToString(Settings.PanMin,

10);

inputPanTravlMax->Text = Convert::ToString(Settings.PanMax,

10);

inputTiltCenter->Text = Convert::ToString(Settings.TiltCenter,

10);

inputTiltTravlMin->Text = Convert::ToString(Settings.TiltMin,

10);

inputTiltTravlMax->Text = Convert::ToString(Settings.TiltMax,

10);

inputRollCenter->Text = Convert::ToString(Settings.RollCenter,

10);

inputRollTravlMin->Text = Convert::ToString(Settings.RollMin,

10);

inputRollTravlMax->Text = Convert::ToString(Settings.RollMax,

10);

// Track bars

panGainTrackBar->Value = Settings.ServoGainPan;

tiltGainTrackBar->Value = Settings.ServoGainTilt;

rollGainTrackBar->Value = Settings.ServoGainRoll;

panCenterTrackBar->Value = Settings.PanCenter - 2100;

panMinTrackBar->Value = Settings.PanMin - (Settings.PanCenter

- 2100);

panMaxTrackBar->Value = Settings.PanMax + (Settings.PanCenter

- 2100);

tiltCenterTrackBar->Value = Settings.TiltCenter - 2100;

tiltMinTrackBar->Value = Settings.TiltMin -

(Settings.TiltCenter - 2100);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

74

tiltMaxTrackBar->Value = Settings.TiltMax +

(Settings.TiltCenter - 2100);

rollCenterTrackBar->Value = Settings.RollCenter - 2100;

rollMinTrackBar->Value = Settings.RollMin -

(Settings.RollCenter - 2100);

rollMaxTrackBar->Value = Settings.RollMax +

(Settings.RollCenter - 2100);

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("Error updating UI

from settings.\r\n");

#ifdef DEBUG

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

#endif

}

}

//--------------------------------------------------------------------

------------------

// Func: UpdateSettingsFromUI

// Desc: Updates the specified settings struct with the user-provided

settings from the

// UI.

//--------------------------------------------------------------------

------------------

System::Void Form1::UpdateSettingsFromUI(HTSETTINGS& Settings)

{

Settings.LPTiltRoll = Convert::ToInt32(textBox_LP_value->Text);

Settings.LPPan = Convert::ToInt32(textBox_LP_valuePan->Text);

Settings.GyroWeightTiltRoll =

Convert::ToInt32(GyroWeight_tiltRoll->Text);

Settings.GyroWeightPan = Convert::ToInt32(GyroWeight_pan->Text);

Settings.ServoGainPan = Convert::ToInt32(servoGainPan->Text);

Settings.ServoGainTilt = Convert::ToInt32(servoGainTilt->Text);

Settings.ServoGainRoll = Convert::ToInt32(servoGainRoll->Text);

int temp = 0;

if (chk_tilt->Checked)

temp |= HT_TILT_REVERSE_BIT;

if (chk_roll->Checked)

temp |= HT_ROLL_REVERSE_BIT;

if (chk_pan->Checked)

temp |= HT_PAN_REVERSE_BIT;

Settings.ServoReverse = temp;

Settings.PanCenter = Convert::ToInt32(inputPanCenter->Text);

Settings.PanMin = Convert::ToInt32(inputPanTravlMin->Text);

Settings.PanMax = Convert::ToInt32(inputPanTravlMax->Text);

Settings.TiltCenter = Convert::ToInt32(inputTiltCenter->Text);

Settings.TiltMin = Convert::ToInt32(inputTiltTravlMin->Text);

Settings.TiltMax = Convert::ToInt32(inputTiltTravlMax->Text);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

75

Settings.RollCenter = Convert::ToInt32(inputRollCenter->Text);

Settings.RollMin = Convert::ToInt32(inputRollTravlMin->Text);

Settings.RollMax = Convert::ToInt32(inputRollTravlMax->Text);

Settings.PanCh = Convert::ToByte(inputPanCh->Text);

Settings.TiltCh = Convert::ToByte(inputTiltCh->Text);

Settings.RollCh = Convert::ToByte(inputRollCh->Text);

}

//--------------------------------------------------------------------

------------------

// Func: btn_connect_Click

// Desc: Event handler for hardware connection button.

//--------------------------------------------------------------------

------------------

System::Void Form1::btn_connect_Click(System::Object^ sender,

System::EventArgs^ e)

{

btn_connect->Enabled = false;

TrackerWrap::Tracker->Open(dd_comport->Text, true);

if (TrackerWrap::Tracker->Port->IsOpen)

{

// Start reading from the port

timer1->Enabled = true;

// Stop any streaming, in case something failed last time

TrackerWrap::Tracker->StreamTrackingData(false);

// Set up controls

stop_HT->Enabled = true;

start_HT->Enabled = true;

btn_update_headtracker->Enabled = true;

btnCalibrate->Enabled = true;

btn_disconnect->Enabled = true;

calibrationWizardToolStripMenuItem->Enabled = true;

calibrationWizardRotToolStripMenuItem->Enabled = true;

btnSendManualCmd->Enabled = true;

RetrieveSettings();

UpdateUIFromSettings(HTSettings);

float f = TrackerWrap::Tracker->Version;

Serial_output_box->Text += String::Format("Firmware Version

{0}\r\n", f);

comPortTimer->Enabled = false;

}

else

{

btn_connect->Enabled = true;

Serial_output_box->Text += String::Format("Hardware not found!

Double check the COM port and ensure you have loaded the proper

firmware.\r\n");

}

}

//--------------------------------------------------------------------

------------------

// Func: btn_disconnect_Click

// Desc: Hardware disconnection button press handler

//--------------------------------------------------------------------

------------------

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

76

System::Void Form1::btn_disconnect_Click(System::Object^ sender,

System::EventArgs^ e)

{

if ( TrackerWrap::Tracker->Port->IsOpen )

{

// Tell hardware to stop streaming (to be nice during next

connection)

TrackerWrap::Tracker->StreamTrackingData(false);

TrackerWrap::Tracker->Close();

timer1->Enabled = false;

}

btn_connect->Enabled = true;

stop_HT->Enabled = false;

start_HT->Enabled = false;

btn_update_headtracker->Enabled = false;

btnCalibrate->Enabled = false;

btn_disconnect->Enabled = false;

comPortTimer->Enabled = true;

calibrationWizardToolStripMenuItem->Enabled = false;

calibrationWizardRotToolStripMenuItem->Enabled = false;

btnSendManualCmd->Enabled = false;

}

//--------------------------------------------------------------------

------------------

// Func: timer1_Tick

// Desc: A window timer is used to update the UI every n milliseconds.

Here's where the

// work is done to capture serial data from the hardware and

update the UI with

// the data.

//--------------------------------------------------------------------

------------------

System::Void Form1::timer1_Tick(System::Object^ sender,

System::EventArgs^ e)

{

if (TrackerWrap::Tracker->Port->IsOpen && !_CalWizard->Visible)

{

while(TrackerWrap::Tracker->Port->BytesToRead > 0)

{

serialbyte = (TrackerWrap::Tracker->Port->ReadChar());

Serial_output_box->Text += Convert::ToChar((serialbyte));

if (serialbyte == 13)

{

linecount++;

if (linecount > 12)

{

Serial_output_box->Clear();

linecount = 0;

}

}

if (TrackerWrap::Tracker->TrackStreaming)

{

if (serialbyte == 13)

{

i++;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

77

if (i == 1)

{

chart1->ChartAreas["ChartArea1"]->BackColor =

System::Drawing::Color::WhiteSmoke;

}

chart1->Series["Tilt"]->Points->AddXY(i,

SerialData[0] / 100 - 90);

chart1->Series["Roll"]->Points->AddXY(i,

SerialData[1] / 100 - 90);

chart1->Series["Pan"]->Points->AddXY(i,

SerialData[2] / 100 - 180);

SerialData[0] = 0;

SerialData[1] = 0;

SerialData[2] = 0;

Serialindex = 0;

}

else if (serialbyte == 44)

{

Serialindex++;

}

else if (serialbyte > 47 && serialbyte < 58)

{

SerialData[Serialindex] = SerialData[Serialindex]

* 10 + (serialbyte - 48);

}

}

}

}

}

//--------------------------------------------------------------------

------------------

// Func: comPortTimer_Tick

// Desc: Enumerates available serial ports. This timer fires every few

seconds, just

// in case the user plugs in the device after starting the app.

//--------------------------------------------------------------------

------------------

System::Void Form1::comPortTimer_Tick(System::Object^ sender,

System::EventArgs^ e)

{

Object^ curPort = dd_comport->SelectedItem;

array<String^>^ ports = TrackerWrap::Tracker->Port-

>GetPortNames();

dd_comport->Items->Clear();

for each(String^ port in ports)

{

dd_comport->Items->Add(port);

}

dd_comport->SelectedItem = curPort;

dd_comport->SelectionLength = 4;

}

//--------------------------------------------------------------------

------------------

// Func: start_HT_Click

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

78

// Desc: Plot start button handler. Sends message to hardware to

stream data.

//--------------------------------------------------------------------

------------------

System::Void Form1::start_HT_Click(System::Object^ sender,

System::EventArgs^ e)

{

if ( TrackerWrap::Tracker->Port->IsOpen )

TrackerWrap::Tracker->StreamTrackingData(true);

}

//--------------------------------------------------------------------

------------------

// Func: clear_plot_Click

// Desc: Clear plot button handler. Clears the series in the plots.

//--------------------------------------------------------------------

------------------

System::Void Form1::clear_plot_Click(System::Object^ sender,

System::EventArgs^ e)

{

chart1->Series["Tilt"]->Points->Clear();

chart1->Series["Roll"]->Points->Clear();

chart1->Series["Pan"]->Points->Clear();

i=0;

chart1->ChartAreas["ChartArea1"]->BackColor =

System::Drawing::Color::Transparent;

}

//--------------------------------------------------------------------

------------------

// Func: btn_update_headtracker_Click

// Desc: Sends settings to head tracker for storage

//--------------------------------------------------------------------

------------------

System::Void Form1::btn_update_headtracker_Click(System::Object^

sender, System::EventArgs^ e)

{

if (TrackerWrap::Tracker->Port->IsOpen)

{

HTSETTINGS settings;

UpdateSettingsFromUI(settings);

TrackerWrap::Tracker->Port-

>WriteLine(String::Format("${0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{1

0},{11},{12},{13},{14},{15},{16},{17},{18},{19}HE",

settings.LPTiltRoll, settings.LPPan, // 0 , 1

settings.GyroWeightTiltRoll,settings.GyroWeightPan, // 2,

3

settings.ServoGainTilt, settings.ServoGainPan,

settings.ServoGainRoll, // 4, 5, 6

settings.ServoReverse, // 7

settings.PanCenter,settings.PanMin,settings.PanMax, // 8,

9, 10

settings.TiltCenter,settings.TiltMin,settings.TiltMax, //

11, 12, 13

settings.RollCenter,settings.RollMin,settings.RollMax, //

14, 15, 16

settings.PanCh,settings.TiltCh,settings.RollCh) ); // 17,

18 19

}

}

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

79

//--------------------------------------------------------------------

------------------

// Func: stop_HT_Click

// Desc: Plot stop button handler. Sends request to hardware to cease

data streaming.

//--------------------------------------------------------------------

------------------

System::Void Form1::stop_HT_Click(System::Object^ sender,

System::EventArgs^ e)

{

if ( TrackerWrap::Tracker->Port->IsOpen )

TrackerWrap::Tracker->StreamTrackingData(false);

}

//--------------------------------------------------------------------

------------------

// Func: btnCalibrate_Click

// Desc: Calibrate button click handler. Does the same thing as the

menu entry.

//--------------------------------------------------------------------

------------------

System::Void Form1::btnCalibrate_Click(System::Object^ sender,

System::EventArgs^ e)

{

Form1::OnCalWizardRot_Menu(sender, e);

}

//--------------------------------------------------------------------

------------------

// Func: exitToolStripMenuItem_Click

// Desc: File->exit menu handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::exitToolStripMenuItem_Click(System::Object^

sender, System::EventArgs^ e)

{

Application::Exit();

}

//--------------------------------------------------------------------

------------------

// Func: aboutToolStripMenuItem_Click

// Desc: Help->About menu handler

//--------------------------------------------------------------------

------------------

System::Void Form1::aboutToolStripMenuItem_Click(System::Object^

sender, System::EventArgs^ e)

{

MessageBox::Show("DIY headtracker project\n - Written by Dennis

Frie 2012\n - Augmented by Mark Mansur 2013");

}

//--------------------------------------------------------------------

------------------

// Func: SendManualCmd_OnClick

// Desc:

//--------------------------------------------------------------------

------------------

System::Void Form1::btnSendManualCmd_Click(System::Object^ sender,

System::EventArgs^ e)

{

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

80

System::String^ line = ManualCmdEdit->Text;

if ( TrackerWrap::Tracker->Port->IsOpen )

{

TrackerWrap::Tracker->Port->DiscardInBuffer();

TrackerWrap::Tracker->Port->WriteLine(line);

}

}

//--------------------------------------------------------------------

------------------

// Func: ManualCmdEdit_OnFocusEnter

// Desc: Called when the control gains focus. Highlights existing

text.

//--------------------------------------------------------------------

------------------

System::Void Form1::ManualCmdEdit_OnFocusEnter(System::Object^

sender, System::EventArgs^ e)

{

ManualCmdEdit->SelectAll();

}

//--------------------------------------------------------------------

------------------

// Func: ManualCmdEdit_OnKeyDown

// Desc: Captures enter key down, to send the command.

//--------------------------------------------------------------------

------------------

System::Void Form1::ManualCmdEdit_OnKeyDown(System::Object^ sender,

System::Windows::Forms::KeyEventArgs^ e)

{

if ( e->KeyCode == Keys::Enter )

btnSendManualCmd_Click(sender, e);

}

//--------------------------------------------------------------------

------------------

// Func: PanCenterTrackBar_ValueChanged

// Desc: Pan center trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanCenterTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(panCenterTrackBar->Value);

inputPanCenter->Text = Convert::ToString(2100 + panCenterTrackBar-

>Value);

int temp = panMinTrackBar->Value + panCenterTrackBar->Value;

if (temp >= 0)

inputPanTravlMin->Text = Convert::ToString(temp);

temp = panMaxTrackBar->Value - panCenterTrackBar->Value;

if (temp >= 0)

inputPanTravlMax->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: PanMinTrackBar_ValueChanged

// Desc: Pan min extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

81

System::Void Form1::PanMinTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(panMinTrackBar->Value);

inputPanCenter->Text = Convert::ToString(2100 + panCenterTrackBar-

>Value);

int temp = panMinTrackBar->Value + panCenterTrackBar->Value;

if (temp >= 0)

inputPanTravlMin->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: PanMaxTrackBar_ValueChanged

// Desc: Pan max extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanMaxTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(panMaxTrackBar->Value);

inputPanCenter->Text = Convert::ToString(2100 + panCenterTrackBar-

>Value);

int temp = panMaxTrackBar->Value - panCenterTrackBar->Value;

if (temp >= 0)

inputPanTravlMax->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: TiltCenterTrackBar_ValueChanged

// Desc: Tilt center trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::TiltCenterTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(tiltCenterTrackBar-

>Value);

inputTiltCenter->Text = Convert::ToString(2100 +

tiltCenterTrackBar->Value);

int temp = tiltMinTrackBar->Value + tiltCenterTrackBar->Value;

if (temp >= 0)

inputTiltTravlMin->Text = Convert::ToString(temp);

temp = tiltMaxTrackBar->Value - tiltCenterTrackBar->Value;

if (temp >= 0)

inputTiltTravlMax->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: TiltMinTrackBar_ValueChanged

// Desc: Tilt min extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::TiltMinTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(tiltMinTrackBar->Value);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

82

inputTiltCenter->Text = Convert::ToString(2100 +

tiltCenterTrackBar->Value);

int temp = tiltMinTrackBar->Value + tiltCenterTrackBar->Value;

if (temp >= 0)

inputTiltTravlMin->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: TiltMaxTrackBar_ValueChanged

// Desc: Tilt max extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::TiltMaxTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(tiltMaxTrackBar->Value);

inputTiltCenter->Text = Convert::ToString(2100 +

tiltCenterTrackBar->Value);

int temp = tiltMaxTrackBar->Value - tiltCenterTrackBar->Value;

if (temp >= 0)

inputTiltTravlMax->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: RollCenterTrackBar_ValueChanged

// Desc: Roll center trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::RollCenterTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(rollCenterTrackBar-

>Value);

inputRollCenter->Text = Convert::ToString(2100 +

rollCenterTrackBar->Value);

int temp = rollMinTrackBar->Value + rollCenterTrackBar->Value;

if (temp >= 0)

inputRollTravlMin->Text = Convert::ToString(temp);

temp = rollMaxTrackBar->Value - rollCenterTrackBar->Value;

if (temp >= 0)

inputRollTravlMax->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: RollMinTrackBar_ValueChanged

// Desc: Roll min extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::RollMinTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(rollMinTrackBar->Value);

inputRollCenter->Text = Convert::ToString(2100 +

rollCenterTrackBar->Value);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

83

int temp = rollMinTrackBar->Value + rollCenterTrackBar->Value;

if (temp >= 0)

inputRollTravlMin->Text = Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: RollMaxTrackBar_ValueChanged

// Desc: Roll max extreme trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::RollMaxTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(rollMaxTrackBar->Value);

inputRollCenter->Text = Convert::ToString(2100 +

rollCenterTrackBar->Value);

int temp = rollMaxTrackBar->Value - rollCenterTrackBar->Value;

if (temp >= 0)

inputRollTravlMax->Text =Convert::ToString(temp);

}

//--------------------------------------------------------------------

------------------

// Func: PanGainTrackBar_ValueChanged

// Desc: Pan gain trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanGainTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(panGainTrackBar->Value);

servoGainPan->Text = Convert::ToString(panGainTrackBar->Value);

}

//--------------------------------------------------------------------

------------------

// Func: TiltGainTrackBar_ValueChanged

// Desc: Tilt gain trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::TiltGainTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(tiltGainTrackBar->Value);

servoGainTilt->Text = Convert::ToString(tiltGainTrackBar->Value);

}

//--------------------------------------------------------------------

------------------

// Func: RollGainTrackBar_ValueChanged

// Desc: Roll gain trackbar value change handler.

//--------------------------------------------------------------------

------------------

System::Void Form1::RollGainTrackBar_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

lblShowOutput->Text = Convert::ToString(rollGainTrackBar->Value);

servoGainRoll->Text = Convert::ToString(rollGainTrackBar->Value);

}

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

84

//--------------------------------------------------------------------

------------------

// Func: PanMinTravelEdit_ValueChanged

// Desc: User text input handler for pan min travel edit control.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanMinTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputPanTravlMin->Modified )

{

try

{

panMinTrackBar->Value = Convert::ToInt32(inputPanTravlMin-

>Text, 10);

inputPanTravlMin->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

pan min trackbar.\r\n");

#ifdef DEBUG

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

#endif

}

}

}

//--------------------------------------------------------------------

------------------

// Func: PanMaxTravelEdit_ValueChanged

// Desc: User text input handler for pan max travel edit control.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanMaxTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputPanTravlMax->Modified )

{

try

{

panMaxTrackBar->Value = Convert::ToInt32(inputPanTravlMax-

>Text, 10);

inputPanTravlMax->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

pan max trackbar.\r\n");

#ifdef DEBUG

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

#endif

}

}

}

//--------------------------------------------------------------------

------------------

// Func: PanCenterEdit_ValueChanged

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

85

// Desc: User text input handler for pan center edit control.

//--------------------------------------------------------------------

------------------

System::Void Form1::PanCenterEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputPanCenter->Modified)

{

try

{

panCenterTrackBar->Value =

Convert::ToInt32(inputPanCenter->Text, 10) - 2100;

int temp = panMinTrackBar->Value + panCenterTrackBar-

>Value;

if (temp >= 0)

inputPanTravlMin->Text = Convert::ToString(temp);

temp = panMaxTrackBar->Value - panCenterTrackBar->Value;

if (temp >= 0)

inputPanTravlMax->Text = Convert::ToString(temp);

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

pan trackbars.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

inputPanCenter->Modified = false;

}

}

System::Void Form1::TiltMinTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputTiltTravlMin->Modified )

{

try

{

tiltMinTrackBar->Value =

Convert::ToInt32(inputTiltTravlMin->Text, 10);

inputTiltTravlMin->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

tilt min trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

System::Void Form1::TiltMaxTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputTiltTravlMax->Modified )

{

try

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

86

{

tiltMaxTrackBar->Value =

Convert::ToInt32(inputTiltTravlMax->Text, 10);

inputTiltTravlMax->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

tilt max trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

System::Void Form1::TiltCenterEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputTiltCenter->Modified)

{

try

{

tiltCenterTrackBar->Value =

Convert::ToInt32(inputTiltCenter->Text, 10) - 2100;

int temp = tiltMinTrackBar->Value + tiltCenterTrackBar-

>Value;

if (temp >= 0)

inputTiltTravlMin->Text = Convert::ToString(temp);

temp = tiltMaxTrackBar->Value - tiltCenterTrackBar->Value;

if (temp >= 0)

inputTiltTravlMax->Text = Convert::ToString(temp);

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

tilt trackbars.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

inputTiltCenter->Modified = false;

}

}

System::Void Form1::RollMinTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputRollTravlMin->Modified )

{

try

{

rollMinTrackBar->Value =

Convert::ToInt32(inputRollTravlMin->Text, 10);

inputRollTravlMin->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

roll min trackbar.\r\n");

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

87

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

System::Void Form1::RollMaxTravelEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputRollTravlMax->Modified )

{

try

{

rollMaxTrackBar->Value =

Convert::ToInt32(inputRollTravlMax->Text, 10);

inputRollTravlMax->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

roll max trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

System::Void Form1::RollCenterEdit_ValueChanged(System::Object^

sender, System::EventArgs^ e)

{

if ( inputRollCenter->Modified)

{

try

{

rollCenterTrackBar->Value =

Convert::ToInt32(inputRollCenter->Text, 10) - 2100;

int temp = rollMinTrackBar->Value + rollCenterTrackBar-

>Value;

if (temp >= 0)

inputRollTravlMin->Text = Convert::ToString(temp);

temp = rollMaxTrackBar->Value - rollCenterTrackBar->Value;

if (temp >= 0)

inputRollTravlMax->Text = Convert::ToString(temp);

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

roll trackbars.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

inputRollCenter->Modified = false;

}

}

System::Void Form1::TiltGainEdit_ValueChanged(System::Object^ sender,

System::EventArgs^ e)

{

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

88

if ( servoGainTilt->Modified )

{

try

{

rollGainTrackBar->Value = Convert::ToInt32(servoGainTilt-

>Text, 10);

servoGainTilt->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

tilt gain trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

//--------------------------------------------------------------------

------------------

// Func: PanGainEdit_ValueChanged

// Desc: Handler for user entry of text into edit control

//--------------------------------------------------------------------

------------------

System::Void Form1::PanGainEdit_ValueChanged(System::Object^ sender,

System::EventArgs^ e)

{

if ( servoGainPan->Modified )

{

try

{

panGainTrackBar->Value = Convert::ToInt32(servoGainPan-

>Text, 10);

servoGainPan->Modified = false;

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

pan gain trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

//--------------------------------------------------------------------

------------------

// Func: RollGainEdit_ValueChanged

// Desc: Handler for user entry of text into edit control

//--------------------------------------------------------------------

------------------

System::Void Form1::RollGainEdit_ValueChanged(System::Object^ sender,

System::EventArgs^ e)

{

if ( servoGainRoll->Modified )

{

try

{

rollGainTrackBar->Value = Convert::ToInt32(servoGainRoll-

>Text, 10);

servoGainRoll->Modified = false;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

89

}

catch (System::Exception^ e)

{

Serial_output_box->Text += String::Format("ERROR updating

roll gain trackbar.\r\n");

Serial_output_box->Text += e->Message;

Serial_output_box->Text += String::Format("\r\n");

}

}

}

//--------------------------------------------------------------------

------------------

// Func: OnCalWizard_Menu

// Desc: Menu click handler

//--------------------------------------------------------------------

------------------

System::Void Form1::OnCalWizard_Menu(System::Object^ sender,

System::EventArgs^ e)

{

_CalWizard = gcnew CalWizard;

_CalWizard->Begin(AXISALIGNMENT);

_CalWizard->Show();

}

//--------------------------------------------------------------------

------------------

// Func: OnCalWizardRot_Menu

// Desc: Menu click handler

//--------------------------------------------------------------------

------------------

System::Void Form1::OnCalWizardRot_Menu(System::Object^ sender,

System::EventArgs^ e)

{

_CalWizard = gcnew CalWizard;

_CalWizard->Begin(MINMAXTRACKING);

_CalWizard->Show();

}

//--------------------------------------------------------------------

------------------

// Func: OnExportSettingsToFile_Menu

// Desc: Exports settings from the UI to a file.

// Settings to export:

/*

int LPTiltRoll; // Firmware: tiltRollBeta

int LPPan; // Firmware: panBeta

int GyroWeightTiltRoll; // Firmware: gyroWeightTiltRoll

int GyroWeightPan; // Firmware: gyroWeightPan

int ServoGainPan; // Firmware: tiltFactor

int ServoGainTilt; // Firmware: panFactor

int ServoGainRoll; // Firmware: rollFactor

Byte ServoReverse; // Firmware: servoReverseMask

int PanCenter; // Firmware: servoPanCenter

int PanMin; // Firmware: panMinPulse

int PanMax; // Firmware: panMaxPulse

int TiltCenter; // Firmware: servoTiltCenter

int TiltMin; // Firmware: tiltMinPulse

int TiltMax; // Firmware: tiltMaxPulse

int RollCenter; // Firmware: servoRollCenter

int RollMin; // Firmware: rollMinPulse

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

90

int RollMax; // Firmware: rollMaxPulse

Byte PanCh; // Firmware: htChannels[0]

Byte TiltCh; // Firmware: htChannels[1]

Byte RollCh; // Firmware: htChannels[2]

*/

//--------------------------------------------------------------------

------------------

System::Void Form1::OnExportSettingsToFile_Menu(System::Object^

sender, System::EventArgs^ e)

{

String^ fileName = "textfile.txt";

SaveFileDialog^ saveFileDialog = gcnew SaveFileDialog;

saveFileDialog->InitialDirectory = "";

saveFileDialog->Filter = "txt files (*.txt)|*.txt|All files

(*.*)|*.*";

saveFileDialog->FilterIndex = 1;

saveFileDialog->RestoreDirectory = true;

if ( saveFileDialog->ShowDialog() ==

System::Windows::Forms::DialogResult::OK )

{

try

{

HTSETTINGS settings;

UpdateSettingsFromUI(settings);

System::IO::StreamWriter^ sw = gcnew

System::IO::StreamWriter(saveFileDialog->FileName);

float f = TrackerWrap::Tracker->Version;

sw->WriteLine("{0} : FW Version", f);

sw->WriteLine("{0} : LPTiltRoll", settings.LPTiltRoll);

sw->WriteLine("{0} : LPPan", settings.LPPan);

sw->WriteLine("{0} : GyroWeightTiltRoll",

settings.GyroWeightTiltRoll);

sw->WriteLine("{0} : GyroWeightPan",

settings.GyroWeightPan);

sw->WriteLine("{0} : ServoGainPan",

settings.ServoGainPan);

sw->WriteLine("{0} : ServoGainTilt",

settings.ServoGainTilt);

sw->WriteLine("{0} : ServoGainRoll",

settings.ServoGainRoll);

sw->WriteLine("{0} : ServoReverseMask",

settings.ServoReverse);

sw->WriteLine("{0} : PanCenter", settings.PanCenter);

sw->WriteLine("{0} : PanMin", settings.PanMin);

sw->WriteLine("{0} : PanMax", settings.PanMax);

sw->WriteLine("{0} : TiltCenter", settings.TiltCenter);

sw->WriteLine("{0} : TiltMin", settings.TiltMin);

sw->WriteLine("{0} : TiltMax", settings.TiltMax);

sw->WriteLine("{0} : RollCenter", settings.RollCenter);

sw->WriteLine("{0} : RollMin", settings.RollMin);

sw->WriteLine("{0} : RollMax", settings.RollMax);

sw->WriteLine("{0} : PanCh", settings.PanCh);

sw->WriteLine("{0} : TiltCh", settings.TiltCh);

sw->WriteLine("{0} : RollCh", settings.RollCh);

sw->Close();

}

catch (Exception^ e)

{

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

91

}

}

}

//--------------------------------------------------------------------

------------------

// Func: OnImportSettingsFromFile_Menu

// Desc: Imports tracker settings from a file into the UI.

//--------------------------------------------------------------------

------------------

System::Void Form1::OnImportSettingsFromFile_Menu(System::Object^

sender, System::EventArgs^ e)

{

String^ fileName = "textfile.txt";

OpenFileDialog^ openFileDialog = gcnew OpenFileDialog;

HTSETTINGS settings;

openFileDialog->InitialDirectory = "";

openFileDialog->Filter = "txt files (*.txt)|*.txt|All files

(*.*)|*.*";

openFileDialog->FilterIndex = 1;

openFileDialog->RestoreDirectory = true;

if ( openFileDialog->ShowDialog() ==

System::Windows::Forms::DialogResult::OK )

{

try

{

System::IO::StreamReader^ din =

System::IO::File::OpenText(openFileDialog->FileName);

String^ str;

int count = 0;

float fw = 0.0;

while ((str = din->ReadLine()) != nullptr)

{

array<wchar_t>^ delim = {' '};

array<String^>^ items = str->Split(delim);

System::Globalization::CultureInfo^ ci = gcnew

System::Globalization::CultureInfo("en-US");

System::Globalization::NumberFormatInfo^ fi = ci-

>NumberFormat;

fi->NumberDecimalSeparator = ".";

switch (count)

{

// Check firmware version

case 0: fw = Convert::ToSingle(items[0], fi); break;

case 1: settings.LPTiltRoll =

Convert::ToInt32(items[0]); break;

case 2: settings.LPPan = Convert::ToInt32(items[0]);

break;

case 3: settings.GyroWeightTiltRoll =

Convert::ToInt32(items[0]); break;

case 4: settings.GyroWeightPan =

Convert::ToInt32(items[0]); break;

case 5: settings.ServoGainPan =

Convert::ToInt32(items[0]); break;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

92

case 6: settings.ServoGainTilt =

Convert::ToInt32(items[0]); break;

case 7: settings.ServoGainRoll =

Convert::ToInt32(items[0]); break;

case 8: settings.ServoReverse =

Convert::ToInt32(items[0]); break;

case 9: settings.PanCenter =

Convert::ToInt32(items[0]); break;

case 10: settings.PanMin = Convert::ToInt32(items[0]);

break;

case 11: settings.PanMax = Convert::ToInt32(items[0]);

break;

case 12: settings.TiltCenter =

Convert::ToInt32(items[0]); break;

case 13: settings.TiltMin= Convert::ToInt32(items[0]);

break;

case 14: settings.TiltMax =

Convert::ToInt32(items[0]); break;

case 15: settings.RollCenter =

Convert::ToInt32(items[0]); break;

case 16: settings.RollMin =

Convert::ToInt32(items[0]); break;

case 17: settings.RollMax =

Convert::ToInt32(items[0]); break;

case 18: settings.PanCh = Convert::ToByte(items[0]);

break;

case 19: settings.TiltCh = Convert::ToByte(items[0]);

break;

case 20: settings.RollCh = Convert::ToByte(items[0]);

break;

}

count++;

}

UpdateUIFromSettings(settings);

Serial_output_box->Text += String::Format("Settings

successfully loaded\r\n");

}

catch (Exception^ e)

{

if (dynamic_cast<System::IO::FileNotFoundException^>(e))

{

Serial_output_box->Text += String::Format("File not

found!\r\n");

}

else

{

Serial_output_box->Text += String::Format("File

error!\r\n");

}

}

}

}

Codi 4. Codi GUI

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

93

9.3.2 Arduino

A continuació tenim el firmware que s’ha grabat al micro. La funció principal d’aquest codi és obtenir i tranformar els valors obtinguts pel sensor per realitzar el moviment. Un altra funció important és la interacció amb la GUI mitjançant comandes. Aquest projecte consta de 3 fitxers i a continuació explicarem la seva funció i quins canvis hem realitzar de cada part:

1. Main: Executa el bucle principal del programa i gestiona la comunicació de la placa amb la GUI. En primer lloc s’ha eliminat la part de comunicació del Pan amb la GUI. També s’ha deshabiliat la interacció dels botons de configuració de paràmetres de cada canal.

2. Sensors: Inicialitza el sensor, mesura i transforma el valor que s’obté del sensor. Anteriorment s’utilitzava un magnetòmetre i s’ha deshabilitat ja que no era útil. Les equacions utilitzades per transformar el valor del sensor s’han modificat per normalitzar els valors.

3. Configuration: Configura els registres dels Timers 0 i 1 que fan saltar interrupcions per llegir els sensors i per construir la trama PPM. En aquest part hi havia funcions que permetien llegir a més de construir una trama PPM per tant s’ha eliminat les funciones ja que nosaltres no utilitzavem aquesta funcionalitat.

10.2.2.1 Main

#include <Wire.h>

#include "config.h"

#include "functions.h"

#include "sensors.h"

#include <EEPROM.h>

// Local file variables

//

int frameNumber = 0; // Frame count since last debug

serial output

char serial_data[101]; // Array for serial-data

unsigned char serial_index = 0; // How many bytes have been received?

char string_started = 0; // Only saves data if string starts

with right byte

unsigned char channel_mapping[13];

char outputAcc = 0; // Stream accelerometer data to host

char outputTrack = 0; // Stream angle data to host

// Keep track of button press

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

94

char lastButtonState = 0; // 0 is not pressed, 1 is pressed

unsigned long buttonDownTime = 0; // the system time of the press

char pauseToggled = 0; // Used to make sure we toggle

pause only once per hold

char ht_paused = 0;

// External variables (defined in other files)

//

extern unsigned char PpmIn_PpmOut[13];

extern char read_sensors;

extern char resetValues;

extern char tiltInverse;

extern char rollInverse;

// Settings (Defined in sensors.cpp)

//

extern float tiltRollBeta;

extern float gyroWeightTiltRoll;

extern unsigned char htChannels[];

// End settings

//--------------------------------------------------------------------

------------------

// Func: setup

// Desc: Called by Arduino framework at initialization time. This sets

up pins for I/O,

// initializes sensors, etc.

//--------------------------------------------------------------------

------------------

void setup()

{

Serial.begin(SERIAL_BAUD);

pinMode(9,OUTPUT);

digitalWrite(2,HIGH);

digitalWrite(3,HIGH);

// Set all other pins to input, for safety.

pinMode(0,INPUT);

pinMode(1,INPUT);

pinMode(2,INPUT);

pinMode(3,INPUT);

pinMode(6,INPUT);

pinMode(7,INPUT);

pinMode(8,INPUT);

// Set button pin to input:

pinMode(BUTTON_INPUT,INPUT);

// Set internal pull-up resistor.

digitalWrite(BUTTON_INPUT,HIGH);

digitalWrite(0,LOW); // pull-down resistor

digitalWrite(1,LOW);

digitalWrite(2,HIGH);

digitalWrite(3,HIGH);

pinMode(ARDUINO_LED,OUTPUT); // Arduino LED

digitalWrite(ARDUINO_LED, HIGH);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

95

// Give it time to be noticed, then turn it off

delay(200); // Note: only use delay here. This won't work when

Timer0 is repurposed later.

digitalWrite(ARDUINO_LED, LOW);

InitPWMInterrupt(); // Start PWM interrupt

Wire.begin(); // Start I2C

// If the device have just been programmed, write initial

config/values to EEPROM:

if (EEPROM.read(0) != 8)

{

//#if (DEBUG)

Serial.println("New board - saving default values!");

//#endif

InitSensors();

SaveSettings();

SaveAccelData();

}

GetSettings(); // Get settings saved in EEPROM

InitSensors(); // Initialize I2C sensors

ResetCenter();

InitTimerInterrupt(); // Start timer interrupt (for

sensors)

}

//--------------------------------------------------------------------

------------------

// Func: loop

// Desc: Called by the Arduino framework once per frame. Represents

main program loop.

//--------------------------------------------------------------------

------------------

void loop()

{

// Check input button for reset/pause request

char buttonPressed = (digitalRead(BUTTON_INPUT) == 0);

if ( buttonPressed && lastButtonState == 0)

{

resetValues = 1;

buttonDownTime = 0;

lastButtonState = 1;

}

if ( buttonPressed )

{

if ( !pauseToggled && (buttonDownTime >

BUTTON_HOLD_PAUSE_THRESH) )

{

// Pause/unpause

ht_paused = !ht_paused;

resetValues = 1;

pauseToggled = 1;

}

}

else

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

96

{

pauseToggled = 0;

lastButtonState = 0;

}

// All this is used for communication with GUI

//

if (Serial.available())

{

if (string_started == 1)

{

// Read incoming byte

serial_data[serial_index++] = Serial.read();

// If string ends with "CH" it's channel configuration,

that have been received.

// String must always be 12 chars/bytes and ending with CH

to be valid.

if (serial_index == 14 &&

serial_data[serial_index-2] == 'C' &&

serial_data[serial_index-1] == 'H' )

{

// To keep it simple, we will not let the channels be

0-initialized, but

// start from 1 to match actual channels.

for (unsigned char i = 0; i < 13; i++)

{

channel_mapping[i + 1] = serial_data[i] - 48;

// Update the dedicated PPM-in -> PPM-out array

for faster performance.

if ((serial_data[i] - 48) < 14)

{

PpmIn_PpmOut[serial_data[i]-48] = i + 1;

}

}

// Reset serial_index and serial_started

serial_index = 0;

string_started = 0;

}

// Configure headtracker

else if (serial_data[serial_index-2] == 'H' &&

serial_data[serial_index-1] == 'E')

{

int valuesReceived[20] =

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

int comma_index = 0;

for (unsigned char k = 0; k < serial_index - 2; k++)

{

// Looking for comma

if (serial_data[k] == 44)

{

comma_index++;

}

else

{

valuesReceived[comma_index] =

valuesReceived[comma_index] * 10 + (serial_data[k] - 48);

}

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

97

serial_index = 0;

string_started = 0;

} // end configure headtracker

// Start accelerometer data stream

else if (serial_data[serial_index-4] == 'G' &&

serial_data[serial_index-3] == 'R' &&

serial_data[serial_index-2] == 'A' &&

serial_data[serial_index-1] == 'V')

{

outputAcc = 1;

outputMagAcc = 0;

outputMag = 0;

outputTrack = 0;

serial_index = 0;

string_started = 0;

}

// Stop accelerometer data stream

else if (serial_data[serial_index-4] == 'G' &&

serial_data[serial_index-3] == 'R' &&

serial_data[serial_index-2] == 'E' &&

serial_data[serial_index-1] == 'N')

{

outputAcc = 0;

outputMag = 0;

outputMagAcc = 0;

outputTrack = 0;

serial_index = 0;

string_started = 0;

}

// Start tracking data stream

else if (serial_data[serial_index-4] == 'P' &&

serial_data[serial_index-3] == 'L' &&

serial_data[serial_index-2] == 'S' &&

serial_data[serial_index-1] == 'T')

{

outputTrack = 1;

outputAcc = 0;

serial_index = 0;

string_started = 0;

}

// Stop tracking data stream

else if (serial_data[serial_index-4] == 'P' &&

serial_data[serial_index-3] == 'L' &&

serial_data[serial_index-2] == 'E' &&

serial_data[serial_index-1] == 'N')

{

outputTrack = 0;

outputAcc = 0;

serial_index = 0;

string_started = 0;

}

// Save RAM settings to EEPROM

else if (serial_data[serial_index-4] == 'S' &&

serial_data[serial_index-3] == 'A' &&

serial_data[serial_index-2] == 'V' &&

serial_data[serial_index-1] == 'E')

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

98

{

SaveSettings();

serial_index = 0;

string_started = 0;

}

// Store accelerometer offset

else if (serial_data[serial_index-3] == 'A' &&

serial_data[serial_index-2] == 'C' &&

serial_data[serial_index-1] == 'C')

{

Serial.println(serial_data);

int valuesReceived[5] = {0,0,0,0,0};

int comma_index = 0;

for (unsigned char k = 0; k < serial_index - 3; k++)

{

// Looking for comma

if (serial_data[k] == 44)

{

comma_index++;

}

else

{

valuesReceived[comma_index] =

valuesReceived[comma_index] * 10 + (serial_data[k] - 48);

}

}

accOffset[0] = valuesReceived[0] - 2000;

accOffset[1] = valuesReceived[1] - 2000;

accOffset[2] = valuesReceived[2] - 2000;

serial_index = 0;

string_started = 0;

SaveAccelData();

}

// if "read_sensors" flag is set high, read sensors and update

if (read_sensors == 1 && ht_paused == 0)

{

UpdateSensors();

GyroCalc();

AccelCalc();

MagCalc();

FilterSensorData();

// Only output this data every X frames.

if (frameNumber++ >= SERIAL_OUTPUT_FRAME_INTERVAL)

{

if (outputTrack == 1)

{

trackerOutput();

}

else if (outputAcc == 1)

{

calAccOutput();

}

frameNumber = 0;

}

read_sensors = 0;

}

}

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

99

Codi 5. Codi main

10.2.2.2 Sensors

//--------------------------------------------------------------------

---------

// File: Sensors.cpp

// Desc: Implementations sensor board functionality.

//--------------------------------------------------------------------

---------

#include "config.h"

#include "Arduino.h"

#include "functions.h"

#include <Wire.h>

// Accelerometer

//

#define ADXL345_ADDR (0x53) // The adress of ADXL345

#define ADXL345_X_ADDR (0x32)// Start address for x-axis

#define ACC_SENS 256 // Sensitivity. 13 bit adc, +/- 16 g.

Calculated as: (2^13)/(16*2)

#define ASSUME_1G_ACC 0 // Assuming the total gravitation is 1.

True if only earth gravitation has influence.

#define SAMPLERATE 128 // Samplerate of sensors (in hz, samples

per second)

unsigned char ADXL345_ID = 0;

// Variables defined elsewhere

//

extern long channel_value[];

// Local variables

//

byte sensorBuffer[10]; // Buffer for bytes read from sensors

char resetValues = 1; // Used to reset headtracker/re-center.

long accRaw[3]; // Raw readings from accelerometer

float accG[3]; // G-force in each direction

float accAngle[3]; // Measured angle from accelerometer

float R; // Unit vector - total G.

// Final angles for headtracker:

float tiltAngle = 90; // Tilt angle

float tiltAngleLP = 90; // Tilt angle with low pass

FilterSensorData

float lastTiltAngle = 90; // Used in low pass FilterSensorData.

float rollAngle = 0; // Roll angle

float rollAngleLP = 90; // Roll angle with low pass

FilterSensorData

float lastRollAngle = 90; // Used in low pass FilterSensorData

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

100

// Start values - center position for head tracker

float tiltStart = 0;

float rollStart = 0;

char TrackerStarted = 0;

// Servo reversing

char tiltInverse = -1;

char rollInverse = 1;

// Settings

//

unsigned char servoReverseMask = 0;

unsigned char htChannels[3] = {0, 1, 2}; //tilt, roll

//

// End settings

// Function used to write to I2C:

void WriteToI2C(int device, byte address, byte val)

{

Wire.beginTransmission(device);

Wire.write(address);

Wire.write(val);

Wire.endTransmission();

}

// Function to read from I2C

void ReadFromI2C(int device, char address, char bytesToRead)

{

Wire.beginTransmission(device);

Wire.write(address);

Wire.endTransmission();

Wire.beginTransmission(device);

Wire.requestFrom(device, bytesToRead);

char i = 0;

while ( Wire.available() )

{

sensorBuffer[i++] = Wire.read();

}

Wire.endTransmission();

}

void trackerOutput()

{

Serial.print(tiltAngleLP - tiltStart + 90);

Serial.print(",");

Serial.print(rollAngleLP - rollStart + 90);

}

//--------------------------------------------------------------------

------------------

// Func: UpdateSensors

// Desc: Retrieves the sensor data from the sensor board via I2C.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

101

//--------------------------------------------------------------------

------------------

void UpdateSensors()

{

// Read x, y, z acceleration, pack the data.

ReadFromI2C(ADXL345_ADDR, ADXL345_X_ADDR, 6);

accRaw[0] = ((int)sensorBuffer[0] | ((int)sensorBuffer[1] << 8)) *

-1;

accRaw[1] = ((int)sensorBuffer[2] | ((int)sensorBuffer[3] << 8)) *

-1;

accRaw[2] = (int)sensorBuffer[4] | ((int)sensorBuffer[5] << 8);

}

//--------------------------------------------------------------------

------------------

// Func: AccelCalc

// Desc: Calculate angle from accelerometer data

//--------------------------------------------------------------------

------------------

void AccelCalc()

{

accRaw[0] += accOffset[0];

accRaw[1] += accOffset[1];

accRaw[2] += accOffset[2];

for (unsigned char i = 0; i<3; i++)

{

accG[i] = (float)accRaw[i] / ACC_SENS;

}

// So, lets calculate R

// R^2 = Rx^2+Ry^2+Rz^2

#if (ASSUME_1G_ACC == 0)

R = sqrt((accG[0] * accG[0]) + (accG[1] * accG[1]) + (accG[2]

* accG[2]));

#else // Otherwise, just assume total G = 1.

R = 1;

#endif

// Calculate final angles:

if (R < 1.3 && R > 0.7)

{

for (unsigned char i = 0; i<3; i++)

{

accAngle[i] = acos(accG[i] / R) * 11.36;

}

}

}

//--------------------------------------------------------------------

------------------

// Func: Filter

// Desc: Filters / merges sensor data.

//--------------------------------------------------------------------

------------------

void FilterSensorData()

{

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

102

UpdateSensors();

AccelCalc();

float tiltAngleTemp = (tiltAngleLP - tiltStart) * tiltInverse

* tiltFactor;

if ( (tiltAngleTemp > -tiltMinPulse) && (tiltAngleTemp <

tiltMaxPulse) )

{

temp = servoTiltCenter + tiltAngleTemp;

channel_value[htChannels[1]] = temp;

}

float rollAngleTemp = -((rollAngleLP - rollStart) *

rollInverse * rollFactor);

if ( (rollAngleTemp > -rollMinPulse) && (rollAngleTemp <

rollMaxPulse) )

{

temp = servoRollCenter + rollAngleTemp;

channel_value[htChannels[2]] = temp;

}

}

}

//--------------------------------------------------------------------

------------------

// Func: InitSensors

// Desc: Initializes the sensor board sensors.

//--------------------------------------------------------------------

------------------

void InitSensors()

{

ReadFromI2C(ADXL345_ADDR, 0x00, 1);

ADXL345_ID = sensorBuffer[0];

// Accelerometer increase G-range (+/- 16G)

WriteToI2C(ADXL345_ADDR, 0x31, 0b00001011);

ReadFromI2C(HMC_ADDR, 0x00, 1);

HMC_ID = sensorBuffer[0];

}

//--------------------------------------------------------------------

------------------

// Func: ResetCenter

// Desc: Utility for resetting tracker center. This is only called

during tracker

// startup. Button press resets are handled during filtering.

(Needs refactor)

//--------------------------------------------------------------------

------------------

void ResetCenter()

{

resetValues = 0;

tiltStart = accAngle[0];

rollStart = accAngle[1];

TrackerStarted = 1;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

103

}

Codi 6. Codi sensors

10.2.2.3 Configuration

// File: Configuration.cpp

// Desc: Implementations of PPM-related functions for the project.

//--------------------------------------------------------------------

---------

#include "config.h"

#include "Arduino.h"

#include "functions.h"

#include "sensors.h"

#include <Wire.h>

extern long channel_value[];

// Local variables

unsigned int pulseTime = 0;

unsigned int lastTime = 0;

unsigned int timeRead;

int channelsDetected = 0;

char channel = 0;

int channelValues[20];

char state = 0; // PPM signal high or Low?

char read_sensors = 0;

// external variables

extern unsigned long buttonDownTime;

extern unsigned char htChannels[];

// Sensor_board, x,y,z

int acc_raw[3] = {1,2,3};

unsigned char PpmIn_PpmOut[13] = {0,1,2,3,4,5,6,7,8,9,10,11,12};

long channel_value[13] =

{2100,2100,2100,2100,2100,2100,2100,2100,2100,2100,2100,2100,2100};

unsigned char channel_number = 1;

char shift = 0;

char time_out = 0;

//--------------------------------------------------------------------

------------------

// Func: InitPWMInterrupt

// Desc:

//--------------------------------------------------------------------

------------------

void InitPPMInterrupt()

{

TCCR1A =

(0 << WGM10) |

(0 << WGM11) |

(0 << COM1A1) |

(1 << COM1A0) | // Toggle pin om compare-match

(0 << COM1B1) |

(0 << COM1B0);

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

104

TCCR1B =

(1 << ICNC1)| // Input capture noise canceler - set to active

(1 << ICES1)| // Input capture edge select. 1 = rising, 0 =

falling. We will toggle this, doesn't matter what it starts at

(0 << CS10) | // Prescale 8

(1 << CS11) | // Prescale 8

(0 << CS12) | // Prescale 8

(0 << WGM13)|

(1 << WGM12); // CTC mode (Clear timer on compare match) with

ICR1 as top.

// Not used in this case:

TCCR1C =

(0 << FOC1A)| // No force output compare (A)

(0 << FOC1B); // No force output compare (B)

TIMSK1 =

(PPM_IN << ICIE1) | // Enable input capture interrupt

(1 << OCIE1A) | // Interrupt on compare A

(0 << OCIE1B) | // Disable interrupt on compare B

(0 << TOIE1);

// OCR1A is used to generate PPM signal and later reset counter

(to control frame-length)

OCR1A = DEAD_TIME;

}

//--------------------------------------------------------------------

------------------

// Func: InitTimerInterrupt

// Desc: Initializes timer interrupts.

//--------------------------------------------------------------------

------------------

void InitTimerInterrupt()

{

TCCR0A =

(0 << WGM00) |

(1 << WGM01) |

(0 << COM0A1) |

(0 << COM0A0) |

(0 << COM0B1) |

(0 << COM0B0);

// 61 hz update-rate:

TCCR0B =

(0 << FOC0A)| //

(0 << FOC0B)| //

(1 << CS00) | // Prescale 1024

(0 << CS01) | // Prescale 1024

(1 << CS02) | // Prescale 1024

(0 << WGM02);

TIMSK0 =

(0 << OCIE0B) |

(1 << OCIE0A) |

(1 << TOIE0);

OCR0B = 64 * 2;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

105

OCR0A = 64 * 2;

}

//--------------------------------------------------------------------

------------------

// Func: TIMER1_COMPA_vect

// Desc: Timer 1 compare A vector

//--------------------------------------------------------------------

------------------

ISR(TIMER1_COMPA_vect)

{

if (OCR1A == FRAME_LENGTH)

{

channel_number = 1;

OCR1A = 0;

}

else

{

if (channel_number == 1)

{

// After first time, when pin have been set high, we

toggle the pin at each interrupt

TCCR1A =

(0 << WGM10) |

(0 << WGM11) |

(0 << COM1A1) |

(POSITIVE_SHIFT_PPM << COM1A0) |

(0 << COM1B1) |

(0 << COM1B0);

}

if ((channel_number) < NUMBER_OF_CHANNELS)

{

OCR1A = channel_value[(channel_number)

channel_number++;

}

else

{

// We have to use OCR1A as top too, as ICR1 is used for

input capture and OCR1B can't be

// used as top.

OCR1A = FRAME_LENGTH;

TCCR1B |= (1 << WGM12);

}

}

}

//--------------------------------------------------------------------

------------------

// Func: TIMER0_COMPA_vect

// Desc: Timer 0 compare A vector Sensor-interrupt. We query sensors

on a timer, not

// during every loop.

//--------------------------------------------------------------------

------------------

ISR(TIMER0_COMPA_vect)

{

// Reset counter - should be changed to CTC timer mode.

TCNT0 = 0;

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

106

read_sensors = 1;

}

Codi 7. Codi configuration

9.4 Altres conceptes d’interès

Mecànica

CG "Centre de Gravetat"; aquest és el punt de l'avió on hi ha el mateix pes distribuït per tots els costats.

Connectors

Per connectar i desconnectar els cables, els connectors s'utilitzen als extrems dels cables. Els connectors comuns per a bateries són Deans & XT60, mentre que els connectors del controlador de vol i els sensors són de 0,1 "espaiats Amortidors Es tracta de peces de cautxú modelades que s'utilitzen per minimitzar les vibracions transmeses a través d'un UAV.

Marc

El marc és com el "esquelet" de l'avió i té totes les parts juntes. Els marcs simples tenen motors connectats a alumini o altres extrusions lleugeres ("braç") que es connecten a un cos central.

Propulsió BEC "Circuit Eliminador de la bateria": un regulador de tensió incorporat a l'ESC que pot proporcionar una potència regulada de 5V DC a qualsevol electrònica que ho necessiti.

Fulles

Les hèlixs d'hèlix són la superfície aerodinàmica que genera l'elevació. Una hèlix normalment té de dues a quatre fulles que es poden arreglar o plegar.

El "controlador de velocitat electrònica" ESC és el dispositiu que es connecta al controlador de la bateria, el motor i el vol i controla la velocitat a la qual gira el motor

LiPo "Polímer de liti" és la bateria més comú que s'utilitza en avions elèctrics a causa del seu pes lleuger (en comparació amb la capacitat d'emmagatzematge) i altes taxes de descàrrega actuals. Hi ha altres tipus de bateries de liti disponibles al mercat (LiFe, LiMn, etc.)

Motor

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

107

El motor és el que s'utilitza per girar les hèlixs; En petits UAV, un motor rasurat s'utilitza amb més freqüència, mentre que per als UAV més grans, un motor elèctric és molt més comú.

PCB

Una "Placa de circuits impresos" és la part plana de fibra de vidre amb molts components soldats. Molts productes electrònics tenen una PCB.

Distribució d'energia

Per poder alimentar tants dispositius diferents utilitzats en un UAV, la bateria s'ha de dividir, que és on entra en joc la distribució d'alimentació (tauler o cable).

Propulsió

Les hèlixs són les que proporcionen l'empenta i són més similars a les que s'utilitzen en els avions i no en els helicòpters.

Servo

Un servo és un tipus d'actuador que, sempre que sigui el senyal correcte, es pot moure a una posició angular específica.

Empenta

L'empenta és la força que un motor i hèlix específic pot proporcionar (a una certa tensió). Normalment es mesura en quilograms (Kg) o lliures (Lbs).

Estació de control

En lloc de (o a més d'un transmissor de mà), una estació (normalment en un cas o muntada en un trípode) s'utilitza per allotjar / integrar els components necessaris per controlar un UAV. Això pot incloure el transmissor, l'antena (e), el receptor de vídeo, el monitor, la bateria, l'ordinador i altres dispositius.

Canal

El nombre de canals d'un transmissor es refereix al nombre de senyals que pot enviar.

Controlador de vol

El "controlador de vol" és el que es consideraria el "cervell" d'un UAV i s'encarrega de tots els processos de dades, càlculs i senyals. El nucli d'un controlador de vol sovint és un "microcontrolador" programable. El controlador de vol pot tenir diversos sensors a bord, incloent un acceleròmetre, un giroscopi, un baròmetre, una brúixola, un GPS, etc. Si el controlador de vol té la capacitat de controlar l'avió per si mateix (per exemple, per navegar a coordenades GPS específiques), es pot considerar un "pilot automàtic".

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

108

Arnesos

Això sol referir-se al cablejat, que són els cables que connecten el receptor al controlador de vol (i de vegades altres dispositius).

Receptor de radiofreqüència

Això és el que processa la informació rebuda remotament sense fils.

Codi

Es refereix al programa que es carrega al controlador de vol de l'UAV.

Transmissor de radiofreqüència

El "transmissor" és el que genera els senyals de control sense fils cap al receptor.

Acceleròmetre

Un acceleròmetre mesura l'acceleració lineal d'un a tres eixos. Les unitats normalment estan en 'g' o gravetat. Un acceleròmetre pot proporcionar l'orientació del avió pel que fa al sòl.

Antena

Les antenes són el que realment reben o envien un senyal des d'un UAV (el senyal ha estat generat per una unitat transmissora). Vénen en una varietat de tipus diferents i inclouen direccional (més fort en una direcció) i omnidireccional.

Baròmetre

S'utilitza per donar informació sobre l'altitud del UAV. Mesura pressió, i com que la pressió canvia amb altitud, l'avió pot "saber" la seva alçada.

Magnetòmetre

Es una brúixola magnètica que proporciona la direcció del camp magnètic de la terra (nord / sud / est / oest).

Gravadora de vols

Una gravadora de vols registra els valors dels sensors del vostre UAV. Aquesta característica a vegades es pot integrar al controlador de vol. GPS "Sistema de posicionament global": els satèl·lits que orbiten al planeta envien senyals que són recollides per l'antena GPS i s'envien a ser processades pel receptor GPS per proporcionar coordenades geogràfiques.

Giroscopi

Un giroscopi mesura l'acceleració angular en un dels tres eixos. Les unitats normalment són graus per segon quadrats.

Muntatge d’un sistema FPV sobre un avió teledirigit amb headtracker Abel Tarragó Aguilar

109

Anemòmetre

És un dispositiu que mesura la velocitat de l'aire.

Pitch

Pitch és l'angle del nas a la cua pel que fa al sòl, o en altres paraules, la rotació d'un avió sobre l'eix d'ala a ala.

Roll

Roll és la rotació de l'avió al llarg de l'eix des del nas fins a la cua.

Yaw

Yaw és la rotació d'un avió sobre un eix perpendicular (90 graus) al pla format entre cap, cua i ala.