Forum: Mikrocontroller und Digitale Elektronik HMC5883L Kompassmodul - Ich bin ratlos.


von Marco H. (bluebird1988)


Lesenswert?

Hallo!
Ich versuche jetzt seit zwei Wochen des HMC5883L Kompassmodul mit meinem 
Raspberry über die wiringpi und I2C zum Laufen zu bekommen - leider ohne 
Erfolg.
Ich habe hier schon viel gelesen und habe viel versucht, nur komme ich 
nicht an sinnvolle Werte.
Was sich mir nicht erschließt, ist zum Einen, wie ich an den Wert zur 
Skalierung komme. Ich versteh es einfach nicht. Brett vorm Kopf?
Zum Anderen komme ich an die Tilt-Kompensierung nicht heran.
Dazu brauche ich die skalierten Werte =(

Hier mal mein Versuchscode. Nicht gerade schick, aber zumindest gibt er 
Werte aus.
1
#include <stdlib.h>
2
#include <iostream>
3
#include <wiringPi.h>
4
#include <wiringPiI2C.h>
5
#include <cmath>
6
7
8
using namespace std;
9
int8_t fd;
10
11
void test(void)
12
{
13
    fd=wiringPiI2CSetup(0x1e);                  // Filedescriptor erstellen
14
    wiringPiI2CWriteReg8(fd,0x00, 0x11);        // positive bias (feld)
15
    wiringPiI2CWriteReg8(fd,0x01, 0x20);        // gain +-1.3 Gauß
16
    wiringPiI2CWriteReg8(fd,0x02, 0x01);        // single-measurement-mode
17
}
18
19
void init(void)
20
{
21
    fd=wiringPiI2CSetup(0x1e);                  // Filedescriptor erstellen
22
    wiringPiI2CWriteReg8(fd,0x00, 0x70);        // Durchschnitt aus 8 Werten
23
    wiringPiI2CWriteReg8(fd,0x01, 0x04);        // gain +-1.3 Gauß
24
    wiringPiI2CWriteReg8(fd,0x02, 0x00);        // continous-measurement mode
25
26
}
27
28
int main()
29
{
30
31
    int16_t data, XMsb=0, XLsb=0, YMsb=0, YLsb=0, ZMsb=0, ZLsb=0, x_out, y_out, z_out,
32
            x_offset, y_offset, z_offset;
33
    float   xmin=0, ymin=0, zmin=0, xmax=0, ymax=0, zmax=0, wmin=1000.0, wmax=0, bearing=100.0;
34
    double winkel;
35
    float grad, xh, yh, bear;
36
    init();
37
    //test();
38
    cout << "Hello world!" << endl;
39
    cout << sizeof(fd) << endl;
40
    cout << fd << endl;
41
42
43
        /*
44
        cout << "XMsb: " << XMsb << endl;
45
        cout << "XLsb: " << XLsb << endl;
46
        cout << "YMsb: " << YMsb << endl;
47
        cout << "YLsb: " << YLsb << endl;
48
        cout << "ZMsb: " << ZMsb << endl;
49
        cout << "ZLsb: " << ZLsb << endl;
50
        */
51
52
    while(1)
53
    {
54
        x_offset = 126;
55
        y_offset = -128;
56
        z_offset = 125;
57
58
59
        XMsb = (wiringPiI2CReadReg16(fd, 0x03)) + (x_offset);
60
        //XLsb = wiringPiI2CReadReg8(fd, 0x04);
61
        YMsb = (wiringPiI2CReadReg16(fd, 0x05)) + (y_offset);
62
        //YLsb = wiringPiI2CReadReg8(fd, 0x06);
63
        ZMsb = (wiringPiI2CReadReg16(fd, 0x07)) + (z_offset);
64
        //ZLsb = wiringPiI2CReadReg8(fd, 0x08);
65
66
67
        cout << "XMsb: " << XMsb << endl;
68
        //cout << "XLsb: " << XLsb << "       " << x << endl;
69
        cout << "YMsb: " << YMsb << endl;
70
        //cout << "YLsb: " << YLsb << "       " << y << endl;
71
        cout << "ZMsb: " << ZMsb << endl;
72
        //cout << "ZLsb: " << ZLsb << "       " << z << endl;
73
74
75
        if (XMsb < xmin)
76
        {
77
            xmin = XMsb;
78
        }
79
        if (XMsb > xmax)
80
        {
81
            xmax = XMsb;
82
        }
83
        if (YMsb < ymin)
84
        {
85
            ymin = YMsb;
86
        }
87
        if (YMsb > ymax)
88
        {
89
            ymax = YMsb;
90
        }
91
        if (ZMsb < zmin)
92
        {
93
            zmin = ZMsb;
94
        }
95
        if (ZMsb > zmax)
96
        {
97
            zmax = ZMsb;
98
        }
99
        if (bearing < wmin)
100
        {
101
            wmin = bearing;
102
        }
103
        if (bearing > wmax)
104
        {
105
            wmax = bearing;
106
        }
107
108
        /*
109
        x_offset = (xmax + xmin) / 2;
110
        y_offset = (ymax + ymin) / 2;
111
        z_offset = (zmax + zmin) / 2;
112
113
114
        cout << "xmin: " << xmin << endl;
115
        cout << "xmax: " << xmax << endl;
116
        cout << "ymin: " << ymin << endl;
117
        cout << "ymax: " << ymax << endl;
118
        cout << "zmin: " << zmin << endl;
119
        cout << "zmax: " << zmax << endl;
120
        cout << "x offset: " << (xmax+xmin)/2 << endl;
121
        cout << "y offset: " << (ymax+ymin)/2 << endl;
122
        cout << "z offset: " << (zmax+zmin)/2 << endl << endl;
123
        */
124
125
        xh = XMsb * cos(XMsb) + YMsb * sin(XMsb) * sin(YMsb) - ZMsb * cos(YMsb) * sin(XMsb);
126
        yh = YMsb * cos(YMsb) + ZMsb * sin(YMsb);
127
128
        bear = atan2(yh,xh);
129
130
        cout << "bear: " << bear << endl;
131
132
133
134
        bearing = atan2(YMsb,XMsb);
135
136
        if (bearing < 0)
137
        {
138
        bearing += 2 * (3.14159265);
139
        }
140
        if (bearing > (2 * 3.14159265))     // ???
141
        {
142
        bearing -= 2 * (3.14159265);
143
        }
144
        bearing *= (180 / 3.4159265);
145
146
147
        cout << "Bearing: " << bearing << endl << endl;
148
        cout << "wmin: " << wmin << endl;
149
        cout << "wmax: " << wmax << endl;
150
        delay(100);
151
    }
152
153
154
    return 0;
155
}

Kann mir bitte bitte wer helfen? Ich weis nicht mehr weiter... =(

von Pandur S. (jetztnicht)


Lesenswert?

Welch Werte kommen denn ? Ausm Modul.

von Marco H. (bluebird1988)


Lesenswert?

Ich bin heute Abend gegen 21 Uhr wieder zu hause und werde dann mal die 
Werte posten.

Ich bekomme Rohdaten aus den Registern. Maximal immer um die 32700 (?).
Und das auf allen Achsen.
Aber diese sind dann leider nicht durchgehend von zB 0 bis ~32700, 
sonder immer mit Sprüngen verbunden, die sich mir nicht erklären.

Hier scheitert es warscheinlich auch an der Skalierung.
Anhand der Rohdaten errechne ich mir dann den Offset, aber wie gesagt, 
ich komme mir der Skalierung nicht klar. Es erschließt sich mir einfach 
nicht, wie ich richig skaliere und warum.

Das wird auch der Grund sein, warum ich keine verwertbaren Werte 
bekomme, die ich zur endgültigen Winkelberechnung brauche.
Ich hoffe, dass ich dann mit den Werten wieder selbstständig in der Lage 
bin, mir die richtigen Winkel berechnen zu lassen.

Und dann kann ich auch Feinheiten wie die Dekination einzubinden, aber 
so weit will ich im Moment noch gar nicht denken :D

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Die Werte aus dem Modul sind 16-Bit Zahlen im 2-er Komplement. D.h. 
dezimal läuft der Wertebereich von -32768 bis +32767.

Was du kriegst sind die Komponenten des Vektors der Feldlinien an dieser 
Position.
Wenn wir uns mal auf den 2D Fall konzentrieren, dann hast du einen 
Vektor in irgendeine Richtung. Du kriegst den Vektor in Form der 
Projektion auf die X-Achse bzw. in Form der Projektion auf die Y-Achse. 
Erinnere dich zurück an deine Schulzeit, als ihr dort mit Trigonometrie 
angefangen habt. Die Projektionen auf die Achsen sind genau das, was als 
Sinus bzw. Cosinus bekannt sind.
Deine Aufgabe ist genau anders herum. Du hast den Sinuswert gegeben bzw. 
den Cosinuswert und fragst dich welcher Winkel da dazugehört. Das ist 
der Winkel um den die magnetische Nordrichtung von deiner Ausrichtung 
des Sensors abweicht.

Einen kleinen Unterschied gibt es noch. In der Mathematik bespricht man 
Sinus und Cosinus am Einheitskreis. Du hast keinen Einheitskreis, 
sondern dein Kreis hat den Radius sqrt(x*x + y*y). D.h um die 
Komponenten auf einen Einheitskreis zu normieren, damit du die 
Arcus-Funktionen anwenden kannst, müssen die Komponenten durch diesen 
Radius dividiert werden.
Allerdings ist das alles eine Standardaufgabe, die oft vorkommt, so dass 
es dafür eine fertige Funktion gibt - atan2
Stopf deine Komponenten in die atan2 Funktion rein und du kriegst den 
Winkel des Vektors schon fix fertig aufbereitet und im richtigen 
Quadranten in Radianten (Achtung darauf!) ausgerechnet zurück. Ja, wenn 
du die Inklination erst mal ignorierst ist es tatsächlich so einfach, 
wie eiin einziger Funktiosaufruf und eine Umrechnung von Radianten in 
Grad (x*180/pi). Das Ergebnis ist der Winkel um den die Nordrichtung 
verdreht ist. D.h natürlich nur, wenn es keine anderen magnetischen 
Beeinflussungen gibt
1
  XMsb = .....
2
  YMsb = ......
3
4
  Winkel = atan2( YMsb, XMsb ) * 180.0 / PI;
5
6
  printf( "%f\n", Winkel );

: Wiederhergestellt durch User
von Pete K. (pete77)


Lesenswert?

Schau mal, was i2cdetect -y 1 sagt, ob das Modul überhaupt erkannt wird.

Auf jeden Fall die Pullups vom Modul ablöten, falls vorhanden, da der 
Raspi diese schon on board hat.

von Marco H. (bluebird1988)


Lesenswert?

Hey! Erstmal danke für die schnellen Antworten!

Ja, genau: -32768 bis 32767 - daran erinnere ich mich.
Verstehe ich das richtig, dass es quasi einfach reicht, mir die Wert aus 
dem Modul, so wie sie jetzt sind, einfach über
1
bearing = atan2(YMsb,XMsb);

ausrechnen zu lassen? Ohne Skalierung? YMsb und XMsb sind ja dabei die 
entsprechenden Werte aus den X- und Y-Registern.
Die Umrechnung "auf den richtigen Quadranten" und die letztliche 
Umrechnung in Degree brauche ich ja trotzdem, wenn ich keine Radangaben 
haben möchte.


Ja, das Modul wird über i2cdetect -y 1 erkannt: 1e ist die Bezeichnung, 
die auftaucht.
Die Pullups müssen wirklich runter? o.O

von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:

> Ja, genau: -32768 bis 32767 - daran erinnere ich mich.
> Verstehe ich das richtig, dass es quasi einfach reicht, mir die Wert aus
> dem Modul, so wie sie jetzt sind, einfach über
>
>
1
bearing = atan2(YMsb,XMsb);
>
> ausrechnen zu lassen?

Im Prinzip müsste es das sein.

> Ohne Skalierung? YMsb und XMsb sind ja dabei die
> entsprechenden Werte aus den X- und Y-Registern.

Genau.

> Die Umrechnung "auf den richtigen Quadranten" und die letztliche
> Umrechnung in Degree brauche ich ja trotzdem, wenn ich keine Radangaben
> haben möchte.

Die Quadrantensache erledigt alles schon atan2. Du brauchst nur noch von 
Radianten in Grad umzurechnen.

Was dir natürlich noch einen Strich durch die Rechnung machen kann, das 
ist ein Sensoroffset. Da wäre es zb mal vernünftig mit einem echten 
magnetischen Kompass die Nordrichtung festzustellen, den Sensor dazu 
parallel zu stellen und dann nachzusehen, ob alle bis auf 1 Komponente 
zu 0 verschwinden oder ob es eine Verschiebung gibt.
Ebenfalls sichtbar müssen sich derartige Probleme machen, wenn man den 
Sensor um 180° dreht. Dann sollten sich theoretisch alle Werte im 
Vorzeichen umdrehen. Tun sie das wirklich?
Was ist bei Drehungen um 90°? Die Werte sollten die Achsen tauschen aber 
ansonsten in ihrer Größe gleich bleiben. Tun sie das?

Daraus ergibt sich ann ein Satz von Korrekturwerten, die 
berücksichtigen, dass die Sensoren in den einzelnen Achsen natürlich 
nicht alle gleich empfindlich sind bzw. einen Offsetfehler haben können.

von Marco H. (bluebird1988)


Lesenswert?

Oookay, jetzt heißt es für mcih erstmal ran an den Raspberry und gucken, 
dass ich das alles mal fix umsetze.
Ich werde mich heute Abend dann nochmal hören lassen!!!

Danke erstmal bis hierhin!

von Marco H. (bluebird1988)


Lesenswert?

So ich hab gerade mal eine Messreihe aufgenommen, indem ich den Sensor 
auf ne Schalchtel geklebt habe, mit der Z-Achse in Bodenrichtung.

Dabei habe ich dann nur mit
1
 
2
bearing = atan2(YMsb,XMsb);
3
bearing *= (180 / 3.4159265);
mir die Werte ausgeben lassen. Rotation gegen den Uhrzeigersinn:

133 bis runter auf 30, dann Sprung auf 140
140 bis runter auf 18, dann Sprung auf 147
147 bis runter auf 70 dann Zählrichtungsumkehr
70 bis rauf auf 140, dann Sprung auf 24
24 bis rauf auf 134, dann Sprung auf 30
30 bis rauf auf 133.

Es ergeben sich also keine sauberen 90°-Positionen.
Die Werte sind mit und ohne Offsetberücksichtigung recht ähnlich.

Wenn die Zählrichtungsumkehr stattfindet, also bei 70, dann ist die 
Ausrichtung der X-Achse schon ziehmlich gut nach Norden gerichtet, 
soweit man das nun mit nem Kompass im Handy sagen kann. Ich weis 
allerdings, dass dort definitiv Norden ist.

Das ist doch schonmal viel Wert! Allerdings wundern mich die Zahlen 
trotzdem.
Was läuft da in der Auflösung falsch?

von Wolfgang (Gast)


Lesenswert?

Marco He schrieb:
> Es ergeben sich also keine sauberen 90°-Positionen.
> Die Werte sind mit und ohne Offsetberücksichtigung recht ähnlich.

Dann lass doch erstmal die ganze Winkelrechnerei weg. Bevor du nicht 
weißt, dass der Offset richtig abgezogen ist und die Werte gleich 
skaliert sind, kommt sonst nur mehr oder weniger Unfug raus.

Mach erstmal eine Scatterplot der Rohdaten, während du den Sensor sauber 
horizontal ausgerichtet hast und langsam ein paar Mal um die vertikale 
Achse drehst. Und den zeigst du dann mal.

von Marco H. (bluebird1988)


Lesenswert?

Vielleicht eine blöde Frage, aber hast du eine Empfehlung, mit was ich 
den Scatter Plot auf dem Raspberry erstelle? Oder soll ich mir die 
Wertepaare einfach in eine Datei ausgeben lassen und sie mit Excel 
darstellen?

von Wolfgang (Gast)


Lesenswert?

Marco He schrieb:
> Oder soll ich mir die Wertepaare einfach in eine Datei ausgeben lassen
> und sie mit Excel darstellen?

Genau das

von Marco H. (bluebird1988)


Angehängte Dateien:

Lesenswert?

Ist mir ein wenig peinlich, aber das sind jetzt rund 150 Messwerte...

Edit: Selbst mit rund 550 sieht das Bild nicht großartig besser aus.
Mach ich was falsch?

Kann doch alles irgendwie nicht sein...

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Marco He schrieb:
> Edit: Selbst mit rund 550 sieht das Bild nicht großartig besser aus.
> Mach ich was falsch?

Das scheint so. Bei einem vernünftigen Magnetfeldsensor muss sich bei 
einem xy-Plot ein ggf. verzerrter Kreis ergeben, dessen Mittelpunkt 
möglicherweise gegen den Ursprung verschoben ist. Vorher braucht man gar 
nicht anfangen, mit den Daten zu rechnen.

Was liefert denn der Selbsttest?

Gegenüber den Achsenbezeichnungen im Datenblatt hast du Y und Z 
vertauscht. Welche Daten sind im Plot dargestellt und worum hast du den 
Sensorchip gedreht?

von Marco H. (bluebird1988)


Lesenswert?

Den verzerrten Kreis habe ich auch erwartet. Deswegen wundere ich mich 
und fange langsam an, an mir zu zweifeln...

Der Selbsttest (mit Defaultwerten), so, wie er im ersten Post 
eingestellt ist, liefert in den drei Registern folgende Werte:

XMsb: -3323
YMsb: 30725
ZMsb: -19707

Im Plot habe ich die X zu Y - Daten dargestellt und um die Z-Achse 
gedreht...
Der Sensor liegt also gerade auf seinen Chips auf der Schachtel auf und 
sinnbildlich auf der Chipseite gedreht.

von Sebastian W. (wangnick)


Lesenswert?

Marco He schrieb:
> Den verzerrten Kreis habe ich auch erwartet. Deswegen wundere ich mich
> und fange langsam an, an mir zu zweifeln...

Die Messwerte bilden doch einen verzerrten Kreis (mit mehreren 
Überläufen auf der Excel-X-Achse)!

LG, Sebastian

von Marco H. (bluebird1988)


Angehängte Dateien:

Lesenswert?

Ich habe mal ein wenig aufgeräumt und ein neues Programm geschrieben, 
nur um die Werte des Selbsttests auszugeben, denn für mich machten die 
obigen Werte keinen Sinn.

Ich führe mit den default-Einstellungen 8 Messungen durch, lasse mir das 
Ergebnis der letzten Messung ausgeben und den Durchschnittswert der 
Messungen.

Im Bild ist das Ergebnis zu sehen.
Warum hab ich aber so kleine Werte?

Hier das Programm dazu:
1
#include <stdlib.h>
2
#include <iostream>
3
#include <wiringPi.h>
4
#include <wiringPiI2C.h>
5
#include <cmath>
6
#include <fstream>
7
8
using namespace std;
9
int8_t fd;
10
int16_t data, XMsb=0, XLsb=0, YMsb=0, YLsb=0, ZMsb=0, ZLsb=0, AVXMsb=0, AVXLsb=0, AVYMsb=0, AVYLsb=0, AVZMsb=0, AVZLsb=0;
11
12
void test(void)
13
{
14
    fd=wiringPiI2CSetup(0x1e);                  // Filedescriptor erstellen
15
    wiringPiI2CWriteReg8(fd,0x00, 0x71);        // positive bias (feld)
16
    wiringPiI2CWriteReg8(fd,0x01, 0x20);        // gain +-1.3 Gauß
17
    wiringPiI2CWriteReg8(fd,0x02, 0x01);        // single-measurement-mode
18
}
19
20
int main()
21
{
22
    test();
23
    cout << "Testmodus" << endl;
24
25
    for (int i=0; i<8; i++)
26
    {
27
        XMsb = (wiringPiI2CReadReg8(fd, 0x03));
28
        XLsb = wiringPiI2CReadReg8(fd, 0x04);
29
        YMsb = (wiringPiI2CReadReg8(fd, 0x05));
30
        YLsb = wiringPiI2CReadReg8(fd, 0x06);
31
        ZMsb = (wiringPiI2CReadReg8(fd, 0x07));
32
        ZLsb = wiringPiI2CReadReg8(fd, 0x08);
33
34
        delay (100);
35
36
        AVXMsb += XMsb;
37
        AVXLsb += XLsb;
38
        AVYMsb += YMsb;
39
        AVYLsb += YLsb;
40
        AVZMsb += ZMsb;
41
        AVZLsb += ZLsb;
42
    }
43
44
    cout << "Letzte Messung:" << endl;
45
    cout << "XMsb: " << XMsb << endl;
46
    cout << "XLsb: " << XLsb << endl;
47
    cout << "YMsb: " << YMsb << endl;
48
    cout << "YLsb: " << YLsb << endl;
49
    cout << "ZMsb: " << ZMsb << endl;
50
    cout << "ZLsb: " << ZLsb << endl << endl;
51
    cout << "Durchschnittswerte der Messungen:" << endl;
52
    cout << "AVXMsb: " << AVXMsb/8  << endl;
53
    cout << "AVXLsb: " << AVXLsb/8  << endl;
54
    cout << "AVYMsb: " << AVYMsb/8  << endl;
55
    cout << "AVYLsb: " << AVYLsb/8  << endl;
56
    cout << "AVZMsb: " << AVZMsb/8  << endl;
57
    cout << "AVZLsb: " << AVZLsb/8  << endl;
58
59
    return 0;
60
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Im Datenblattt ist doch die Vorgehensweise beim Self-Test angegeben.
Halte dich doch einfach mal an die Herstellervorgabe
1
Below is an example of a “positive self test” process using
2
continuous-measurement mode:
3
1. Write CRA (00) – send 0x3C 0x00 0x71 (8-average, 15 Hz default,
4
   positive self test measurement)
5
2. Write CRB (01) – send 0x3C 0x01 0xA0 (Gain=5)
6
3. Write Mode (02) – send 0x3C 0x02 0x00 (Continuous-measurement mode)
7
4. Wait 6 ms or monitor status register or DRDY hardware interrupt pin
8
5. Loop
9
     Send 0x3D 0x06 (Read all 6 bytes. If gain is changed then this data
10
     set is using previous gain)
11
     Convert three 16-bit 2’s compliment hex values to decimal values
12
     and assign to X, Z, Y, respectively.
13
     Send 0x3C 0x03 (point to first data register 03)
14
     Wait about 67 ms (if 15 Hz rate) or monitor status register or
15
     DRDY hardware interrupt pin
16
   End_loop
17
6. Check limits –
18
   If all 3 axes (X, Y, and Z) are within reasonable limits (243 to 575
19
   for Gain=5, adjust these limits basing on the gain setting used.
20
   See an example below.) Then
21
      All 3 axes pass positive self test
22
      Write CRA (00) – send 0x3C 0x00 0x70 (Exit self test mode and
23
      this procedure)
24
   Else
25
     If Gain<7
26
       Write CRB (01) – send 0x3C 0x01 0x_0 (Increase gain setting
27
       and retry, skip the next data set)
28
     Else
29
       At least one axis did not pass positive self test
30
       Write CRA (00) – send 0x3C 0x00 0x70 (Exit self test mode and
31
       this procedure)
32
   End If


Noch ein Detail:
Auch wenn das 16 Bit Ergebnisse sind, aus dem Datenblatt (das ich jetzt 
auch studiert habe) geht hervor, dass der erwartete Wertebereich von 
-2048 bis 2047 geht - in allen Gain Stufen.

Woher also deine ca 32700 von oben stammen, ist mir nicht ganz klar. 
Laut Datenblatt kannst du diese Ergebnisse nicht erhalten. Vielleicht 
hat dir die 16 Bit Leseroutine die Bytes verkehrtr rum zusammengesetzt?

: Bearbeitet durch User
von Marco H. (bluebird1988)


Angehängte Dateien:

Lesenswert?

Dann scheine ich ein Problem mit dem Verständnis von Punkt 5 zu haben:
1
5. Loop
2
     Send 0x3D 0x06 (Read all 6 bytes. If gain is changed then this data
3
     set is using previous gain)
4
     Convert three 16-bit 2’s compliment hex values to decimal values
5
     and assign to X, Z, Y, respectively.
6
     Send 0x3C 0x03 (point to first data register 03)
7
     Wait about 67 ms (if 15 Hz rate) or monitor status register or
8
     DRDY hardware interrupt pin
9
   End_loop

Ich versteh nicht, was ich machen soll. Ich bin echt fertig... hau das 
Ding bald in die Tonne...

Ich lese doch alle 6 Register aus =(
Selbst, wenn ich die 6 Register als 3x16-Bit auslese, also mir die 
2er-Komplemente ausgeben lasse, erhalte ich nur die Werte wie auf dem 
Bild zu diesem Post hier.

Was soll das mit dem "Send 0x3D 0x06 "?
0x3D ist lesen,
0x06 ist das YLSB-Register,
also ist der Befehl für den Raspberry:
(wiringPiI2cReadReg8(fd, 0x06))
wobei fd der Sensor ist.
Den Wert lese ich doch aber schon aus....
So wie die anderen 5 Werte doch auch.
Ihr glaubt nicht, wie ich aufm Schlauch stehe...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:

Deine Werte sehen doch nicht schlecht aus.


Irgendwie machst du mir das alles zu kompliziert.
1
#include <stdlib.h>
2
#include <iostream>
3
#include <wiringPi.h>
4
#include <wiringPiI2C.h>
5
#include <cmath>
6
#include <fstream>
7
8
using namespace std;
9
10
11
int main()
12
{
13
    int8_t fd;
14
    uint8_t XMsb=0, XLsb=0, YMsb=0, YLsb=0, ZMsb=0, ZLsb=0
15
16
    fd = wiringPiI2CSetup(0x1e);                  // Filedescriptor erstellen
17
18
    wiringPiI2CWriteReg8(fd, 0x00, 0x70);   // Mittelwert: 8, 15Hz, normale Messung
19
    wiringPiI2CWriteReg8(fd, 0x01, 0x20);   // gain 1
20
    wiringPiI2CWriteReg8(fd, 0x02, 0x00);   // continous
21
22
    while( 1 ) {
23
24
        XMsb = wiringPiI2CReadReg8( fd, 0x03 );
25
        XLsb = wiringPiI2CReadReg8( fd, 0x04 );
26
        YMsb = wiringPiI2CReadReg8( fd, 0x05 );
27
        YLsb = wiringPiI2CReadReg8( fd, 0x06 );
28
        ZMsb = wiringPiI2CReadReg8( fd, 0x07 );
29
        ZLsb = wiringPiI2CReadReg8( fd, 0x08 );
30
31
        printf( "X: 0x%02X 0x%02X  %4d\n", XMsb, XLsb, (int)(( XMsb << 8 ) | XLsb ) );
32
33
        delay (100);
34
    }
35
}

Deine Werte für die X Achse sollten ein wenig schwanken und wenn du den 
Sensor (flach am Tisch liegend) um die Hochachse drehst, sollten sie 
sich verändern.

Da das Magnetfeld der Erde ca 0.7 Gauss an den Polen und 0.2 Gauss am 
Äquator beträgt, wird es bei uns ein Wert irgendwo da dazwischen sein. 
Ich nehm mal 0.5 Gauss an. Bei dem eingestellten Gain, wird 1 Gauss mit 
einem Wert von 1090 autauchen. Erwartungswerte für die X Achse bewegen 
sich also von ca. -540 bis ca +540. Je nachdem wie stark dein lokales 
Magnetfeld ist und wie stark die Inklination ist, auch mehr oder 
weniger. Aber in etwa in diesem Bereich.

Wenn du zur Ausgabe der X Werte noch die Y-Werte mit dazu nimmst, dann 
sollte man bei einer Drehung auch sehen, wie die X Werte zu bzw. 
abnehmen und im Gegenzug dazu die Y-Werte zu bzw. abnehmen, so wie man 
das beim Zusammenhang zwischen Cosinus und Sinus erwarten würde.

Was ich verändert habe: Ich habe vor allen Dingen mal auf Continous 
Measurement umgestellt. Denn mit einer Einzelmessung hat man wenig 
angefangen, wenn man 'Action' beim Drehen sehen möchte.
Und dann lass ich mir natürlich in der Schleife ausgeben:
DIe Bytes wie sie vom Sensor kommen und das was ich daraus mache. Damit 
ich sehen kann, ob die Zusammensetzung klappt oder ob ich irgedwo 
falsche Annahmen gemacht habe. Die Bytes lass ich mir sinnvollerweise 
Hex ausgeben, der mich eigentlich interessierende Wert dann dezimal.

Und dann schau mer mal.

Und noch was:
Der Datentyp der Wahl ist immer ein uint8_t wenn man es mit Bytes zu 
tun hat. Das was du vom Sensor kriegst sind zuallererst mal Bytes. Und 
erst wenn 2 Bytes zu einer 16 Bit Einheit zusammengesetzt sind, ist der 
Zeitpunkt gekommen, die Interpretation dieser Einheit zu einem int zu 
wechseln. Also: zuerst die beiden uint8_t zu 16 Bit zusammensetzen und 
erst dann die Anweisung geben, dass das Ganze als int aufzufassen ist.
Wenn dein Pi mit 32 Bit ints operiert, dann muss man noch einen 
Zwischenschritt einfügen und die 16 Bit Einheit erst mal auf einen 
int16_t casten, ehe man dann auf int geht.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Und noch was:
Je nach Situation auf deinem Schreibtisch können da auch ganz schöne 
Fehler auftreten. Jeder Trafo, jeder (Röhren-)Monitor, jeder Motor 
erzeugt ein Magnetfeld, dass sich mit dem Erdmagnetfeld natürlich 
überlagert.

Selbst wenn du also weisst wo Norden ist, ist beileibe nicht 
sichergestellt, dass sich diese Richtung in deinen Daten auch mit exakt 
einem Maximum in einem der X bzw. Y Werte bemerkbar macht.

von Marco H. (bluebird1988)


Lesenswert?

Also erstmal danke für deine Hilfe - ich bin wie gesagt am 
verzweifeln...

Zu den neuen Werten, die sich durch dein Script ergeben, nur für die 
X-Achse:

Drehrichtung im Uhrzeigersinn:

0 --> 397
397 --> 0
65335 --> 65412
65421 --> 65335

Ich habe die Y-Werte noch nicht mit anzeigen lassen, denn ich glaube 
erstmal ist wichtig zu wissen, ob die Werte Sinn machen, bevor ich 
wieder alles durcheinanderbringe...

von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:
> Also erstmal danke für deine Hilfe - ich bin wie gesagt am
> verzweifeln...
>
> Zu den neuen Werten, die sich durch dein Script ergeben, nur für die
> X-Achse:
>
> Drehrichtung im Uhrzeigersinn:
>
> 0 --> 397
> 397 --> 0
> 65335 --> 65412

Wie sehen die Bytes dazu aus? Sind die plausibel?

Mach mal:
1
        printf( "X: 0x%02X 0x%02X  %4d\n", XMsb, XLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ) );

Also: Zwischenschritt über einen Cast nach int16_t
Du hast scheinbar 32-Bit int.

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Zu den neuen Werten, die sich durch dein Script ergeben, nur für die
X-Achse:

Drehrichtung im Uhrzeigersinn:

0 --> 400
400 --> 0
0 --> -105
-105 --> 0

Ja, die Bytes sehen plausibel aus, jedenfalls gibts keine wirren 
Ausgaben, sondern saubere Werte zwischen 0x00 bis 0xFF.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:
> Zu den neuen Werten, die sich durch dein Script ergeben, nur für die
> X-Achse:
>
> Drehrichtung im Uhrzeigersinn:
>
> 0 --> 400
> 400 --> 0
> 0 --> -105
> -105 --> 0

Da scheint aber ein ordentlicher Offset drinn zu sein.
Irgendwelche gröberen Metallteile in der Nähe?

Es wird Zeit die Y-Achse mit dazu zu nehmen. Ausgabe am besten: X und Y 
in einer Zeile. Wenn die zu lang wird, dann die Byteausgabe wegzulassen. 
Die Werte sehen ja erst mal von der Größenordnung her nicht schlecht 
aus.

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Herr schmeiß Hirn vom Himmel oder erschlag mich...

Ich kenne printf zwar als Pendant zu cout, aber was mache ich hier schon 
wieder falsch?
1
printf( XMsb, XLsb, YMsb, YLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ), (int)(int16_t)(( YMsb << 8 ) | YLsb ) );

Mist, wenn man nur rudimentär C++ in der Schule hatte...
Aber ich hoffe, alle die mitlesen, haben was zu lachen :D

von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:
> Herr schmeiß Hirn vom Himmel oder erschlag mich...
>
> Ich kenne printf zwar als Pendant zu cout, aber was mache ich hier schon
> wieder falsch?
>
>
1
> printf( XMsb, XLsb, YMsb, YLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ), 
2
> (int)(int16_t)(( YMsb << 8 ) | YLsb ) );
3
>


Wo ist denn der Format String.

Eine ganz simple Lösung wäre gewesen, die printf Anweisung zu 
duplizieren, X gegen Y zu tauschen und in der 'X_Zeile' den 
Zeilenvorschub \n gegen ein Leerzeichen zu tauschen. Minimaler Aufwand 
und für ein Testsystem gut genug
1
        printf( "X: 0x%02X 0x%02X  %4d  ", XMsb, XLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ) );
