Inhoudsopgave:

Wallace - DIY autonome robot - deel 5 - IMU toevoegen - Ajarnpa
Wallace - DIY autonome robot - deel 5 - IMU toevoegen - Ajarnpa

Video: Wallace - DIY autonome robot - deel 5 - IMU toevoegen - Ajarnpa

Video: Wallace - DIY autonome robot - deel 5 - IMU toevoegen - Ajarnpa
Video: 5 Vertical Farms Run by AI and Robots | Future of Farming ▶ 3 2024, November
Anonim
Image
Image

We gaan samen met Wallace verder. De naam Wallace kwam van een mix van "Wall-E", en van een eerder project (spraakherkenning), en bij het gebruik van het hulpprogramma "espeak" klonk het een beetje Brits. En als een bediende of butler. En dat is het einddoel: dat dit project iets nuttigs wordt. Dus "Wallace".

Wallace kan bewegen, hij kan obstakels ontwijken met behulp van IR-afstandssensoren (onlangs zijn ze op de een of andere manier gebakken (?) time, samen met een MCP23017-expander) en kan ten slotte veranderingen in de motorstroom detecteren om te weten wanneer hij ergens tegenaan loopt.

Naast de sensoren "onthoudt" Wallace de 100 bewegingen en heeft hij een rudimentaire analyse met behulp van de bewegingsgeschiedenis.

Het doel tot nu toe voor Wallace is om alleen maar vooruit te blijven gaan en te weten wanneer het vastzit in een herhalend patroon (zoals in een hoek) en niet echt vooruit.

Ik heb verschillende iteraties doorlopen voor beweging en navigatie, en de constante hoofdpijn was tijdens rotatie.

Aangezien Wallace een rupsrobot is, en ik de dingen in de software eenvoudiger wilde houden (voor later), heb ik hem om te draaien gewoon op zijn plaats laten draaien/draaien. Pas dus een gelijk maar tegengesteld vermogen / inschakelduur toe op de motoren.

Het ondervonden probleem is te wijten aan het ontwerp van het Agent 390-robotplatform. De rupsbanden hebben de neiging om tegen de zijkanten te wrijven. En erger nog, de ene kant doet dat meer dan de andere.

Op vloeren en rechtdoor was het geen probleem. Het verschijnt op tapijt. Ik heb ervoor gekozen om Wallace van de vloerbedekking te houden nadat de sporen vuil zijn geworden (ze nemen vuil heel gemakkelijk op).

Het echte probleem is bij het draaien op vloeren.

Als ik de software een duty cycle van hoog niveau laat toepassen, draait het min of meer constant. Tijdens een lage inschakelduur kan het echter wel of niet echt draaien. Of het kan even draaien en dan vertragen. De draaibeweging lijkt oncontroleerbaar via de software, of op zijn best heel moeilijk.

Het probleem treedt op tijdens het navigeren en het verplaatsen of weg van obstakels. Het kan ofwel te wild wegzwaaien, of het kan vast komen te zitten in een poging om zeer kleine verschuivingen te maken, zonder echt te bewegen.

En dus motiveerde de bovenstaande uitleg dit Instructable.

Aanvankelijk had ik de introductie van een motion-sensing unit (IMU) willen afschaffen of uitstellen, omdat ze A) gecompliceerd zijn, B) luidruchtig zijn, C) na verloop van tijd fouten kunnen ontstaan, enzovoort, enzovoort. was dat we het heel goed konden doen door vooruit te springen naar time-of-flight IR-lasersensoren. En dat konden we - met behulp van lasers konden we weten of de robot draaide of niet, door de veranderingen in afstand te volgen.

In feite zouden we dat nu ook (soort van) kunnen doen, met de akoestische sensoren.

Dit alles is echter een zeer indirecte, gecompliceerde manier om één simpele vraag te beantwoorden: "hebben we gedraaid of niet?"

Het leek me dat het springen om de ToF-lasersensoren te gebruiken me naar het volgende softwareniveau zou brengen; namelijk SLAM (Gelijktijdige Lokalisatie en Mapping). Ik was er nog niet klaar voor om daarheen te gaan.

