Tento modul obsahuje integrovaný obvod s funkcí zastupující dvě zařízení, gyroskop a akcelerometr. Gyroskop je zařízení, které se používá hlavně v navigaci a obsahuje setrvačník, který zachovává polohu osy své rotace. Můžeme tedy díky němu poznat, jaká je poloha celého modulu vůči ploše Země. Akcelerometr je pak zařízení, které měří gravitační zrychlení a můžeme s ním tedy měřit náklon či vibrace modulu.
Námi vybraný modul gyroskopu a akcelerometru pak ještě obsahuje DMP (Digital Motion Processor), který nám velice zjednoduší práci s daty, protože v reálném čase sbírá data ze zmíněných dvou zařízení a poskytuje nám přímo tři důležité hodnoty, které udávají rotace kolem jednotlivých os. V angličtině se nazývají yaw (Z osa), pitch (Y osa) a roll (X osa). Modul má v sobě také integrovaný teploměr, ten je však velmi nepřesný a proto se nevyužívá.
Tento modul s gyroskopem a akcelerometrem má celkem 8 propojovacích pinů, nám však bude stačit zapojit pouze 5. Propojíme tedy VCC na napájecí napětí +5V, GND na zem, SCL na A5, SDA na A4 a INT na D2. Piny SCL a SDA jsou připojeny na I2C sběrnici a pin INT slouží pro detekci přerušení od DMP.
První ukázkový kód pro zapojení a vyzkoušení gyroskopu a akcelerometru obsahuje jednoduchou komunikaci přes knihovnu Wire, která je již od instalace přítomna v Arduino IDE. Na začátku programu tedy vytvoříme potřebné proměnné a v podprogramu setup nastavíme nejprve modul přes I2C sběrnici a také komunikaci po sériové lince. V nekonečné smyčce loop pak vždy aktivujeme I2C sběrnici, na ní pošleme žádost o data od modulu a poté vyčteme data ze všech tří os akcelerometru a gyroskopu. Tato naměřená data se poté vytisknou po sériové lince včetně informace o teplotě.
// Arduino gyroskop a akcelerometr 1 // připojení knihovny Wire #include <Wire.h> // inicializace proměnné pro určení adresy senzoru // 0x68 nebo 0x69, dle připojení AD0 const int MPU_addr=0x68; // inicializace proměnných, do kterých se uloží data int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; void setup() { // komunikace přes I2C sběrnici Wire.begin(); Wire.beginTransmission(MPU_addr); Wire.write(0x6B); Wire.write(0); Wire.endTransmission(true); // komunikace přes sériovou linku rychlostí 115200 baud Serial.begin(115200); } void loop() { // zapnutí přenosu Wire.beginTransmission(MPU_addr); // zápis do registru ACCEL_XOUT_H Wire.write(0x3B); Wire.endTransmission(false); // vyzvednutí dat z 14 registrů Wire.requestFrom(MPU_addr,14,true); AcX=Wire.read()<<8|Wire.read(); AcY=Wire.read()<<8|Wire.read(); AcZ=Wire.read()<<8|Wire.read(); Tmp=Wire.read()<<8|Wire.read(); GyX=Wire.read()<<8|Wire.read(); GyY=Wire.read()<<8|Wire.read(); GyZ=Wire.read()<<8|Wire.read(); // výpis surových dat z proměnných na sériovou linku Serial.print("AcX = "); Serial.print(AcX); Serial.print(" | AcY = "); Serial.print(AcY); Serial.print(" | AcZ = "); Serial.print(AcZ); // přepočtení teploty dle datasheetu Serial.print(" | Temp = "); Serial.print(Tmp/340.00+36.53); Serial.print(" | GyX = "); Serial.print(GyX); Serial.print(" | GyY = "); Serial.print(GyY); Serial.print(" | GyZ = "); Serial.println(GyZ); delay(500); }
Data, která dostaneme s prvním ukázkovým kódem, však nejsou moc čitelná a slouží hlavně pro první otestování modulu. Pro získání lepších dat je pak nutné využít knihovny MPU-6050, která je ke stažení zde a knihovny I2Cdev, která je ke stažení zde. Po stažení a rozbalení balíčků s knihovnami zkopírujeme obě složky do naší složky libraries v místě, kde si ukládáme veškeré programy (standardně v Dokumentech). Po novém spuštění Arduino IDE uvidíme mezi příklady knihovnu MPU-6050. Druhý ukázkový kód je založen právě na příkladu od zmíněné knihovny a jeho výstupem jsou již data o rotacích jednotlivých os získáné z DMP čipu.
V druhém ukázkovém programu jsou tedy opět nejprve připojeny všechny důležité knihovny a poté vytvořeny všechny potřebné proměnné. Následně je vytvořen podprogram dmpINT, který obsahuje nastavení informací o detekci přerušení. Poté následuje podprogram setup s nastavením všech potřebných pinů a sběrnic, včetně sériové linky a také kontroly připojeného DSP. V nekonečné smyčce loop pak vždy detekujeme přerušení od DMP čipu a v případě jeho nečinnosti můžeme provádět libovolné operace uvnitř while smyčky (označeno komentářem). Při zachycení přerušení vyčteme informace o rotacích kolem všech os a tyto informace následně vytiskneme do sériové linky.
Níže si můžete prohlédnout nejprve zdrojový kód, poté obrázek objasňující zmíněné rotace kolem os a nakonec ukázkový výpis z tohoto ukázkového programu.
// Arduino gyroskop a akcelerometr 2 // knihovny potřebné pro modul #include "Wire.h" #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" // nastavení adresy modulu // 0x68 nebo 0x69, dle připojení AD0 // MPU6050 mpu(0x69) MPU6050 mpu; // číslo pinu s LED diodou pro notifikaci #define LED_PIN 13 // inicializace proměnných, do kterých se uloží data bool dmpReady = false; uint8_t mpuIntStatus; uint8_t devStatus; uint16_t packetSize; uint16_t fifoCount; uint8_t fifoBuffer[64]; // inicializace proměnných pro výpočet Quaternion q; // [w, x, y, z] kvaternion VectorFloat gravity; // [x, y, z] vektor setrvačnosti float rotace[3]; // rotace kolem os x,y,z // Rutina přerušení volatile bool mpuInterrupt = false; void dmpINT() { mpuInterrupt = true; } void setup() { // nastavení LED jako výstupní pinMode(LED_PIN, OUTPUT); // nastavení I2C sběrnice Wire.begin(); // komunikace přes sériovou linku rychlostí 115200 baud Serial.begin(115200); while (!Serial); // inicializace akcelerometru a gyroskopu Serial.println(F("Inicializace I2C zarizeni..")); mpu.initialize(); Serial.println(F("Test pripojenych zarizeni..")); Serial.println(mpu.testConnection() ? F("Modul pripojeni") : F("Pripojeni modulu selhalo")); // incializace DMP Serial.println(F("Inicializace DMP...")); devStatus = mpu.dmpInitialize(); // kontrola funkčnosti DMP if (devStatus == 0) { // zapnutí DMP Serial.println(F("Povoleni DMP...")); mpu.setDMPEnabled(true); // nastavení pinu INT jako přerušovacího, interrupt 0 odpovídá pinu 2 attachInterrupt(0, dmpINT, RISING); mpuIntStatus = mpu.getIntStatus(); Serial.println(F("DMP pripraveno, cekam na prvni preruseni..")); dmpReady = true; // načtení velikosti zpráv, které bude DMP posílat packetSize = mpu.dmpGetFIFOPacketSize(); } else { // V případě chyby: // 1 : selhání připojení k DMP // 2 : selhání při nastavení DMP Serial.print(F("DMP inicializace selhala (kod ")); Serial.print(devStatus); Serial.println(F(")")); } digitalWrite(LED_PIN, LOW); } void loop() { // dokud nepošle DMP přerušení, můžeme provádět ostatní příkazy // ve smyčce while níže if (!dmpReady) return; // tato podmínka čeká na příjem přerušení a můžeme v ní provádět // ostatní operace while (!mpuInterrupt && fifoCount < packetSize) { // místo pro ostatní operace // .. } // získání informace o statusu DSP mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // získání velikosti zásobníku dat fifoCount = mpu.getFIFOCount(); // kontrola přetečení zásobníku dat if ((mpuIntStatus & 0x10) || fifoCount == 1024) { mpu.resetFIFO(); Serial.println(F("Preteceni zasobniku dat!")); // v případě přetečení zásobníku je nutné // častěji vyčítat data } else if (mpuIntStatus & 0x02) { // kontrola délky dat while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // čtení paketu ze zásobníku mpu.getFIFOBytes(fifoBuffer, packetSize); // při větším množství paketů snížíme počítadlo fifoCount -= packetSize; // přečtení dat z DSP a uložení do proměnných mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(rotace, &q, &gravity); // výpis informací o rotacích kolem jednotlivých os Serial.print("Rotace \t X "); Serial.print(rotace[2] * 180/M_PI); Serial.print("st \t Y "); Serial.print(rotace[1] * 180/M_PI); Serial.print("st \t Z "); Serial.print(rotace[0] * 180/M_PI); Serial.println("st"); } }
Obrázek s názorným příkladem rotací kolem os x, y a z včetně anglických názvů.
Ukázkový výpis ze Sériového monitoru:
Inicializace I2C zarizeni.. Test pripojenych zarizeni.. Modul pripojeni Inicializace DMP... Povoleni DMP... DMP pripraveno, cekam na prvni preruseni.. Rotace X -2.15st Y -2.90st Z -0.03st Rotace X -2.06st Y -2.90st Z -0.03st ..
Tento modul obsahující gyroskop, akcelerometr a DMP čip se využívá často u kvadrokoptér, helikoptér a podobných zařízení, kdy potřebujeme kontrolovat právě rotace samotných zařízení či různé vibrace vyskytující se v okolí. Rád bych upozornil na to, že po každém nahrání programu či zapnutí zařízení s tímto senzorem je nutné vyčkat okolo 15 až 20 sekund kvůli kalibraci DMP čipu, sami uvidíte, že v prvních sekundách jsou výstupní hodnoty velice nestálé.
Poznámka: na rozdíl od většiny článků uvedených na tomto webu byla použita rychlost sériové linky větší než 9600 a to konkrétně 115200 baud. Tato změna byla nutná kvůli rychlejšímu vypisování informací ze zásobníku dat a je tedy nutné v Sériovém monitoru také změnit rychlost v pravém spodním rohu, jinak budete dostávat falešné znaky.
Seznam použitých komponent:
http://dratek.cz/arduino-vstupni-periferie/830-arduino-gyroskop-akcelerometr.html
http://dratek.cz/arduino/974-arduino-uno-r3-atmega328p-1424115860.html
http://dratek.cz/arduino/844-arduino-nepajive-pole.html
http://dratek.cz/arduino-kabelaz-propoje-rozsireni/1063-arduino-vodice-samec-samec-40-kusu.html