2
        printf( "Y: 0x%02X 0x%02X  %4d\n", YMsb, YLsb, (int)(int16_t)(( YMsb << 8 ) | YLsb ) );



printf mag ich deswegen lieber, weil die Formatiermöglichkeiten im 
Formatstring einfach schneller anzuwenden sind als diese ganzen 
Stream-Operatoren.

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Oh man... =(

Naja... so: Die Y-Werte drehen sich um 280, je nachdem, wie ruhig ich 
den Sensor um die Hochachse drehe.
Die Bits sehen dabei auch wieder nicht wirr aus.

von Karl H. (kbuchegg)


Lesenswert?

Marco He schrieb:
> Oh man... =(
>
> Naja... so: Die Y-Werte drehen sich um 280, je nachdem, wie ruhig ich
> den Sensor um die Hochachse drehe.

d.h. die bleiben immer so um die 280?

dann nimm mal die Z Achse dazu. Denn die Frage ist ja: welche beiden 
Achsen hast du in deiner Haltung waagrecht zum Boden ausgerichtet.
Wir gehen immer davon aus, dass das die X und die Y Achse sein werden. 
Muss aber nicht so sein.

von Marco H. (bluebird1988)


Lesenswert?

Haa ich hab nen printf-Befehl selbst kopiert und verändert :D :D :D

X-Werte:
0 --> 400
400 --> 0
0 --> -105
-105 --> 0

Y-Werte:
~280, je nach ruhiger Hand beim Rotieren um die Hochachse

Z-Werte: Angefangen bei X=0, dann weiter wie oben

115 --> 163 --> -140
140 --> -370 --> -316
-316 --> -105
-105 --> 97

Also Wenn x = 0, dann zeigt Z 115,
Wenn x = 400, dann zeigt Z 140 usw...

Sind da Y und Z vertauscht?!

von Fritz (Gast)


Lesenswert?

Was mich beim HMC5883L fast einen halben Tag gekostet hat, war die 
Tatsache, dass die Daten nicht in XYZ angeordnet sind, sondern in XZY.

Den Fehler machst du offensichtlich auch gerade.

von Karl H. (kbuchegg)


Lesenswert?

Da der Z Wert springt denke ich, dass das wirklich die Richtung zum 
Boden ist. Die Frage ist jetzt nur: was ist mit deinem Y Wert los?

Sensor nicht in der Hand halten! Leg ihn auf den Tisch zum drehen. Damit 
hast du auf einfachste Weise eine gleichbleibende Drehebene.


Verkippe mal den Sensor um 90°, so dass die Achse die vorher in den 
Tisch reingegangen ist (und um die gedreht wird) sich jetzt in der Ebene 
drehen kann. Aber so kippen, dass die vorhergehende Y-Achse jetzt in den 
Tisch reinschaut.

-> X hat nach wie vor gleiches Verhalten, aber die Y und die Z Achse 
tauschen die 'Plätze'. Hast du dann immer noch das Verhalten, dass eine 
Achse ziemlich konstante Werte anzeigt und die andere Achse springt?

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Da scheinen wirklich Y und Z vertauscht zu sein...

Karl Heinz schrieb:
> Verkippe mal den Sensor um 90°, so dass die Achse die vorher in den
> Tisch reingegangen ist (und um die gedreht wird) sich jetzt in der Ebene
> drehen kann. Aber so kippen, dass die vorhergehende Y-Achse jetzt in den
> Tisch reinschaut.

Dann bleibt Z relativ konstant und Y ändert fröhlich seine Werte :D

von Karl H. (kbuchegg)


Lesenswert?

Ja.
Aber wenn du einigermassen langsam und konstant drehst, können die Werte 
nicht so rasant springen.

Würde man die Werte jeder Achse plotten, müssten sich eigentlich 2 
Sinuskurven ergeben, die um 90° phasenverschoben sind.

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Also die Werte spingen ja nicht, sondern gehen schon fließend.
Ich habe nur die markanten Punkte hier aufgeschrieben.
Wenn ich mir zum beispiel die X-Achse nur von den werten her angucke, 
würde ich schon eine Sinus-Form vermuten.

X-Werte:
0 --> 400 (Maximum)
400 --> 0
0 --> -105 (Minimum)
-105 --> 0

Die Kurve müsste ja um[(400 + 105)/2] = 252,5 schwingen.

Wenn ich die Werte jetzt in ne Textdatei ausgeben will,
wie stelle ich das am schlausten an?
Also wie lasse ich mir XMsb als geshifteten Wert mit dem Umweg über 
(int)(int16_t) richtig ausgeben?

Über
ofstream Dateix ("")
{
Dateix << XMsb = ( XMsb << 8 ) | XLsb ) << endl;
}
würde mir ja diese Wandlung fehlen...

von Karl H. (kbuchegg)


Lesenswert?

Du kannst natürlich über die Stream Funktionen gehen. Dazu sind sie da.

Trotzdem tendiere ich persönlich auch hier zu den alten C Mechanismen, 
wenn ich schon selbst im Programm auf eine Datei schreiben will und 
nicht einfach den redirect Mechanismus der Shell ausnutze.
1
...
2
  FILE* outFile;
3
4
  outFile = fopen( "Daten.txt", "w" );
5
  if( outFile == NULL ) {
6
    printf( "Error opening Daten.txt\n" );
7
    exit( 1 );
8
  }
9
10
...
11
12
       fprintf( outFile, "X: 0x%02X 0x%02X  %4d  ", XMsb, XLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ) );