Het is een goede zaak om een robotproject in lagen te doen, waarbij de eerste (onderste) lagen eenvoudiger zijn en de laatste (bovenste) lagen abstracter en moeilijkere problemen aanpakken.

Lagen kunnen ongeveer als volgt worden gedacht:

  1. robot fysiek frame / mechanische structurele basis
  2. rudimentair aandrijfsysteem (Raspberry, Roboclaw, motoren, bekabeling, enz., basissoftware, toetsenbordgestuurd)
  3. essentiële circuits om sensoren te ondersteunen (bidirectionele spanningsverschuiver, poortuitbreiding, noodstop, stroomverdeling, enz.)
  4. sensoren voor het vermijden van obstakels (akoestisch, IR)
  5. essentiële, basispositionering en bewegingsdetectie (versnellingsmeter, gyro, magnetometer, motor-encoders, wiel-encoders)

Je kunt je eigen lijst maken. De punten over deze lijst zijn dat je deze waarschijnlijk min of meer in die volgorde moet doen, en ook dat als je wat tijd aan elke laag besteedt om ze goed te laten werken, dat je later zou moeten helpen als de dingen ingewikkelder worden.

Bovenstaande lijst zou in software min of meer kunnen worden toegewezen aan deze conceptuele lagen.

  • SLAM (gelijktijdige lokalisatie en mapping)
  • Controle en bewustzijn van beweging, rotatie
  • Basis obstakel vermijden
  • Controle en detectie van sensorgegevens
  • Essentiële beweging Vooruit, achteruit, links en rechts, versnellen, vertragen, stoppen

Zoals u kunt zien, zijn de eerste items voor deze lijst de bovenste, meer gecompliceerde lagen die meer abstracte problemen en vragen aanpakken, zoals "waar ben ik" en "waar ga ik heen", terwijl de laatste items de lagere softwarelagen die omgaan met "hoe te praten/luisteren naar sensor A" of "hoe dit wiel te verplaatsen".

Nu, ik zeg niet dat wanneer je bij een laag begint, je deze hebt voltooid en dan op de volgende laag staat, om nooit meer terug te keren naar de vorige. Een robotproject kan veel lijken op moderne, iteratieve methoden voor softwareontwikkeling (agile, SCRUM, enz.).

Ik zeg alleen dat je bij elk de tijd moet nemen. Je moet een afweging maken hoeveel je bij elk moet doen, en beslissen wat je op een bepaalde laag probeert, de tijd en moeite waard is.

Er is een zeker "conflict" of "spanning" tussen twee concurrerende ideeën of richtingen.

Een daarvan is wat ik "plug-n-play" zou noemen om probleem A op te lossen.

De andere is DIY (doe het zelf). En dat is misschien niet eens het beste label voor dit andere idee.

Hier is een voorbeeld van elk, hopelijk zie je de spanning of het conflict tussen de twee keuzes.

Laten we voor dit voorbeeld SLAM, het vermijden van obstakels en essentiële basisbewegingen samenvatten als één probleem dat tegelijkertijd moet worden opgelost.

  1. Als we besluiten om de plug-n-play-route te gaan, springen we meteen (afhankelijk van het budget) naar dingen als die aan de bovenkant gemonteerde roterende lasers, of scherptedieptecamera, of ToF-lasers, en de IMU (onderwerp van dit Instructable).
  2. Als we daarentegen de tweede route willen gaan, kunnen we proberen alle mogelijke informatie uit sommige akoestische sensoren of IR-sensoren te halen, of helemaal geen sensoren - we gebruiken gewoon motorstroombewaking (bump)

Wat valt er te zeggen over #1 versus #2? Eén ding zou zijn dat we veel meer hebben geleerd door #2 te doen. De beperkingen van het hebben van alleen akoestische sensoren om mee te werken, dwingen ons om over veel meer zaken na te denken.

Aan de andere kant, als we te veel gefocust zijn op het doen van dingen via #2, verspillen we misschien tijd, omdat we meer vragen dan we zouden moeten van akoestische sensoren.

