Étape 4: Le gyroscope à 3 axes MPU6050 et accéléromètre
Il nous faut un signal proportionnel à l’angle d’inclinaison - qui est l’axe des Y dans le logiciel et ce gyroscope lorsqu’il n’est plat. Une fois de plus je ne recommande pas simplement sauter à la solution finale, j’ai, tester d’abord le gyroscope en soi et regarder sur le port série que l’angle est tel que vous l’inclinez en arrière (avec aucun moteur d’entraînement). Si vous devez utiliser le programme à partir de ce lien par Jeff Rowberg qui a écrit le logiciel pilote
https://github.com/jrowberg/i2cdevlib/BLOB/Master/...
Vous devrez également utiliser sa bibliothèque (même lien). Si son programme ne compile pas alors vous n’avez pas sa bibliothèque
i2cdevlib installé sur l’Arduino. Vous pouvez le télécharger depuis ce indestructible
Lorsque vous exécutez le programme d’essai vous pouvez très bien se que lorsque le pendule est à 90 degrés vertical que l’angle est compensée par rien dire jusqu'à +/-10 degrés!! Cela varie de périphérique à périphérique (je suis porté à croire) et c’est pourquoi j’ai mis un pot de garniture sur la conception finale.
Le câblage du gyroscope MPU6050 est simple
Se connecter VCC et Gnd à 3.3V et le fondement de l’Arduino (pas 5V!)
relier la broche de l’Int (l’interruption) pour Arduino Pin 2
connecter SCL et XDA pour le même correspondant à lettrage broches de l’Arduino. Il s’agit pour le bus i2c.
Les autres broches ne sont pas utilisés.
J’ai monté le gyroscope sur un petit morceau de plastique par l’intermédiaire de deux petites vis (trous sont déjà percés sur le périphérique bien sûr). J’ai ensuite utilisé un pistolet à colle pour coller l’ensemble sur le châssis de la roue. Voici le programme de test du gyroscope. Il n’est pas alimenter les moteurs, simplement l’utiliser pour tester. Utiliser le moniteur de la série sur l’Arduino pour voir les sorties de gyroscope.
------------------------------------------------------------------------------------------------------------------
Démonstration de classe (I2Cdev) pour le périphérique I2C Arduino croquis pour la classe de MPU6050 à l’aide de DPM (MotionApps v2.0)
21/06/2012 par Jeff Rowberg
Mises à jour (j’espère) doivent toujours être disponibles à https://github.com/jrowberg/i2cdevlib
Changelog :
2013-05-08 - ajout du support de Fastwire sans soudure
-Ajout d’une remarque concernant l’étalonnage gyro
2012-06-21 - ajout de note sur Arduino 1.0.1 + erreur de compatibilité de Leonardo
2012-06-20 - FIFO améliorée déborder manutention et simplifié les processus lecture
2012-06-19 - totalement réarrangé le code d’initialisation DMP et simplification
2012-06-13 - extraire des données de gyro et accel de paquet de peps au lieu de lire directement
2012-06-09 - Difficulté cassé séquence lecture FIFO et interruption détection de modifications à la hausse
2012-06-05 - ajouter sortie de compensation de gravité initiale référence cadre accélération
-Ajouter fichier d’assistance maths 3D à esquisse, exemple DMP6
-Ajouter la sortie de Euler et lacet/tangage/roulis des formats de sortie
2012-06-04 - supprimer accel offset compensation pour de meilleurs résultats (Merci Sungon Lee)
2012-06-01 - la sensibilité du gyroscope fixe à 2000 deg/sec au lieu de 250
2012-05-30 - base travail d’initialisation de DMP
/* ============================================
Code de bibliothèque I2Cdev appareil est placé sous la licence MIT
Copyright (c) 2012 Jeff Rowberg
Permission est accordée, gratuitement, à toute personne obtenant une copie
de ce logiciel et les fichiers de documentation associée (le "logiciel"), pour faire face
dans le logiciel sans restriction, y compris sans s’y limiter, les droits
pour utiliser, copier, modifier, fusionner, publier, distribuer, concéder en sous-licence ou vendre
copies du logiciel et de permettre aux personnes à qui le logiciel est
meublé pour ce faire, les conditions suivantes :
L’avis de copyright ci-dessus et cette notification de permission doivent figurer dans
toutes les copies ou des parties importantes du logiciel.
LE LOGICIEL EST FOURNI « TEL QUEL », SANS GARANTIE D’AUCUNE SORTE, EXPRESSE OU
IMPLICITE, Y COMPRIS MAIS SANS S’Y LIMITER LES GARANTIES DE QUALITÉ MARCHANDE,
ADEQUATION A UN USAGE PARTICULIER ET DE NON-CONTREFAÇON. EN AUCUN CAS, LA
AUTEURS OU TITULAIRES DE DROITS D’AUTEUR SERA RESPONSABLE DE TOUTE RÉCLAMATION, DOMMAGE OU AUTRE
RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, DÉLICTUELLE OU AUTRE, DÉCOULANT DE,
D’OU EN RELATION AVEC LE LOGICIEL OU L’UTILISATION OU AUTRES TRANSACTIONS EN
LE LOGICIEL.
===============================================
*
/ I2Cdev et MPU6050 doivent être installés comme les bibliothèques, ou bien les fichiers .cpp/.h
pour les deux classes doivent être dans le chemin d’accès include de votre projet
#include « I2Cdev.h »
#include « MPU6050_6Axis_MotionApps20.h »
#include « MPU6050.h » / / pas nécessaire si vous utilisez MotionApps include file
Bibliothèque de fils Arduino est requis si I2Cdev I2CDEV_ARDUINO_WIRE mise en œuvre
est utilisé dans I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include « Wire.h »
#endif
adresse I2C de classe par défaut est 0x68
des adresses I2C spécifiques peuvent être passés comme un paramètre ici
AD0 faible = 0x68 (valeur par défaut pour SparkFun en petits groupes et un Comité d’évaluation InvenSense)
AD0 haute = 0x69
Mpu MPU6050 ;
MPU6050 mpu(0x69) ; <--utiliser pour AD0 haute
/* =========================================================================
Remarque : en plus de connexion 3.3V, GND, SDA et SCL, cette esquisse
dépend de la broche d’INT de la MPU-6050 étant reliée à de l’Arduino
broche d’interruption externe #0. Sur l’Arduino Uno et Mega 2560, c’est
broche de I/O numérique 2.
* ========================================================================= *
* =========================================================================
Remarque : Arduino v1.0.1 auprès de la Commission de Leonardo génère une erreur de compilation
Lorsque vous utilisez Serial.write (buf, len). La sortie de la théière utilise cette méthode.
La solution exige une modification dans le fichier USBAPI.h de l’Arduino, qui
est heureusement simple, mais ennuyeux. Cela sera corrigé dans la prochaine IDE
Communiqué. Pour plus d’informations, consultez ces liens :
http://Arduino.cc/forum/index.php/topic, 109987.0.h...
http://code.google.com/p/Arduino/issues/detail?id=...
* ========================================================================= */
Supprimez « OUTPUT_READABLE_QUATERNION » si vous voulez voir le réel
format de composants dans un [w, x, y, z] Quaternion (pas mieux pour l’analyse
sur une télécommande accueillir comme traitement ou quelque chose de bien)
#define OUTPUT_READABLE_QUATERNION
Supprimez « OUTPUT_READABLE_EULER » si vous voulez voir angles d’Euler
(en degrés) calculé à partir des quaternions venant de la FIFO.
Notez que les angles d’Euler souffrent de blocage de cardan (pour plus d’informations, consultez
http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_EULER
Supprimez « OUTPUT_READABLE_YAWPITCHROLL » si vous voulez voir le lacet
/ les angles de tangage/roulis (en degrés) calculé à partir des quaternions à venir
de la FIFO. Notez que cela nécessite aussi des calculs vectoriels gravité.
Notez également que les angles de lacet/tangage/roulis souffrent de blocage de cardan (pour
plus d’informations, voir : http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL
Supprimez « OUTPUT_READABLE_REALACCEL » si vous voulez voir accélération
composants avec gravité supprimés. Ce cadre de référence d’accélération est
pas rémunérés pour l’orientation, donc + X est toujours + X conformément à la
capteur, juste, sans les effets de la gravité. Si vous souhaitez que l’accélération
compenser l’orientation, nous OUTPUT_READABLE_WORLDACCEL à la place.
#define OUTPUT_READABLE_REALACCEL
Supprimez « OUTPUT_READABLE_WORLDACCEL » si vous voulez voir accélération
composants avec gravité retirée et modifiés pour le cadre mondial de
référence (lacet est par rapport à l’orientation initiale, depuis aucun magnétomètre
est présent dans ce cas). Pourrait être très pratique dans certains cas.
#define OUTPUT_READABLE_WORLDACCEL
Supprimez « OUTPUT_TEAPOT » si vous voulez sortie qui correspond à la
format utilisé pour la démo de théière InvenSense
#define OUTPUT_TEAPOT
#define LED_PIN 13 / / (Arduino est 13, Teensy est 11, Teensy ++ est 6)
bool blinkState = false ;
MPU/statut vars
bool dmpReady = false ; la valeur true si DMP init a réussi
uint8_t mpuIntStatus ; détient l’octet d’État réelle interruption de MPU
uint8_t devStatus ; retourne l’état après chaque opération de dispositif (0 = réussite,! 0 = erreur)
uint16_t packetSize ; attendre la taille de paquet DMP (valeur par défaut est 42 octets)
uint16_t fifoCount ; nombre d’octets tous actuellement de FIFO
uint8_t fifoBuffer [64] ; Tampon de stockage FIFO
orientation/motion vars
Quaternion q ; [w, x, y, z] conteneur de quaternion
VectorInt16 aa ; [x, y, z] accel Carrier
VectorInt16 aaReal ; [x, y, z] exempt de gravité accel Carrier
VectorInt16 aaWorld ; [x, y, z] monde-cadre accel Carrier
VectorFloat gravité ; [x, y, z] vecteur de la gravité
flotteur d’euler [3] ; [lb/po2, thêta, phi] conteneur angle d’Euler
flotteur ypr [3] ; [mouvement de lacet, tangage, rouler] lacet/tangage/roulis conteneur et gravité le vecteur
structure de paquet pour la démo de théière InvenSense
uint8_t teapotPacket [14] = {« $», 0 x 02, 0,0 0,0 0,0, 0,0, 0 x 00, 0 x 00, « \r », « \n »} ;
// ================================================================
=== ROUTINE DE DÉTECTION D’INTERRUPTION ===
// ================================================================
volatils bool mpuInterrupt = false ; indique si broche interruption MPU est passée en haut
void dmpDataReady() {}
mpuInterrupt = true ;
}
// ================================================================
=== PREMIÈRE INSTALLATION ===
// ================================================================
void setup() {}
Joignez-vous à bus I2C (I2Cdev bibliothèque ne fait pas automatiquement)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.Begin() ;
TWBR = 24 ; horloge de 400kHz I2C (200kHz si le CPU est de 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::Setup (400, true) ;
#endif
initialiser la communication série
(115 200 bauds choisi parce qu’il est nécessaire pour la sortie de la démo de théière, mais il a
vraiment à vous en fonction de votre projet)
Serial.Begin(115200) ;
while (!. Série) ; attendre pour le dénombrement de Leonardo, d’autres continuent immédiatement
Remarque : 8MHz ou processeurs plus lents de hôte, comme le Teensy @ 3,3 v ou Ardunio
Mini Pro cadencé à 3,3 v, ne peut pas gérer ce débit en bauds fiable en raison de
le calendrier de baud étant trop mal alignée avec les tiques de processeur. Vous devez utiliser
38400 ou plus lent dans ces cas, ou utiliser une sorte d’externe séparé
solution de cristal pour la minuterie de l’UART.
initialiser le périphérique
Serial.println (F ("initialisation I2C dispositifs...")) ;
MPU.Initialize() ;
vérifier la connexion
Serial.println (F ("Testing dispositif connexions...")) ;
Serial.println(MPU.testConnection() ? F("MPU6050 Connection successful"): F (« MPU6050 de connexion a échoué")) ;
Attendez de prêt
Serial.println (F (« \nSend tout caractère pour commencer la programmation du DMP et de démonstration: ")) ;
tandis que (Serial.available() & & Serial.read()) ; tampon vide
while (!. Serial.available()) ; attendre pour les données
tandis que (Serial.available() & & Serial.read()) ; tampon vide nouveau
charger et configurer DPM
Serial.println (F ("initialisation DMP...")) ;
devStatus = mpu.dmpInitialize() ;
fournir vos propres compensations gyro ici, mis à l’échelle de sensibilité min
mpu.setXGyroOffset(220) ;
mpu.setYGyroOffset(76) ;
mpu.setZGyroOffset(-85) ;
mpu.setZAccelOffset(1788) ; 1688 par défaut pour ma puce de test
Veillez à ce que cela a fonctionné (renvoie 0 si oui)
Si (devStatus == 0) {}
Allumez le DMP, maintenant qu’il est prêt
Serial.println (F (« activation DMP...")) ;
mpu.setDMPEnabled(true) ;
activer la détection d’interruption Arduino
Serial.println (F ("Enabling interrupt détection (Arduino interruption externe 0)...")) ;
attachInterrupt (0, dmpDataReady, RISING) ;
mpuIntStatus = mpu.getIntStatus() ;
donc la fonction principale de loop() sait qu’il est acceptable d’utiliser la valeur notre drapeau DMP prêt
Serial.println (F (DMP ready ! En attente de première interruption...")) ;
dmpReady = true ;
obtenir la taille du paquet DMP attendue pour comparaison ultérieure
packetSize = mpu.dmpGetFIFOPacketSize() ;
} else {}
ERREUR !
1 = charge de mémoire initiale a échoué
2 = DMP configuration mises à jour a échoué
(si ça va casser, habituellement le code sera 1)
Serial.Print (F (« échec de l’initialisation de DMP (code ")) ;
Serial.Print(devStatus) ;
Serial.println(F(")")) ;
}
configurer des LED pour la sortie
pinMode (LED_PIN, sortie) ;
}
// ================================================================
=== BOUCLE DE PROGRAMME PRINCIPAL ===
// ================================================================
void loop() {}
Si la programmation n’a pas, n’essayez pas de faire n’importe quoi
Si (! dmpReady) return ;
attendre pour interruption MPU ou extra paquet (s) disponibles
tandis que (! mpuInterrupt & & fifoCount < packetSize) {}
autres trucs de comportement de programme ici
// .
// .
// .
Si vous êtes vraiment paranoïaque vous pouvez tester fréquemment entre autre
trucs pour voir si mpuInterrupt est vrai et dans l’affirmative, « break; » de la
boucle while() pour traiter immédiatement les données MPU
// .
// .
// .
}
réinitialiser l’indicateur d’interruption et obtenir les octets INT_STATUS
mpuInterrupt = false ;
mpuIntStatus = mpu.getIntStatus() ;
obtenir le décompte actuel de FIFO
fifoCount = mpu.getFIFOCount() ;
vérification de dépassement de capacité (cela ne devrait jamais arriver sauf si notre code est trop inefficace)
Si ((mpuIntStatus & 0x10) || fifoCount == 1024) {}
réinitialiser afin que nous puissions continuer proprement
mpu.resetFIFO() ;
Serial.println (F (« dépassement de la FIFO!")) ;
dans le cas contraire, recherchez les interrupt prêt de DMP données (cela se produit fréquemment)
} ElseIf (mpuIntStatus & 0 x 02) {}
Attendez la longueur correcte de données disponibles, devrait être très courte attente
tandis que (fifoCount < packetSize) fifoCount = mpu.getFIFOCount() ;
lire un paquet de FIFO
mpu.getFIFOBytes (fifoBuffer, packetSize) ;
suivre le comte FIFO ici dans le cas où il y a > 1 paquet disponible
(Ceci nous permet immédiatement lire la suite sans attendre une interruption)
fifoCount = packetSize ;
#ifdef OUTPUT_READABLE_QUATERNION
afficher les quaternions sous forme matricielle facile: w x y z
mpu.dmpGetQuaternion (& q, fifoBuffer) ;
Serial.Print("quat\t") ;
Serial.Print(q.w) ;
Serial.Print("\t") ;
Serial.Print(q.x) ;
Serial.Print("\t") ;
Serial.Print(q.y) ;
Serial.Print("\t") ;
Serial.println(q.z) ;
#endif
#ifdef OUTPUT_READABLE_EULER
afficher les angles d’Euler en degrés
mpu.dmpGetQuaternion (& q, fifoBuffer) ;
mpu.dmpGetEuler (euler, & q) ;
Serial.Print("euler\t") ;
Serial.Print (euler [0] * 180/M_PI) ;
Serial.Print("\t") ;
Serial.Print (euler [1] * 180/M_PI) ;
Serial.Print("\t") ;
Serial.println (euler [2] * 180/M_PI) ;
#endif
#ifdef OUTPUT_READABLE_YAWPITCHROLL
afficher les angles d’Euler en degrés
mpu.dmpGetQuaternion (& q, fifoBuffer) ;
mpu.dmpGetGravity (gravité, & q) ;
mpu.dmpGetYawPitchRoll (ypr, & q et gravité) ;
Serial.Print("ypr\t")
Serial.Print (ypr [0] * 180/M_PI) ;
Serial.Print("\t") ;
/////////////////////////////////////////////////////////////////////////////////////////
/ C’est le Gyro angle ypr [1], nous utilisons celle-ci pour le chariot de la pendule et convertir en degrés dans la ligne ci-dessous.
Assurez-vous que vous obtenez près de zéro lorsque le chariot est vertical.b n
Serial.Print (ypr [1] * 180/M_PI) ;
Serial.Print("\t") ;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println (ypr [2] * 180/M_PI) ;
#endif
#ifdef OUTPUT_READABLE_REALACCEL
afficher l’accélération réelle, ajustée pour supprimer la gravité
mpu.dmpGetQuaternion (& q, fifoBuffer) ;
mpu.dmpGetAccel (& aa, fifoBuffer) ;
mpu.dmpGetGravity (gravité, & q) ;
mpu.dmpGetLinearAccel (& aaReal, & aa et la gravité) ;
Serial.Print("areal\t") ;
Serial.Print(aaReal.x) ;
Serial.Print("\t") ;
Serial.Print(aaReal.y) ;
Serial.Print("\t") ;
Serial.println(aaReal.z) ;
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
afficher l’accélération initiale de monde-frame, ajustée pour supprimer la gravité
et l’orientation connue basée sur rotation de quaternion
mpu.dmpGetQuaternion (& q, fifoBuffer) ;
mpu.dmpGetAccel (& aa, fifoBuffer) ;
mpu.dmpGetGravity (gravité, & q) ;
mpu.dmpGetLinearAccel (& aaReal, & aa et la gravité) ;
mpu.dmpGetLinearAccelInWorld (& aaWorld, & aaReal, & q) ;
Serial.Print("aworld\t") ;
Serial.Print(aaWorld.x) ;
Serial.Print("\t") ;
Serial.Print(aaWorld.y) ;
Serial.Print("\t") ;
Serial.println(aaWorld.z) ;
#endif
#ifdef OUTPUT_TEAPOT
afficher les valeurs quaternion en format démo InvenSense théière :
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] ++ ; le packetCount, boucles à 0xFF exprès
#endif
LED pour indiquer l’activité de cligner des yeux
blinkState =! blinkState ;
digitalWrite (LED_PIN, blinkState) ;
}
}