13
14
....
15
16
17
  fclose( outFile );

Aber ehe du umbaust, probier doch einfach mal, ob dir deine Shell nicht 
ganz simpel den Output in ein File redirecten kann.

heisst dein Programm "kompass" und startest du es in der shell mittels
1
kompass
dann probier einfach mal
1
kompass > Daten.txt
und sieh nach, ob eine derartige Datei erzeugt wird und die Ausgabe 
deines Programms dorthin umgeleitet wurde.
Es gibt durchaus Dinge, in denen sind die textbasierten Shells jedem 
Klickibunti System überlegen. Nur umgehen muss man eben damit können.

: Bearbeitet durch User
von Marco H. (bluebird1988)


Lesenswert?

Danke für den Code!

Jetzt bekomme ich leider nur die Datei erstellt, aber keine Ausgabe.
1
          
2
FILE* outFile;
3
4
outFile = fopen( "DatenX.txt", "w" );
5
if( outFile == NULL ) {
6
printf( "Error opening DatenX.txt\n" );
7
exit( 1 );
8
}
9
fprintf( outFile, "X: 0x%02X 0x%02X  %4d  ", XMsb, XLsb, (int)(int16_t)(( XMsb << 8 ) | XLsb ) );

Ich hab leider null Plan von C, geschweige denn, was du mit starten aus 
der Shell meinst.
Ich schreibe mein rudimentäres Wissen mit C++ in Codeblocks nieder und 
starte meine Programme darüber... =/ ich komm mir echt bescheuert vor...