Nog een concept of idee om over na te denken: welke combinatie van hardware en software beantwoordt het beste de vragen "hoe", en welke combinatie van software (en hardware?) beantwoordt de vraag "wat", "wanneer", "waar". Omdat 'hoe' meestal een vraag op een lager niveau is waarvan 'wat', 'wanneer' en 'waar' afhangen om een antwoord te krijgen.

Hoe dan ook, al het bovenstaande was gewoon iets om over na te denken.

In mijn geval is het, na veel inspanning en het constant irritante probleem van wrijving op het circuit en niet in staat om consistente controle en beweging te krijgen, tijd om iets anders te doen.

Dus dit Instructable - een IMU.

Het doel is dat als de IMU zegt dat de robot NIET draait, we de werkcyclus verhogen. Als we te snel draaien, verminderen we de duty cycle.

Stap 1: De IMU-sensor

De IMU-sensor
De IMU-sensor
De IMU-sensor
De IMU-sensor

En dus is onze volgende sensor om aan Wallace toe te voegen de IMU. Na wat onderzoek kwam ik uit op een MPU6050. Maar op dat moment leek de MPU9050 (en zelfs recenter de MPU9250) een nog beter idee.

Mijn go-to-bron is Amazon (in de VS). Dus ik heb er twee besteld.

Wat ik in feite kreeg (er lijkt geen controle over te zijn; dat is wat ik niet leuk vind aan Amazon) waren twee MPU92/65. Ik twijfel een beetje over de aanduiding. Bekijk de afbeeldingen; dat lijkt een "familie" aanduiding te zijn. Daar zit ik in ieder geval aan vast.

Het toevoegen is heel eenvoudig - koop een proto-bord met verbindingssporen, soldeer de sensor op het bord, voeg een 10-pins schroefklemmenblok toe (ik heb de mijne van Pololu).

Om interferentie tot een minimum te beperken, heb ik geprobeerd deze sensoren uit de buurt van al het andere te plaatsen.

Dat betekende ook het gebruik van enkele nylon bouten/moeren.

Ik ga het I2C-protocol gebruiken. Hopelijk valt de totale draadlengte mee.

Er is elders voldoende informatie over de basisaansluitingen en spanningsniveaus, enz., dus ik zal dat hier niet herhalen.

Stap 2: Dingen zijn niet altijd schoon, gemakkelijk

Op dit moment lijkt er niet veel online te zijn voor deze specifieke MPU-92/65. Wat beschikbaar is, zoals bij de meeste sensoren, lijken voorbeelden te zijn met Arduino.

Ik probeer deze Instructables een beetje anders te maken door een niet-zo-schoon proces te presenteren, omdat dingen niet altijd meteen werken.

Ik veronderstel dat deze Instructables meer op een blog lijken dan op rechte A-B-C, 1-2-3 "dit is hoe je het doet".

Stap 3: Eerste test

Eerste test
Eerste test
Eerste test
Eerste test

Uit de afbeeldingen in de vorige stap zijn de rode en zwarte draden die naar de sensoren gaan natuurlijk VCC (5V) en GND. De groene en gele draden zijn de I2C-aansluitingen.

Als je andere I2C-projecten hebt gedaan, of deze series hebt gevolgd, dan weet je al over "i2cdetect", en dat is de eerste stap om te weten of de Raspberry de nieuwe sensor kan zien.

Zoals je kunt zien aan de afbeeldingen in deze stap, was onze eerste poging niet succesvol. De IMU verschijnt niet (moet apparaat-ID 0x68 zijn).

Het goede nieuws is echter dat de I2C-bus rijdt. Wel zien we één apparaat 0x20 en het is de MCP23017 poortexpander (momenteel verantwoordelijk voor de HCSR04 akoestische sensoren).

Het is niet gemakkelijk te zien op de afbeelding, maar ik heb wel dezelfde gekleurde groene en gele draden van de IMU op de MCP23017 aangesloten (zie linksonder in de afbeelding)

We zullen wat problemen moeten oplossen.

Stap 4: Problemen oplossen

