Cette fois, nous construisons une boussole numérique. Pour cela, nous en avons besoin Arduino nano, un Module GY-271 et un Anneau LED RGB. Nous pouvons simplement fournir à l'appareil fini un bloc de batterie 9V.
Circuit:
Le circuit est très simple. Le module GY-271 et l'anneau LED sont alimentés via 5V. Alors connectez GND et connectez Vcc à 5V sur le Nano. Le bus I2C du GY-271 est connecté aux connecteurs I2C du Nano. A4 avec SDA et A5 avec SCL. Pour l'anneau LED, nous connectons la ligne de signal à D4 sur le nano. Pour l'alimentation, nous connectons le pôle négatif du bloc de batterie avec GND et le pôle positif 9V via un interrupteur avec Vin sur le Nano.
Le code
La plupart des bibliothèques existantes sont destinées au HMC5883 qui a non seulement une adresse I2C différente mais également une affectation de registre différente. Cependant, comme le contrôle du QMC5883L est très simple, je n'ai pas utilisé de bibliothèque cette fois.
Nous pouvons facilement utiliser les fonctions de la bibliothèque Arduino I2C.
Dans le cas d'une réinitialisation logicielle, nous définissons les registres de contrôle 10 et 11. Intéressant est le registre de contrôle 9 avec lequel vous pouvez définir les paramètres importants du QMC5883L.
Le mode de fonctionnement stand-by ou mesure continue. Avec le débit de données de sortie, vous pouvez déterminer combien de mesures par seconde doivent être effectuées. 10 Hz, 50 Hz, 100 Hz ou 200 Hz peuvent être sélectionnés. Plus cette fréquence est élevée, plus la consommation d'énergie est élevée. La sensibilité (rang RNG) indique la densité de flux magnétique pour une déviation complète. Ici, +/- 2 Gauss ou +/- 8 Gauss peuvent être sélectionnés. Avec une sensibilité plus élevée, il convient de noter que l'influence perturbatrice des champs externes augmente. Enfin, vous pouvez définir le taux de suréchantillonnage. 64, 128, 256 et 512 peuvent être définis. Une valeur plus élevée réduit la bande passante du filtre et donc le bruit gênant, mais cela augmente également la consommation d'énergie.
Si vous souhaitez en savoir plus, vous pouvez les trouver dansFiche technique QMC5883L .
L'angle par rapport au champ magnétique terrestre est déterminé à partir des valeurs lues pour x et y. Cette valeur n'est exacte qu'à moitié si le module est maintenu aussi horizontal que possible. Pour l'affichage, l'angle est converti de +/- 180 degrés à 0 à 360 degrés puis divisé par 30 de sorte que nous obtenons 12 sections correspondant aux 12 LED de l'anneau. L'écart est ensuite utilisé pour déterminer la luminosité de la LED. si l'écart est négatif, la LED en face et la LED suivante sont également allumées. Si la valeur se situe entre les deux, les deux LED s'allument de manière égale.
Pour l'anneau LED, nous avons besoin de la bibliothèque NeoPixelBus.h. La bibliothèque du bus I2C Wire.h fait partie de l'installation standard.
Attention note importante:J'ai eu une erreur de compilation interne lors de la compilation. Des recherches sur Internet ont montré que c'est un problème avec la dernière bibliothèque matérielle Arduino. L'installation de la version précédente a résolu le problème. Sélectionnez simplement la version 1.6.22 dans le gestionnaire de cartes au lieu de la version 1.6.23 actuelle et cliquez sur Installer.
#include <Wire.h> // Bibliothèque Arduino I2C #include <NeoPixelBus.h> // bibliothèque pour bande led // Adresse I2C du QMC5883L #define ADDR 0x0d // valeurs pour le registre de contrôle QMC5883 1 // mode de fonctionnement #define Mode_Standby 0b00000000 #define Mode_Continuous 0b00000001 // Débit de données en sortie #define ODR_10Hz 0b00000000 #define ODR_50Hz 0b00000100 #define ODR_100Hz 0b00001000 #define ODR_200Hz 0b00001100 // Plage de mesure #define RNG_2G 0b00000000 #define RNG_8G 0b00010000 // Taux d'échantillonnage excessif #define OSR_512 0b00000000 #define OSR_256 0b01000000 #define OSR_128 0b10000000 #define OSR_64 0b11000000 // quelques constantes pour l'anneau LED #définir MAXBRIGHT 64 #définir LEDCOUNT 12 #définir SIGNALPIN 4 // initialiser le pilote de bande LED NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> bande(LEDCOUNT, SIGNALPIN); // définir la couleur noire pour éteindre les leds RgbColor noir(0,0,0); // fonction pour écrire des données dans un registre sur QMC5883L néant writeRegister(uint8_t reg, uint8_t val){ Câble.beginTransmission(ADDR); //commence à parler Câble.écrire(reg); Câble.écrire(val); Câble.endTransmission(); } // fonction pour lire les résultats de QMC5883L néant readData(uint16_t * X, uint16_t * y, uint16_t * z) { Câble.beginTransmission(ADDR); Câble.écrire(0x00); Câble.endTransmission(); Câble.demande de(ADDR, 6); *X = Câble.lis(); // LSB x *X |= Câble.lis() << 8; // MSB x *y = Câble.lis(); // LSB z *y |= Câble.lis() << 8; // MSB z *z = Câble.lis(); // LSB y *z |= Câble.lis() << 8; // MSB y } // fonction pour définir le registre de contrôle 1 sur QMC5883L néant setCtrlRegister(uint8_t suréchantillonnage, uint8_t intervalle, uint8_t débit de données, uint8_t mode) { writeRegister(9,suréchantillonnage | intervalle | débit de données | mode); } // fonction pour réinitialiser QMC5883L néant redémarrage en douceur() { writeRegister(0x0a,0x80); writeRegister(0x0b,0x01); } // préparer le matériel néant installer(){ En série.commencer(9600); Câble.commencer(); En série.println("Début"); redémarrage en douceur(); setCtrlRegister(OSR_128,RNG_2G,ODR_100Hz,Mode_Continuous); En série.println("init done"); } néant boucle(){ int X,y,z; // données à trois axes flotte azimut; uint16_t azi; // azimut uniquement positif comme entier uint8_t led1,led2; uint8_t val1,val2; int8_t diff; // cela réinitialise tous les néopixels à un état désactivé bande.Commencer(); bande.Spectacle(); readData(&X, &y, &z); // lire les données du capteur // calcule l'angle entre x et y // change le signe puisque les leds de l'anneau sont ordonnées dans le sens horaire azimut = -atan2(y,X) * 180.0/PI; // ajoute 180 degrés pour n'obtenir que des valeurs positives azi = azimut+180; // nous avons 12 leds tous les 30 degrés led1=(azi/30) % 12; // on calcule la différence entre l'angle d'origine // et l'angle led donne au maximum +/- 30 diff = azi - led1 *30; // nous voulons montrer les deux leds à gauche et à droite // angle d'origine si (diff>0) { // si la différence est positive, nous mettons la led suivante led2 = led1++; si (led2 > 11) led2 = 0; val1 = diff; val2 = 30-diff; } autre { // si la différence est négative, nous mettons la led précédente led2 = led1--; si (led2<0) led2 = 11; val1 = -diff; val2 = 30+diff; } // éteindre toutes les leds bande.ClearTo(noir); // met les wo leds sur la valeur calculée avec du rouge RgbColor col1(val1*MAXBRIGHT/30,0,0); bande.SetPixelColor(led1,col1); RgbColor col2(val2*MAXBRIGHT/30,0,0); bande.SetPixelColor(led2,col2); // envoie des données à l'anneau led bande.Spectacle(); // Afficher les valeurs sur la ligne série En série.impression("Valeur X:"); En série.println(X); En série.impression("Valeur Y:"); En série.println(y); En série.impression("Valeur Z:"); En série.println(z); En série.impression("Richtung:"); En série.impression(azimut); En série.println("°"); En série.impression("LED 1 ="); En série.impression(led1); En série.impression("lumineux ="); En série.println(val1); En série.impression("LED 2 ="); En série.impression(led2); En série.impression("lumineux ="); En série.println(val2); En série.println(); // attend 1 seconde retard(1000); }
Viel Spass mit dem Kompass
Gerald
13 commentaires
Roland
Vorsicht mit der I2C-Adresse! Es sind auch Module mit der Adresse 0×1E (ursprüngliche Standardadresse) im Umlauf. Das Datenblatt von Honeywell enthält 0×3C und 0×3D.
Unter https://playground.arduino.cc/Main/I2cScanner/ findet man einen einfachen Adressscanner
Simon
Hallo, muss das Modul nicht kalibriert werden? Bei mir zeigt er nur 4 LEDs an (Ring getestet) und liefert utopische Werte im Serial Monitor.
LG
Simon
Rüdiger Sachse
Ich habe mir den GY-271 besorgt, um mein (Arduino)-Autopilot-Projekt zu verbessern.
Normalerweise ist der AP durchaus in der Lage einen stabilen Kurs zu einem Waypoint zu fahren. Die Navigationsdaten bekommet er von einem GPS-Plotter. Peilung und Crosstrack-Error sind kein Problem, da sich die Werte relativ langsam ändern, aber der aktuelle Kurs und insbesondere die schnelle Kursänderung werden nur verzögert (alle 2-3 Sek) ausgegeben. Das Schiff muss eine gewisse Strecke fahren um den GPS-basierten Kurs zu erhalten. Bei langsamer Fahrt wird die Berechnung immer ungenauer. Mit dem GY-Modul hoffe ich besseren Werte für die schnellen Kursänderungen und damit ein besseres Steuerverhalten zu erzielen.
Hier ist mir etwas merkwürdiges aufgefallen! Die Werte für die X-Y-Z-Achsen werden mit Hilfe der Arduino-Lib Wire.h ausgelesen.
Die Registerinhalte stimmen nicht mit dem Datenblatt überein, Z und Y sind vertauscht!!
code:
x = Wire.read()<<8; //X msb //16bit int X-Achse x |= Wire.read(); //X lsb z = Wire.read()<<8; //Z msb //nach datenblatt Y-Achse ?? z |= Wire.read(); //Z lsb y = Wire.read()<<8; //Y msb //nach datenblatt Z-Achse ?? y |= Wire.read(); y+=180; //Y lsb // +180 addieren ??Wire.requestFrom(I2C_address, 6); //6 bytes lesen
Die X-Werte liegen symmetrisch zur 0-Linie, bei den Y-Werten muss 180 addiert werden.
Die Z-Werte sind wesentlich höher (bis 900).
Beim Drehen des Moduls um 360 Grad auf dem platten Tisch erhalte ich für X und Y zwei schöne sinusförmige Kurven mit 90 Grad Phasenversatz (COS für X, SIN für Y). Die Minima und Maxima liegen wie zu erwarten bei je 0 (bzw 360), 90, 180 und 270 Grad bezogen auf magnetisch Nord. Die Kurven sind allerdings nicht symmetrisch zur 0-Linie (bei jedem Chip anders), daher muss der Offset-Wert ermittelt werden. Man dreht einen Vollkreis und nimmt die Mitte von Min und Max.
Daraus lässt sich der Radiant, bzw Kompasswinkel mit der Funktion
rad= atan2(y,x) errechnen und bekommt eine tadellose Kompassdarstellung.
Jetzt muss ich nur noch die Einflüsse durch Rollbewegungen kompensieren, aber das ist eine andere Geschichte…
Gerald
Hallo Sven offenbar hast Du ein Board mit einem HMC5883. Der Sketch ist für den QMC5883L wie er auf dem Modul von AZ-Delivery verbaut ist. Der HMC5883 hat eine andere I2C Adresse. Folgende Änderung im Sketch ist notwendig damit der HMC5883 funktioniert.
//I2C address of the QMC5883L
#define ADDR 0×17
Dann sollte es funktionieren.
sven
ich habe das problem,
X Value: -1
Y Value: -1
Z Value: -1
Richtung: 135.00°
LED 1 = 11 bright = 15
LED 2 = 10 bright = 15
es zeigt immer die selben werte an.
Beim arduino example HMC5883L geht es.
Ulrich Engel
Hallo Gerald,
nun funktioniert der Kompass wie gewünscht. Es waren aber Änderungen notwendig.
Erst einmal habe ich, auf Anraten eines “Profis”, das GY-271 Modul etwas (8-10 cm) vom Ring und dem Nano entfernt, um Magnetfeldeinflüsse durch Strom zu verhindern. Dann habe ich das Modul untersucht und festgestellt, dass es sich nicht um einen “original/generic” Chip handelt. Man erkennt dieses Original am Aufdruck auf dem kleinen schwarzen Chip auf dem Modul. Beim Original steht “L5883 2120”. Beim Fake, der nicht funktioniert steht “DA 5883 8012”.
Ulrich Engel
Hallo Gerald,
vielen Dank für die Antwort. Ich habe noch einmal gemäß Deiner Beschreibung die Verdrahtung kontrolliert. Dann habe ich den Kompass von Google Maps auf dem Handy eingeschaltet. Der zeigt stabil nach N wenn ich das Handy auf dem Tisch flach drehe.
Eigentlich hatte ich dieses auch für die LEDs im Ring erwartet. Es sollten doch die leuchtenden LEDs (2 Stück) beim flachen Drehen der Schaltung (x-Y des Sensors) immer in die gleiche Richtung zeigen. Nämlich nach N.
Das ist bei mir leider nicht der Fall. Es bleiben immer die gleichen LEDs an und drehen mit.
Ich habe noch kein Projekt mit einem Nano gemacht. Ist es normal, dass der schwarze Chip sehr heiß wird?
Viele Grüße aus Berlin
Ulli
Gerald
Hallo Ulrich
Ich habe jetzt die Schaltung nochmals aufgebaut. Beim Erdmagnetfeld sollten die Werte für X und Y in einem Bereich von +/- 2000 liegen und für Z bei -3000 bis -5000. Dein Y Wert ist ziemlich konstant bei etwa -6000. Ich vermute daher, dass ein externes Magnetfeld in Y Richtung vorhanden ist, das den Einfluß des Erdmagnetfeldes überdeckt. Du solltest mal die Schaltung mit Batterie betreiben und möglichst von Störquellen (Elektrogeräte) entfernt testen.
Ulrich Engel
Hallo Gerald,
eigentlich hatte ich erhofft, dass ich Euren Erfahrungsschatz nutzen kann und Unterstützung bei meinem Problem erhalte. Ich würde gerne das Projekt fertig bekommen und bei meinem Geo-Cacher (Projekt von Euch) nutzen.
Viele Grüße
Ulli aus Berlin
Ulrich Engel
Hallo,
super Idee. Tolle Ergänzung zum Tutorial “Geocaching”.
Kompilieren und Hochladen (wenn man auf Old Bootloader umschaltet) funktioniert fehlerfrei.
Mein Problem ist leider, dass die Daten, die auf den serial monitor ausgegeben werden sehr wir sind. Auch bleiben die LEDs immer an der gleichen Stelle an, wenn ich den ganzenAufbau drehe.
Hier ein Auszug. Wo könnte ich den die Ergebnisliste als Datei posten?
Start
init done
X Value: 0Y Value: 0Z Value: 0Richtung:
0.00°LED 1 = 5 bright = 0LED 2 = 6 bright = 30
X Value: -1187Y Value: -8795Z Value: -6610Richtung:
97.69°LED 1 = 10 bright = 7LED 2 = 9 bright = 23
X Value: -1177Y Value: -8857Z Value: -6552Richtung:
97.57°LED 1 = 10 bright = 7LED 2 = 9 bright = 23
X Value: -1245Y Value: -8765Z Value: -6572Richtung:
98.08°LED 1 = 10 bright = 8LED 2 = 9 bright = 22
X Value: -1270Y Value: -6092Z Value: -6647Richtung:
101.78°LED 1 = 10 bright = 11LED 2 = 9 bright = 19
X Value: -1265Y Value: -5975Z Value: -6615Richtung:
101.95°LED 1 = 10 bright = 11LED 2 = 9 bright = 19
X Value: -1335Y Value: -5960Z Value: -6662Richtung:
102.63°LED 1 = 10 bright = 12LED 2 = 9 bright = 18
X Value: -1317Y Value: -5950Z Value: -6657Richtung:
102.48°LED 1 = 10 bright = 12LED 2 = 9 bright = 18
X Value: -1355Y Value: -6017Z Value: -6720Richtung:
102.69°LED 1 = 10 bright = 12LED 2 = 9 bright = 18
X Value: -1302Y Value: -6042Z Value: -6630Richtung:
102.16°LED 1 = 10 bright = 12LED 2 = 9 bright = 18
X Value: -4462Y Value: -6542Z Value: -6672Richtung:
124.30°LED 1 = 11 bright = 4LED 2 = 10 bright = 26
X Value: -4375Y Value: -6430Z Value: -6657Richtung:
124.23°LED 1 = 11 bright = 4LED 2 = 10 bright = 26
X Value: -4197Y Value: -6415Z Value: -6695Richtung:
123.19°LED 1 = 11 bright = 3LED 2 = 10 bright = 27
X Value: -4232Y Value: -6390Z Value: -6705Richtung:
123.52°LED 1 = 11 bright = 3LED 2 = 10 bright = 27
X Value: -4232Y Value: -6425Z Value: -6732Richtung:
123.37°LED 1 = 11 bright = 3LED 2 = 10 bright = 27
Könnte dieses an dem Sensor liegen? Wie ich gelesen habe, werden ja oft auch unter gleichem Namen auch Nicht-Originale angeboten, die man nur am Aufdruck auf dem Chip identifizieren kann.
Ich habe wohl so einen “Fake” erwischt.
Wolfgang
Danke Gerald,
ich habe die Fehler gefunden.
Das Hochladen des Programmes ohne zusätzliches Modul hat es dann gebracht.
Frohe Ostern an alle
Wolfgang
Gerald
Hallo Wolfgang, die Fehlermeldung “stray 302” bedeutet dass ein Sonderzeichen im code vorkommt. Es gibt dazu einen sehr ausführlichen Blog Beitrag, der zeigt wie man diesen Fehler finden und beheben kann. Suche einfach nach “kodierungsfehler-schnell-beheben”.
Im Bereich Posts findest Du dann den Link.
Wolfgang Butenhoff
Hallo,
bei der Programmzeile:
setCtrlRegister(OSR_128,RNG_2G,ODR_100Hz,Mode_Continuous);
bekomme ich immer wieder die Meldung: " stray’ \302’ in program"
Wo ist der Fehler? Der Hinweis mit Version 1.6.22 ist berücksichtigt.
Für die Software brauche ich Hilfe ….die Hardware ist bestimmt richtig “verdrahtet”.