von Wolfgang (Gast)


Lesenswert?

Karl Heinz schrieb:
> Da scheint aber ein ordentlicher Offset drinn zu sein.
> Irgendwelche gröberen Metallteile in der Nähe?

Metallteile in der Nähe verursachen beim Drehen keinen Offset. Dazu 
müßte der Magnetfeldanteil schon auf dem Bord selbst entstehen und sich 
mitdrehen.

von Marco H. (bluebird1988)


Angehängte Dateien:

Lesenswert?

Ein Kreis, ein Kreis, ein Kreis!!!

Endlich!

Hab an dem Output erwas zu knobeln gehabt, aber jetzt hab ich die Werte 
mal geplottet!

Ich habe den Sensor dabei so liegen gehabt, dass die Y-Achse wieder in 
den Tisch zeigt,

Karl Heinz schrieb:
> Verkippe mal den Sensor um 90°, so dass die Achse die vorher in den
> Tisch reingegangen ist (und um die gedreht wird) sich jetzt in der Ebene
> drehen kann. Aber so kippen, dass die vorhergehende Y-Achse jetzt in den
> Tisch reinschaut.
>
> -> X hat nach wie vor gleiches Verhalten, aber die Y und die Z Achse
> tauschen die 'Plätze'.


Gibt mir das den Offset?