Image
Image
Probleemoplossen
Probleemoplossen
Probleemoplossen
Probleemoplossen

Met behulp van de continuïteitsinstelling op een voltmeter (die met de hoge toon) heb ik VCC (5V), GND, SDA en SCL-verbindingen getest. Die waren goed.

De volgende poging was om de MCP23017 los te koppelen van de I2C-bus, zodat alleen de MPU-92/65 op de bus achterbleef. Dat bleek vruchteloos - "i2cdetect" toonde toen geen apparaten.

Dus vervolgens heb ik de sensor van de totempaal verwijderd en rechtstreeks opnieuw aangesloten op de 5V-naar-3V bidirectionele bus; d.w.z. rechtstreeks naar de framboos. (kortere draden?).

En voila. Dit keer is er succes. We zien 0x68 verschijnen met "i2cdetect".

Maar we weten nog niet waarom het deze keer werkte. Zou het aan de lengte van de draden kunnen liggen? De vorige locatie?

Let op: Het maakte niet uit of ADO gegrond was of niet. Het kan zijn dat er aan boord pullup- en pull-down-weerstanden zijn. Hetzelfde zou kunnen gelden voor FSYNC.

Vervolgens heb ik de MCP23017 opnieuw aangesloten. Dus nu hebben we twee apparaten op de I2C-bus. (zie afbeelding). Succes, we zien nu zowel 0x20 als 0x68 met i2cdetect.

De video's gaan iets meer in op wat er is gebeurd tijdens het oplossen van problemen.

Stap 5: De gegevens van de sensor lezen

Image
Image
De gegevens van de sensor lezen
De gegevens van de sensor lezen
De gegevens van de sensor lezen
De gegevens van de sensor lezen

Verschillende benaderingen

Ik besloot om meerdere benaderingen te volgen om nuttige informatie van de sensor te krijgen. Hier zijn ze, niet in willekeurige volgorde:

  1. probeer wat basisprogrammering
  2. kijk door wat online documentatie over registers
  3. bekijk de voorbeelden en/of code van anderen

Waarom deze benaderingen? Waarom niet gewoon op zoek naar een bestaande bibliotheek of code?

Door te experimenteren en enkele ideeën uit te proberen, kunnen we niet alleen wat kennis over deze specifieke sensor opnemen, maar ook wat techniek, vaardigheid en manieren van denken opdoen over het aanpakken van iets nieuws, en iets dat misschien niet veel documentatie heeft; iets dat veel onbekenden kan hebben.

En als we eenmaal met onze eigen ideeën hebben gespeeld en deze hebben uitgeprobeerd en enig inzicht hebben gekregen, zijn we in een betere positie om de code of bibliotheek van iemand anders te evalueren.

Nadat ik bijvoorbeeld wat C++-code voor de MPU9250 in github had bekeken, realiseerde ik me dat het me dwong om interrupts te gebruiken, wat ik nog niet wil doen.

Het wordt ook geleverd met extra dingen zoals kalibratie; nogmaals, iets waar ik nog niet in geïnteresseerd ben.

Het kan zijn dat wat ik moet doen om de simpele vraag "is de robot ja of nee draait" te beantwoorden heel eenvoudig kan worden beantwoord door gewoon enkele registers te lezen.

registreert

Op dit moment lijkt er niet veel beschikbaar te zijn over deze sensor. Als je de afbeeldingen bekijkt die bij deze Instructable horen, en de inscripties op de eigenlijke chips van dichtbij bekijkt, vraag ik me af of dit geen namaak is. Ik relateer wat ik zie niet aan iets van Invense. Hoe dan ook, ik koos ervoor om te kijken naar de register-informatie van de modellen die ik vond: de MPU-6050 en de MPU-9250.

In beide gevallen is het volgende voor beide hetzelfde. En om te beginnen gaan we ervan uit dat dit ook voor deze MPU-92/65 zo zal zijn.

59 tot 64 - metingen van de versnellingsmeter

65, 66 - temperatuurmetingen 67 tot 72 - gyroscoopmetingen 73 tot 96 - externe sensorgegevens

