Deze keer bouwen we aan een digitaal kompas. Om dit te doen, hebben we een Arduino-NanoA GY-271-module en een RGB LED-ring. We kunnen het afgewerkte apparaat gewoon voorzien van een 9V batterijblok.
Circuit:
Het circuit is heel eenvoudig. De GY-271 module en de LED ring worden geleverd via 5V. Sluit Dus GND aan en sluit Vcc aan op 5V op de nano. De I2C bus van de GY-271 is aangesloten op de I2C connectoren van de Nano. A4 met SDA en A5 met SCL. Voor de LED-ring verbinden we de signaallijn op D4 op de nano. Voor de voeding verbinden we de negatieve paal van het accublok met GND en de 9V plus paal via een schakelaar met Vin op de nano.
De code
De meeste bestaande bibliotheken zijn voor de HMC5883 die niet alleen een ander I2C-adres heeft, maar ook een andere registeropdracht. Maar aangezien de controle van de QMC5883L is zeer eenvoudig, heb ik afgezien van het gebruik van een bibliotheek deze keer.
We kunnen eenvoudig gebruik maken van de functies van de Arduino I2C bibliotheek.
In soft reset stellen we de controleregisters 10 en 11 in. Interessant is het besturingsregister 9 waarmee u de belangrijke parameters van de QMC5883L instellen.
De bedrijfsmodus stand-by of continue meting. Met de uitvoergegevenssnelheid u bepalen hoeveel metingen per seconde u moet uitvoeren. 10 Hz, 50 Hz, 100 Hz of 200 Hz kunnen worden geselecteerd. Hoe hoger deze frequentie, hoe hoger het stroomverbruik. Gevoeligheid (rang RNG) geeft de magnetische fluxdichtheid voor volledige uitslag aan. Hier u kiezen voor +/- 2 Gauss of +/- 8 Gauss. Met de hogere gevoeligheid, moet worden opgemerkt dat de storende invloed van vreemde velden toeneemt. Ten slotte u de oversampling-snelheid instellen. Het is 64, 128, 256 en 512 verstelbaar. Een hogere waarde vermindert de filterbandbreedte en dus hinderlijkgeluid, maar ook het stroomverbruik neemt af.
Als u meer details wilt weten, u ze vinden in de QMC5883L-gegevensblad .
Uit de leeswaarden voor x en y wordt de hoek naar het aardmagnetisch veld bepaald. Deze waarde is slechts halfnauwkeurig als de module zo horizontaal mogelijk wordt gehouden. Voor het display wordt de hoek omgezet van +/- 180 graden naar 0 tot 360 graden en vervolgens gedeeld door 30, zodat we 12 secties krijgen die overeenkomen met de 12 LED's van de ring. De afwijking wordt vervolgens gebruikt om de helderheid van de LED te bepalen. als de afwijking negatief is, wordt de bestaande LED en anders de volgende LED ingeschakeld. Als de waarde er tussenin zit, gloeien beide LED's even helder.
Voor de LED-ring hebben we de NeoPixelBus.h bibliotheek nodig. De bibliotheek voor de I2C Bus Wire.h maakt deel uit van de standaard installatie.
Aandachtspunt: Ik kreeg een interne compiler fout tijdens het samenstellen. Internet zoekopdrachten bleek dat dit een probleem is met de nieuwste Arduino hardware bibliotheek. Een installatie van de vorige versie, het probleem opgelost. Selecteer in de board manager gewoon versie 1.6.22 in plaats van de huidige 1.6.23 en klik op Installeren.
#include <Draad.H> I2C Arduino Bibliotheek #include <NeoPixelBus NeoPixelBus.H> bibliotheek voor led strip I2C-adres van de QMC5883L #define Addr 0x0d waarden voor het Controleregister QMC5883 1 bedrijfsmodus #define Mode_Standby 0b0000000000 #define Mode_Continuous 0b00000001 Outputgegevenssnelheid #define ODR_10Hz 0b0000000000 #define ODR_50Hz 0b00000100 #define ODR_100Hz 0b00001000 #define ODR_200Hz 0b00001100 Meetbereik #define RNG_2G 0b0000000000 #define RNG_8G 0b00010000 Over bemonsteringssnelheid #define OSR_512 0b0000000000 #define OSR_256 0b01000000 #define OSR_128 0b100000000 #define OSR_64 0b111000000 enkele constanten voor de LED-ring #define MAXBRIGHT MAXBRIGHT 64 #define LEDCOUNT 12 #define SIGNAALVASTSPELD 4 initialiseer ledstripdriver NeoPixelBus NeoPixelBus<NeoGrbFeature NeoGrbFeature, Neo800KbpsMethode> Strip(LEDCOUNT, SIGNAALVASTSPELD); kleur zwart definiëren om leds uit te schakelen Rgbcolor Zwarte(0,0,0); functie om gegevens te schrijven in een register op QMC5883L Void writeRegister(uint8_t Reg, uint8_t Val){ Draad.beginTransmissie(Addr); beginnen te praten Draad.Schrijven(Reg); Draad.Schrijven(Val); Draad.eindTransmissie(); } functie om resultaten van QMC5883L te lezen Void leesGegevens(uint16_t * X, uint16_t * Y, uint16_t * Z) { Draad.beginTransmissie(Addr); Draad.Schrijven(0x00); Draad.eindTransmissie(); Draad.verzoekVan(Addr, 6); *X = Draad.Lezen(); LSB x *X |= Draad.Lezen() << 8; MSB x *Y = Draad.Lezen(); LSB z *Y |= Draad.Lezen() << 8; MSB z *Z = Draad.Lezen(); LSB y *Z |= Draad.Lezen() << 8; MSB y } functie om het controleregister 1 op QMC5883L in te stellen Void CtrlRegister instellen(uint8_t overSampling, uint8_t Bereik, uint8_t gegevensRate, uint8_t Modus) { writeRegister(9,overSampling | Bereik | gegevensRate | Modus); } functie om QMC5883L te resetten Void softReset() { writeRegister(0x0a,0x80); writeRegister(0x0b,0x01); } hardware voorbereiden Void Setup(){ Seriële.Beginnen(9600); Draad.Beginnen(); Seriële.println("Begin"); softReset(); CtrlRegister instellen(OSR_128,RNG_2G,ODR_100Hz,Mode_Continuous); Seriële.println("init gedaan"); } Void Lus(){ Int X,Y,Z; drievoudige asgegevens Float Azimut; uint16_t azi; azimut alleen positiv als geheel getal uint8_t led1,led2; uint8_t val1,val2; int8_t Diff; hiermee worden alle neopixels teruggezet naar een off-status Strip.Beginnen(); Strip.Toon(); leesGegevens(&X, &Y, &Z); gegevens van sensor lezen de hoek tussen x en y berekenen wechange de signe sinds leds in de ring besteld met de klok mee Azimut = -atan2(Y,X) * 180.0/Pi; voeg 180 graden toe om alleen positieve waarden te krijgen azi = Azimut+180; we hebben 12 leds elke 30 graden led1=(azi/30) % 12; we berekenen het verschil tussen de oorspronkelijke hoek en led hoek geeft bij maximaal +/- 30 Diff = azi - led1 *30; we willen zowel leds links als rechts laten zien aan de oorspronkelijke hoek Als (Diff>0) { als verschil positiv is stellen we de volgende led led2 = led1++; Als (led2 > 11) led2 = 0; val1 = Diff; val2 = 30-Diff; } Anders { als het verschil negatief is, stellen we de vorige led led2 = led1--; Als (led2<0) led2 = 11; val1 = -Diff; val2 = 30+Diff; } schakel alle leds uit Strip.ClearTo(Zwarte); stel de wo leds op de berekende waarde met rood Rgbcolor col1(val1*MAXBRIGHT MAXBRIGHT/30,0,0); Strip.SetPixelColor(led1,col1); Rgbcolor col2(val2*MAXBRIGHT MAXBRIGHT/30,0,0); Strip.SetPixelColor(led2,col2); gegevens naar de ledring verzenden Strip.Toon(); Waarden weergeven op seriële regel Seriële.Afdrukken("X Waarde: "); Seriële.println(X); Seriële.Afdrukken("Y Waarde: "); Seriële.println(Y); Seriële.Afdrukken("Z Waarde: "); Seriële.println(Z); Seriële.Afdrukken(Richtung: "); Seriële.Afdrukken(Azimut); Seriële.println("°"); Seriële.Afdrukken("LED 1 = "); Seriële.Afdrukken(led1); Seriële.Afdrukken(" helder = "); Seriële.println(val1); Seriële.Afdrukken("LED 2 = "); Seriële.Afdrukken(led2); Seriële.Afdrukken(" helder = "); Seriële.println(val2); Seriële.println(); wacht 1 seconde Vertraging(1000); }
Viel Spass mit dem Kompass
Gerald
13 Reacties
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”.