von Wolfgang (Gast)


Lesenswert?

Marco He schrieb:
> Gibt mir das den Offset?

Logisch. Der Anteil, der sich beim drehen nicht ändert, ist der Offset, 
d.h. x0=130, y0=-615, z0=0

Marco He schrieb:
> Hab an dem Output erwas zu knobeln gehabt.
Prima, besonders der X-Z Plot. Was hast du geändert?

von Marco H. (bluebird1988)


Lesenswert?

Der output wollte mit "w" nicht gelingen, sondern nur mit "a" für 
append.
Und ich habe mir nur die Zahlen ausgeben lassen, ein Wert pro Zeile.
War für mich als C-neuling mit ein wenig Recherche verbunden, aber das 
war nicht mehr schlimm, als ich wieder etwas mehr Geduld hatte.

Den Offset würde ich jetzt einfach mit den Wertepaaren der Achsen 
verrechnen.
Also X - 130, Y + 615

Jetzt aber folgende Wissenslücke:
Wir wandeln doch (int)(int16_t)(( XMsb << 8 ) | XLsb ) );
Nur dadurch erhalten wir doch überhaupt erst unsere Werte.

Wenn ich jetzt aber sage Xoffset = ((int)(int16_t)(( XMsb << 8 ) | XLsb 
) ); wie muss ich dann Xoffset als Variable deklarieren?
Als int16_t?