Een opmerking: de MPU-6050 lijkt GEEN magnetometer te hebben, terwijl de MPU-9250 (en we nemen aan dat deze ook) er wel een heeft.

Nog wat interessante, hopelijk nuttige informatie uit het registerdocument:

Magnetometerinformatie:

magnetometer id: 0x48 registers 00 tot 09: 00H WIA 0 1 0 0 1 0 0 0 01H INFO INFO7 INFO6 INFO5 INFO4 INFO3 INFO2 INFO1 INFO0 02H ST1 0 0 0 0 0 0 DOR DRDY 03H HXL HX7 HX6 HX5 HX4 HX3 HX02 HX1 HXH HX15 HX14 HX13 HX12 HX11 HX10 HX9 HX8 05H HYL HY7 HY6 HY5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY9 HY9 HY6 HY5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY9 HY9 HY6 HY5 HY4 HZ5 HZHZ0 ST2 0 0 0 BITM HOFL 0 0 0 een overzicht van wat elk register betekent: HXL[7:0]: X-as meetgegevens lager 8bit HXH[15:8]: X-as meetgegevens hoger 8bit HYL[7:0]: Y-as meetgegevens lager 8bit HYH[15:8]: Y-as meetgegevens hoger 8bit HZL[7:0]: Z-as meetgegevens lager 8bit HZH[15:8]: Z-as meetgegevens hoger 8bit

Programmeren

Een ander stukje informatie uit de registerdocumenten is dat er slechts ongeveer 100 registers leken te zijn. Dus een tactiek zou kunnen zijn om een eenvoudig programma te schrijven dat toegang heeft tot het apparaat (0x68) en probeert een reeks registers opeenvolgend te lezen, zonder enige acht te slaan op hun betekenis, gewoon om te zien welke gegevens te zien zijn.

En voer vervolgens opeenvolgende passen uit, gebruik dezelfde code, en vergelijk de gegevens van de ene doorgang met de volgende.

Het idee is dat we waarschijnlijk alle registers kunnen elimineren die geen gegevens lijken te hebben (nullen of FF?) of die absoluut nooit veranderen, en we zouden ons ook kunnen concentreren op de registers die wel veranderen.

Dan, we kijken alleen naar degenen die veranderen, voeg een middelingsfunctie toe die het gemiddelde neemt van de laatste N-waarden van dat register, om te zien of er in feite een bepaalde constante waarde voor dat register is. Dit zou veronderstellen dat we de sensor heel stil en op dezelfde locatie houden.

Ten slotte zouden we dan voorzichtig dingen met de sensor kunnen proberen, zoals er tegenaan duwen (versnellingsmeter, gyro), of erop blazen (temperatuur), of draaien (de vorige twee plus magnetometer) en kijken welk effect dit heeft op de waarden.

Ik gebruik de bedradingPi-bibliotheek graag zoveel mogelijk. Het heeft ondersteuning voor I2C.

Eerste loop:

/********************************************************************************

* om te bouwen: gcc first.test.mpu9265.c -o first.test.mpu9265 -lwiringPi * * om uit te voeren: sudo./first.test.mpu9265 * * dit programma voert gewoon een reeks (mogelijke) registers uit van de MCP23017, * en dan van de MPU9265 (of een andere MPU op dat 0x68-adres) * * Ik gebruikte het om te valideren of ik zelfs van de sensor kon lezen, aangezien ik al * vertrouwen had in de MCP23017. * *************************************************** ******************************/ #include #include #include #include #include int main(int argc, char** argv) { puts("Laten we eens kijken wat MCP23017 @ 0x20 te zeggen heeft:"); fout = 0; int apparaat-ID1 = 0x20; int fd1 = bedradingPiI2CSetup(deviceId1); if (-1 == fd1) { fprintf (stderr, "Kan bedradingPi I2C-apparaat niet openen: %s\n", strerror (errno)); retour 1; } for (int reg=0;reg<300;reg++) {fprintf(stderr, "%d", bedradingPiI2CReadReg8(fd1, reg));fflush(stderr); vertraging(10); } zet(""); puts("Laten we eens kijken wat MPU9265 @ 0x20 te zeggen heeft:"); fout = 0; int apparaat-ID2 = 0x68; int fd2 = bedradingPiI2CSetup(deviceId2); if (-1 == fd2) { fprintf (stderr, "Kan bedradingPi I2C-apparaat niet openen: %s\n", strerror (errno)); retour 1; } for (int reg=0;reg<300;reg++) {fprintf(stderr, "%d", bedradingPiI2CReadReg8(fd2, reg));fflush(stderr); vertraging(10); } zet(""); retourneer 0; }

De tweede rit:

/********************************************************************************

* om te bouwen: gcc second.test.mpu9265.c -o second.test.mpu9265 -lwiringPi * * om uit te voeren: sudo./second.test.mpu9265 * * Dit programma voert het registernummer uit naast de gelezen waarde. * * Dit maakt het handig om de uitvoer naar een bestand te pipen (omleiden), en dan * kunnen verschillende runs worden gedaan om te vergelijken. Het kan enig inzicht geven in * welk register belangrijk is en hoe de gegevens zich zouden kunnen gedragen. * *************************************************** **************************/ #include #include #include #include #include #include int main(int argc, char** argv) { int apparaat-ID = -1; if (0) { } else if (!strncmp(argv[1], "0x20", strlen("0x20"))) { deviceId = 0x20; } else if (!strncmp(argv[1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("Laten we eens kijken wat MPU9265 @ 0x20 te zeggen heeft:"); fout = 0; int fd = bedradingPiI2CSetup (apparaat-ID); if (-1 == fd) { fprintf (stderr, "Kan bedradingPi I2C-apparaat niet openen: %s\n", strerror (errno)); retour 1; } for (int reg=0;reg<300;reg++) { fprintf(stderr, "%d:%d\n", reg, bedradingPiI2CReadReg8(fd, reg));fflush(stderr); vertraging(10); } retourneer 0; }

De derde rit:

/********************************************************************************

* om te bouwen: gcc third.test.mpu9265.c -o third.test.mpu9265 -lwiringPi * * om uit te voeren: sudo./third.test.mpu9265 * * Dit programma is het resultaat van het tweede. Het leest alleen uit de * registers die een verschil aangeven tussen de ene run en de volgende.* *************************************************** **************************/ #include #include #include #include #include #include int main(int argc, char** argv) { int apparaat-ID = -1; if (0) { } else if (!strncmp(argv[1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("Laten we eens kijken wat MPU9265 @ 0x20 te zeggen heeft:"); fout = 0; int fd = bedradingPiI2CSetup (apparaat-ID); if (-1 == fd) { fprintf (stderr, "Kan bedradingPi I2C-apparaat niet openen: %s\n", strerror (errno)); retour 1; } for (int reg=61;reg<=73;reg++) { fprintf(stderr, "%d:%d\n", reg, bedradingPiI2CReadReg8(fd, reg));fflush(stderr); vertraging(10); } for (int reg=111;reg<=112;reg++) { fprintf(stderr, "%d:%d\n", reg, bedradingPiI2CReadReg8(fd, reg));fflush(stderr); vertraging(10); } for (int reg=189;reg<=201;reg++) { fprintf(stderr, "%d:%d\n", reg, bedradingPiI2CReadReg8(fd, reg));fflush(stderr); vertraging(10); } for (int reg=239;reg<=240;reg++) { fprintf(stderr, "%d:%d\n", reg, bedradingPiI2CReadReg8(fd, reg));fflush(stderr); vertraging(10); } retourneer 0; }

Dus wat hebben we tot nu toe geleerd? De afbeelding van de tabel met gekleurde gemarkeerde gebieden geeft aan dat de uitvoer lijkt overeen te komen met de eerste sets registers.

De resultaten tot nu toe kunnen nieuwe vragen oproepen.

Vraag: waarom is er maar één registerresultaat voor de "externe" groep?

Vraag: wat zijn al die onbekende registers "???????"

Vraag: omdat het programma niet interrupt-gedreven is, vroeg het dan te langzaam om data? te snel?