von Marco H. (bluebird1988)


Lesenswert?

Habe jetzt den Code etwas angepasst und den Offset wie beschrieben 
reingerechnet.
Ich werde mir hoffentlich heute nachmittag, spätestens morgen nachmittag 
die Werte nochmal Plotten und die neuen Ergebnisse sowie den aktuellen 
Code posten.
Die xwerte springen noch etwas herum, die ywerte laufen schonmal sauber. 
Ich bin gespannt, was die neuen Plotts zeigen!

von Marco H. (bluebird1988)


Angehängte Dateien:

Lesenswert?

Hey!

Es ist vollbracht!
Ich habe endlich einen Ursprungskreis!
Eine Winkelberechnung mit atan2 und einer Umrechnung wegen 
Vorzeichenwechsel ergibt jetzt eine fortlaufende Gradangabe von 0 bis 
360 mit einer Abweichung von -11 Grad zur Angabe meines Kompass im 
Handy.
Ich werde also mit dem Offset noch minimal herumspielen und dann sollte 
die Gradanzeige gut arbeiten!

Jetzt muss ich mal gucken, ob ich den Neigungsfehler, wenn das Modul 
nicht 100%ig gerade ausgerichtet ist, auch noch rausgerechnet bekomme.

Eine Formel habe ich dazu schon, nur kann ich die erst später 
ausprobieren. Muss jetzt erstmal wieder zur Spätschicht...

Ich melde mich spätestens morgen Mittag wieder!

von Wolfgang (Gast)


Lesenswert?

Marco He schrieb:
> Jetzt muss ich mal gucken, ob ich den Neigungsfehler, wenn das Modul
> nicht 100%ig gerade ausgerichtet ist, auch noch rausgerechnet bekomme.

Da brauchst du deinen 3D-Magnetfeldvektor und den Schwerkraftvektor vom 
Beschleunigungssensor. Der Magnetfeldvektor wird auf die 
Schwerkraft-Normalenebene projiziert und dann hast du die Komponenten 
für die Azimut-Berechnung.

von Marco H. (bluebird1988)


Lesenswert?

Hey Hey!

Also ich habe das Kompassmodul nun auf nahezu 0 Grad abweichung 
gefummelt.
Klar gibt es eine minimale Abweichung, aber ich will ja keine 
hochpräzise Anlage entwickeln :D

Danke erstmal dafür an alle, die mich angeleitet haben!!!!

Jetzt knobel ich ein wenig am ADXL345 3-Achs-Beschleunigungsaufnehmer, 
um hinterher die Tilt-Kompensation zu realisieren.

Ich bekomme die Register ausgelesen und erhalte auch Werte, jedoch bin 
ich mir nicht sicher, ob eine exakte Kalibrierung notwendig ist, sodass 
wieder alle drei Vektoren einen gemeinsamen Nullpunkt haben oder ob ich 
nicht einfach über die Verhältnisse der Achsen gehen kann.

Hier mal meine min / max - Werte:
x min -445
x max 578

y min -512
y max 422

z min 530
z max 1152

Die Winkel ergeben sich ja nachher aus atan2(y,z) und atan2(x,z)...
Ich würde jetzt die Min-Werte einfach über den Offset auf Null setzen 
uind die Idee war dann, zB x ins Verhältnis zu Z zu setzen und mit dem 
Wert den Winkel auszurechnen. Nur wo liegt mein Denkfehler?

Mit dem Taschenrechner bekomme ich es nicht sinnvoll hin, die Achsen so 
zu skalieren, dass ich damit rechnen kann...
Wenn ich jetzt schon die atan2 anwende und von Rad in Grad umrechne, 
komme ich auf Winkel zwischen -15 und 22 Grad statt 0 (Horizontal) und 
90 (senkrecht) Grad.

Hier kommt mein Code:
1
#include <stdlib.h>
2
#include <iostream>
3
#include <wiringPi.h>
4
#include <wiringPiI2C.h>
5
#include <inttypes.h>
6
#include <fstream>
7
#include <cmath>
8
9
10
using namespace std;
11
int8_t fd;
12
int xmsbacc, xlsbacc, ymsbacc, ylsbacc, zmsbacc, zlsbacc, xrawacc, yrawacc, zrawacc,
13
    x_scaled, y_scaled, z_scaled, x, y, z,
14
    xg, yg, zg;
15
16
17
void init(void)
18
{
19
    fd=wiringPiI2CSetup(0x53);
20
    wiringPiI2CWriteReg8(fd,0x31, 0x0B );
21
    wiringPiI2CWriteReg8(fd,0x2D, 0x08 );
22
    //  wiringPiI2CWriteReg8(fd, 0x2e, 0x00);
23
    wiringPiI2CWriteReg8(fd, 0x1e, 0x00);
24
    wiringPiI2CWriteReg8(fd, 0x1f, 0x00);
25
    wiringPiI2CWriteReg8(fd, 0x20, 0x00);
26
27
    wiringPiI2CWriteReg8(fd, 0x21, 0x00);
28
    wiringPiI2CWriteReg8(fd, 0x22, 0x00);
29
    wiringPiI2CWriteReg8(fd, 0x23, 0x00);
30
31
    wiringPiI2CWriteReg8(fd, 0x24, 0x01);
32
    wiringPiI2CWriteReg8(fd, 0x25, 0x0f);
33
    wiringPiI2CWriteReg8(fd, 0x26, 0x2b);
34
    wiringPiI2CWriteReg8(fd, 0x27, 0x00);
35
36
    wiringPiI2CWriteReg8(fd, 0x28, 0x09);
37
    wiringPiI2CWriteReg8(fd, 0x29, 0xff);
38
    wiringPiI2CWriteReg8(fd, 0x2a, 0x80);
39
    wiringPiI2CWriteReg8(fd, 0x2c, 0x0a);
40
    wiringPiI2CWriteReg8(fd, 0x2f, 0x00);
41
    wiringPiI2CWriteReg8(fd, 0x38, 0x9f);
42
    delay(100);
43
}
44
45
int main()
46
{
47
    float pitch, roll, winkel1, winkel2, minx=1000, maxx=0, miny=1000, maxy=0, minz=1000, maxz=0;
48
    init();
49
50
    cout << sizeof(fd) << endl;
51
    cout << fd << endl;
52
53
    while(1)
54
    {
55
        xmsbacc = wiringPiI2CReadReg8( fd, 0x32 );
56
        xlsbacc = wiringPiI2CReadReg8( fd, 0x33 );
57
        ymsbacc = wiringPiI2CReadReg8( fd, 0x34 );
58
        ylsbacc = wiringPiI2CReadReg8( fd, 0x35 );
59
        zmsbacc = wiringPiI2CReadReg8( fd, 0x36 );
60
        zlsbacc = wiringPiI2CReadReg8( fd, 0x37 );
61
62
        xrawacc = (int)(int16_t)((xlsbacc << 8) | xmsbacc);
63
        yrawacc = (int)(int16_t)((ylsbacc << 8) | ymsbacc);
64
        zrawacc = (int)(int16_t)((zlsbacc << 8) | zmsbacc);
65
66
        x_scaled = xrawacc;
67
        y_scaled = yrawacc;
68
        z_scaled = zrawacc;
69
/*
70
        xrawacc = ((xlsbacc << 8) | xmsbacc);
71
        yrawacc = ((ylsbacc << 8) | ymsbacc);
72
        zrawacc = ((zlsbacc << 8) | zmsbacc);
73
*/
74
        if (x_scaled < minx)
75
        {
76
            minx = x_scaled;
77
        }
78
        if (x_scaled > maxx)
79
        {
80
            maxx = x_scaled;
81
        }
82
        if (y_scaled < miny)
83
        {
84
            miny = y_scaled;
85
        }
86
        if (y_scaled > maxy)
87
        {
88
            maxy = y_scaled;
89
        }
90
        if (z_scaled < minz)
91
        {
92
            minz = z_scaled;
93
        }
94
        if (z_scaled > maxz)
95
        {
96
            maxz = z_scaled;
97
        }
98
        cout << "minx: " << minx << endl;
99
        cout << "maxx: " << maxx << endl;
100
        cout << "miny: " << miny << endl;
101
        cout << "maxy: " << maxy << endl;
102
        cout << "minz: " << minz << endl;
103
        cout << "maxz: " << maxz << endl;
104
        delay(100);
105
    }
106
    return 0;
107
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.