Vraag: kunnen we de resultaten beïnvloeden door dingen te proberen met de sensor zelf terwijl deze draait?

Stap 6: Laten we meer graven in de metingen / gegevens

Ik denk dat de volgende stap voor alles is om het programma te verbeteren om:

  • wees flexibel in hoeveel lusvertraging (ms)
  • wees flexibel in het aantal metingen om een lopend gemiddelde per register te geven

(Ik moest het programma als een bestand bijvoegen. Het leek een probleem te zijn om het hier in te voegen. "fourth.test.mpu9265.c")

Hier is een run met de laatste 10 metingen voor een gemiddelde, in een lus van 10 ms:

sudo./vierde.test.mpu9265 0x68 10 10

61:255 0 255 0 255 0 255 0 0 0: 102 62:204 112 140 164 148 156 188 248 88 228: 167 63:189 188 189 187 189 188 188 188 188 189: 188 64: 60 40 16 96 208 132 116 252 172 36: 112 65: 7 7 7 7 7 7 7 7 7 7: 7 66:224 224 224 240 160 208 224 208 144 96: 195 67: 0 0 0 0 0 0 0 0 0 0: 0 68:215 228 226 228 203 221 239 208 214 187: 216 69: 0 255 0 255 255 0 255 0 0 0: 102 70:242 43 253 239 239 45 206 28 247 207: 174 71: 0 255 255 0 255 255 255 255 255 255: 204 72: 51 199 19 214 11 223 21 236 193 8: 117 73: 0 0 0 0 0 0 0 0 0 0: 0 111: 46 149 91 199 215 46 142 2 233 199: 132 112: 0 0 0 0 0 0 0 0 0 0: 0 189:255 0 255 0 255 0 0 255 0 255: 127 190: 76 36 240 36 100 0 164 164 152 244: 121 191:188 188 188 188 187 188 187 189 187 189: 187 192: 8 48 48 196 96 220 144 0 76 40: 87 193: 7 7 7 7 7 8 7 7 7 7: 7 194:208 224 144 240 176 240 224 208 240 224: 212 195: 0 0 0 0 0 0 0 0 0 0: 0 196:243 184 233 200 225 192 189 242 188 203: 209 197:255 0 0 0 255 0 255 0 0 255: 102 198:223 39 247 43 245 22 255 221 0 6: 130 199: 0 255 255 255 0 255 255 255 255 0: 178 200:231 225 251 1 252 20 211 216 218 16: 164 201: 0 0 0 0 0 0 0 0 0 0: 0 239: 21 138 196 87 26 89 16 245 187 144: 114 240: 0 0 0 0 0 0 0 0 0 0: 0

De eerste, meest linkse kolom is het registernummer. Dan komen de laatste 10 metingen voor dat register. Ten slotte is de laatste kolom het gemiddelde voor elke rij.

Het lijkt erop dat de registers 61, 69, 71, 189, 197 en 199 ofwel alleen binair zijn, ofwel gereed/niet gereed, ofwel de hoge byte van een 16-bits waarde (negatief?).

Andere interessante observaties:

  • registers 65, 193 - zeer stabiel en dezelfde waarde
  • register 63, 191 - zeer stabiel en dezelfde waarde
  • registers 73, 112, 195, 201, 240 - allemaal op nul

Laten we deze waarnemingen terugkoppelen naar het veelkleurige, gemarkeerde tafelbeeld van eerder.

Registreer 65 - temperatuur

Inschrijven 193 - ???????

Registreer 63 - versnellingsmeter

Inschrijven 191 - ???????

Registreren 73 - extern

Registreer 112 en verder - ???????

Nou, we hebben nog steeds onbekenden, maar we hebben iets nuttigs geleerd.

Register 65 (temperatuur) en register 63 (versnellingsmeter) waren beide zeer stabiel. Dit is iets wat we zouden verwachten. Ik heb de sensor niet aangeraakt; het beweegt niet, afgezien van incidentele trillingen, omdat de robot op dezelfde tafel als mijn computer rust.

Er is één interessante test die we kunnen doen voor elk van deze temperatuur-/versnellingsmeterregisters. Voor die test hebben we nog een andere versie van het programma nodig.

Stap 7: We zijn in staat om de temperatuur en versnelling te beïnvloeden

In de vorige stappen hebben we ten minste één register voor temperatuur en één voor versnelling versmald.

Met deze volgende versie van het programma ("vijfde.test.mpu9265.c") kunnen we daadwerkelijk een verandering zien plaatsvinden voor beide registers. Bekijk de video's.

Meer graven

Als we teruggaan en de registergegevens bekijken, zien we dat er:

  • drie 16-bits uitgangen voor gyroscoop
  • drie 16-bits uitgangen voor versnellingsmeter
  • drie 16-bits uitgangen voor magnetometer
  • een 16-bits uitgang voor temperatuur

De resultaten die door onze eenvoudige testprogramma's werden verkregen, waren echter allemaal enkele 8-bits uitgangen. (enkele registers).

Dus laten we meer van dezelfde aanpak proberen, maar deze keer lezen we 16 bits in plaats van 8.

We zullen waarschijnlijk iets moeten doen zoals hieronder. Laten we de temperatuur als voorbeeld gebruiken, aangezien het maar één 16 bit-uitgang is.

// verkrijg bestandsdescriptor fd…

int tempRegHi = 65; int tempRegLo = 66; int hiByte = bedradingPiI2CReadReg8(fd, tempRegHi); int loByte = bedradingPiI2CReadReg8(fd, tempRegLo); int resultaat = hiByte << 8; // plaats de hoge volgorde 8 bits in het bovenste deel van een 16-bits waarderesultaat |= loByte; // voeg nu de lo-volgorde 8 bits toe, wat een volledig 16-bits nummer oplevert // print dat nummer of gebruik de horizontale grafische weergavefunctie van eerder

Uit onze vorige stappen hebben we gezien dat register 65 behoorlijk stabiel is, terwijl register 66 erg luidruchtig is. Aangezien 65 de hoge-orde-byte is en 66 de lage-orde-byte, is dat logisch.

Voor het lezen kunnen we de gegevens van register 65 nemen zoals ze zijn, maar we kunnen de waarden van register 66 uitgemiddelden.

Of we kunnen gewoon het hele resultaat middelen.

Bekijk de laatste video voor dit onderdeel; het demonstreert het lezen van de volledige 16-bits temperatuurwaarde. De code is "sixth.test.mpu9265.c"

Stap 8: De versnellingsmeter en gyroscoop

Image
Image

De video's voor deze sectie tonen de output van de accelerometer en de gyroscoop, met behulp van een testprogramma "seventh.test.mpu9265.c". Die code kan 1, 2 of 3 opeenvolgende byte-paren (hi en lo bytes) lezen en de waarden converteren naar een enkele waarde van 16 bits. We kunnen dus elke enkele as lezen, of we kunnen er twee samen lezen (en het telt de veranderingen op), of we kunnen ze alle drie lezen (en het telt de veranderingen op).

Om te herhalen, voor deze fase, voor deze Instructable, wil ik gewoon een simpele vraag beantwoorden: "is de robot geroteerd/geroteerd?". Ik ben niet op zoek naar een precieze waarde, zoals of het 90 graden is gedraaid. Dat komt later als we SLAM gaan doen, maar het is niet vereist voor het eenvoudig vermijden van obstakels en willekeurige bewegingen.

Stap 9: (werk in uitvoering) de magnetometer

bij gebruik van de i2cdetect-tool wordt de MPU9265 weergegeven als 0x68 in de tabel:

0 1 2 3 4 5 6 7 8 9 a b c d e f

00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Er zijn extra stappen nodig om van het magnetometergedeelte van de IMU te lezen.

Van het Invesense-registers PDF-document:

REGISTREERT 37 TOT 39 – I2C SLAVE 0 CONTROL

  • REGISTREER 37 - I2C_SLV0_ADDR
  • REGISTREER 38 - I2C_SLV0_REG
  • REGISTREER 39 - I2C_SLV0_CTRL

Aanbevolen: