PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 3D kompass. Rechnung



Spacecam
13.08.2013, 18:11
Hallo RN,
ich lese so meinen 3D Kompass aus:


#!/usr/bin/env python3
import time
import random
import smbus
import math
import serial


while True:
mitte = 0
bus.write_byte_data(address,0,80)
bus.write_byte_data(address,1,32)

bus.write_byte_data(address,2,1)
time.sleep(0.01)
x = y = z = 1.0
x = y = z = 1.0
x1=bus.read_byte_data(address,3)
x2=bus.read_byte_data(address,4)
z1=bus.read_byte_data(address,5)
z2=bus.read_byte_data(address,6)
y1=bus.read_byte_data(address,7)
y2=bus.read_byte_data(address,8)



Jetzt möchte ich den Winkel nach Norden ausrechnen. Kann mir wer helfen :/
Ich würde nun gerne den Winkel unabhängig von der Neigung des Modules berechnen.
LG
Versuch 1:


#!/usr/bin/env python3
import time
import random
import smbus
import math
import serial

bus = smbus.SMBus(1)
address = 0x1e
while True:
mitte = 0
bus.write_byte_data(address,0,80)
bus.write_byte_data(address,1,32)

bus.write_byte_data(address,2,1)
time.sleep(0.01)
x = y = z = 1.0
x = y = z = 1.0
x1=bus.read_byte_data(address,3)
x2=bus.read_byte_data(address,4)
x=x1*256.0+x2

if x>32767:
x-=65536
z1=bus.read_byte_data(address,5)
z2=bus.read_byte_data(address,6)
z=z1*256.0+z2

if z>32767:
z-=65536
y1=bus.read_byte_data(address,7)
y2=bus.read_byte_data(address,8)
y=y1*256.0+y2

if y>32767:
y-=65536


#print"teyt",x,y,z
ang = 180+round(math.atan2(x, y)*(180/math.pi),0)

print"winkel",ang



bringt allerdings nur werte bis 270grad...kann mir wer helfen?

Kampi
14.08.2013, 10:35
Hey,

werden die X und Y Koordinaten den richtig ausgegeben?

Spacecam
14.08.2013, 15:18
Hey,

werden die X und Y Koordinaten den richtig ausgegeben?

ich habe den Kompass x,y,z mal aufgezeichnet dazu den errechneten winkel

X: -3.0 Y: -303.0 Z: -400.0 Winkel 1.0
X: -3.0 Y: -301.0 Z: -401.0 Winkel 1.0
X: -22.0 Y: -293.0 Z: -403.0 Winkel 4.0
X: -75.0 Y: -266.0 Z: -406.0 Winkel 16.0
X: -176.0 Y: -210.0 Z: -392.0 Winkel 40.0
X: -209.0 Y: -70.0 Z: -393.0 Winkel 71.0
X: -184.0 Y: 35.0 Z: -390.0 Winkel 101.0
X: -118.0 Y: 117.0 Z: -390.0 Winkel 135.0
X: -35.0 Y: 123.0 Z: -399.0 Winkel 164.0
X: 83.0 Y: 1.0 Z: 1.0 Winkel 269.0
X: 156.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 230.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 263.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 226.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 186.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 182.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 132.0 Y: 1.0 Z: 1.0 Winkel 270.0
X: 120.0 Y: 1.0 Z: 1.0 Winkel 270.0

Technipion
15.08.2013, 12:07
Hey Spacecam,
ich habe deine Daten mehrfach überprüft und dabei auch eine andere Formel zu Hilfe genommen, aber es kommt immer das Gleiche heraus: Du hast nunmal nur Winkel bis 270°.
Wenn du genauer drüber nachdenkst ist es auch logisch, am Schluss deiner Tabelle bleibt Y konstant bei 1.0, nur X verändert sich. Daraus folgt eine so kleine Änderung des Winkels, dass wegen der Rundung nur noch 270° herauskommt.
Ich habe dir zum Überprüfen mal eine Tabelle und ein Bild angehängt, sofern ich alles richtig verstanden habe kannst du damit per Hand deinen Winkel überprüfen.
Höchstwahrscheinlich werden die Werte falsch ausgelesen, oder das Gerät spinnt.

MFG Techipion26230

Torrentula
15.08.2013, 12:19
Mir hat diese Seite sehr gut geholfen, die Winkelberechnung zu verstehen: https://www.loveelectronics.co.uk/Tutorials/8/
Ist ja im Endeffekt dasselbe, was man auch schon in der 8. Klasse in Physik lernt, mann kan einen Vektor auf der XY-Ebene in seine beiden Teilvektoren in X und Y Ebene zerlegen. Genau diese Teilvektoren misst ja das Magnetometer und mit Hilfe des (Arcus-)Tangens kann man dann den Winkel zum magnetischen Nordpol berechnen.

Zu beachten ist, dass man die Werte vom Magnetometer mit Hilfe der lokalen Abweichung des Erdmagnetfeldes kompensieren muss, um genau den magnetischen Nordpol zu bestimmen (ist auch in dem Artikel oben beschrieben, lokale Abweichung lässt sich im Netz nachschauen, bzw. auch das GPS kann es einem sagen).

Wenn du dann noch für die Neigung kompensieren willst, benötigst du ein Accelerometer, ist in diesem Artikel beschrieben: https://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial

Spacecam
15.08.2013, 19:55
Hey Spacecam,
ich habe deine Daten mehrfach überprüft und dabei auch eine andere Formel zu Hilfe genommen, aber es kommt immer das Gleiche heraus: Du hast nunmal nur Winkel bis 270°.
Wenn du genauer drüber nachdenkst ist es auch logisch, am Schluss deiner Tabelle bleibt Y konstant bei 1.0, nur X verändert sich. Daraus folgt eine so kleine Änderung des Winkels, dass wegen der Rundung nur noch 270° herauskommt.
Ich habe dir zum Überprüfen mal eine Tabelle und ein Bild angehängt, sofern ich alles richtig verstanden habe kannst du damit per Hand deinen Winkel überprüfen.
Höchstwahrscheinlich werden die Werte falsch ausgelesen, oder das Gerät spinnt.

MFG Techipion26230

ok,
ich habe mal eine neuen bestellt.... ich hoffe dann läuft es. Danke für die Exel anwendung ;)

Spacecam
17.08.2013, 11:46
fehler gefunden... ich hatte ausversehen das auslesen von

z1 u z1 in der IF bedinung drinne....
sry

Technipion
17.08.2013, 14:37
Macht doch nix ;)
Nur aus Fehlern lernt man schließlich!

Sag mal, hat dein 3D-Kompass zufällig was mit dem Projekt zu tun einen Raspi ins All zu schießen?
Gruß Technipion

Spacecam
17.08.2013, 14:48
Macht doch nix ;)
Nur aus Fehlern lernt man schließlich!

Sag mal, hat dein 3D-Kompass zufällig was mit dem Projekt zu tun einen Raspi ins All zu schießen?
Gruß Technipion

Zufällig ja,
ich habe einen Script der mit GPS Daten die mir mein GPS Modul ausgibt einen Kurs ausrechnet denn der Raspi fliegen muss. Nun brauch ich nur sicherheitshalber noch ein Accelerometer wie
Torrentula erwähnt hat. Im Moment kann die Box mit dem PI schon recht gut fliegen und den Kurs ansteuern.


LG

LG

Torrentula
17.08.2013, 17:22
Du benötigst immer noch ein Accelerometer, denn schließlich willst du ja für Neigung kompensieren. Das Magnetometer misst ja erstmal nur die Stärke eines Magnetfeldes auf 3 Achsen. Diese Werte werden in der Einheit Gauß angegeben, d.h. du musst sie, wie du es bereits machst im Code, miteinander verrechnen, sodass du einen Winkel zum magnetischen Nordpol bekommst (<besserwisser>und erst dann ist es ein Kompass</besserwisser> :P).

Diese simple Formel:

ang = 180+round(math.atan2(x, y)*(180/math.pi),0)

Ist eigentlich eine Vereinfachung, denn hier wird davon ausgegangen, dass das Magnetometer parallel zum Boden ausgerichtet ist (d.h. die Z-Achse senkrecht zur Erdoberfläche steht).

Mit Hilfe eines Acceleromters kannst du die Beschleunigung auf 3 Achsen messen, mit Hilfe dieser Werte kannst du dir deinen Winkel um alle drei Achsen ausrechnen, d.h. du kennst Pitch (X-Winkel), Yaw (Z-Winkel) und Roll (Y-Winkel) (alles im Bezug auf die Erdoberfläche).
Wenn du jetzt Pitch und Roll kennst, dann kannst du die Messung des Magnetometers für Neigung kompensieren (Pseudocode):


pitch = asin(ACC_X);
roll = asin(ACC_Y);

x = MAG_X * cos(pitch) + MAG_Z * sin(pitch);
y = MAG_X * sin(roll) * sin(pitch) + MAG_Y * cos(roll) - MAG_Z * sin(roll) * cos(pitch);

ang = atan2(y, x);


Alles nachzulesen auf https://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial

Spacecam
17.08.2013, 17:40
Du benötigst immer noch ein Accelerometer, denn schließlich willst du ja für Neigung kompensieren. Das Magnetometer misst ja erstmal nur die Stärke eines Magnetfeldes auf 3 Achsen. Diese Werte werden in der Einheit Gauß angegeben, d.h. du musst sie, wie du es bereits machst im Code, miteinander verrechnen, sodass du einen Winkel zum magnetischen Nordpol bekommst (<besserwisser>und erst dann ist es ein Kompass</besserwisser> :P).

Diese simple Formel:

ang = 180+round(math.atan2(x, y)*(180/math.pi),0)

Ist eigentlich eine Vereinfachung, denn hier wird davon ausgegangen, dass das Magnetometer parallel zum Boden ausgerichtet ist (d.h. die Z-Achse senkrecht zur Erdoberfläche steht).

Mit Hilfe eines Acceleromters kannst du die Beschleunigung auf 3 Achsen messen, mit Hilfe dieser Werte kannst du dir deinen Winkel um alle drei Achsen ausrechnen, d.h. du kennst Pitch (X-Winkel), Yaw (Z-Winkel) und Roll (Y-Winkel) (alles im Bezug auf die Erdoberfläche).
Wenn du jetzt Pitch und Roll kennst, dann kannst du die Messung des Magnetometers für Neigung kompensieren (Pseudocode):


pitch = asin(ACC_X);
roll = asin(ACC_Y);

x = MAG_X * cos(pitch) + MAG_Z * sin(pitch);
y = MAG_X * sin(roll) * sin(pitch) + MAG_Y * cos(roll) - MAG_Z * sin(roll) * cos(pitch);

ang = atan2(y, x);


Alles nachzulesen auf https://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial

ja danke, habe mir heute morgen eins bestellt.
Danke nochmal :)

Spacecam
20.08.2013, 16:52
Du benötigst immer noch ein Accelerometer, denn schließlich willst du ja für Neigung kompensieren. Das Magnetometer misst ja erstmal nur die Stärke eines Magnetfeldes auf 3 Achsen. Diese Werte werden in der Einheit Gauß angegeben, d.h. du musst sie, wie du es bereits machst im Code, miteinander verrechnen, sodass du einen Winkel zum magnetischen Nordpol bekommst (<besserwisser>und erst dann ist es ein Kompass</besserwisser> :P).

Diese simple Formel:

ang = 180+round(math.atan2(x, y)*(180/math.pi),0)




Ist eigentlich eine Vereinfachung, denn hier wird davon ausgegangen, dass das Magnetometer parallel zum Boden ausgerichtet ist (d.h. die Z-Achse senkrecht zur Erdoberfläche steht).

Mit Hilfe eines Acceleromters kannst du die Beschleunigung auf 3 Achsen messen, mit Hilfe dieser Werte kannst du dir deinen Winkel um alle drei Achsen ausrechnen, d.h. du kennst Pitch (X-Winkel), Yaw (Z-Winkel) und Roll (Y-Winkel) (alles im Bezug auf die Erdoberfläche).
Wenn du jetzt Pitch und Roll kennst, dann kannst du die Messung des Magnetometers für Neigung kompensieren (Pseudocode):


pitch = asin(ACC_X);
roll = asin(ACC_Y);

x = MAG_X * cos(pitch) + MAG_Z * sin(pitch);
y = MAG_X * sin(roll) * sin(pitch) + MAG_Y * cos(roll) - MAG_Z * sin(roll) * cos(pitch);

ang = atan2(y, x);


Alles nachzulesen auf https://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial






#!/usr/bin/env python3
import time
import random
import smbus
import math
import serial

bus = smbus.SMBus(1)
address = 0x1e


class SensorADXL345(object):
def __init__(self, bus_nr, addr):
self.bus = smbus.SMBus(bus_nr)
self.addr = addr

def read_data_beschl(self):
ax = self.bus.read_word_data(self.addr, 0x32)
ay = self.bus.read_word_data(self.addr, 0x34)
az = self.bus.read_word_data(self.addr, 0x36)
return (ax, ay, az)

bus = smbus.SMBus(1)
address = 0x1e

while True:
mitte = 0
bus.write_byte_data(address,0,80)
bus.write_byte_data(address,1,32)

bus.write_byte_data(address,2,1)
time.sleep(0.01)
x = y = z = 1.0
x = y = z = 1.0
x1=bus.read_byte_data(address,3)
x2=bus.read_byte_data(address,4)
x=x1*256.0+x2

if x>32767:
x-=65536
z1=bus.read_byte_data(address,5)
z2=bus.read_byte_data(address,6)
z=z1*256.0+z2

if z>32767:
z-=65536
y1=bus.read_byte_data(address,7)
y2=bus.read_byte_data(address,8)
y=y1*256.0+y2

if y>32767:
y-=65536


ang = 180+round(math.atan2(x, y)*(180/math.pi),0)
sensor = SensorADXL345(1, 0x53)
xm, ym, zm = sensor.read_data_beschl()
pitch = xm
roll = ym
x = x * math.cos(pitch) + z * math.sin(pitch);
y = x * math.sin(roll) * math.sin(pitch) + y * math.cos(roll) - z * math.sin(roll) * math.cos(pitch);
ang2 = 180+round(math.atan2(x, y)*(180/math.pi),0)
print "alt",ang, "neu",ang2
time.sleep(2)


die alten werte stimmen nur die neuen mit Zusatz sensor sind total falsch. Was is das prob?


wenn ich pitch und roll auf 0 setze kommt der richtige winkel raus...nur wenn ich die Accelerometer werte nehme nicht mehr...

Spacecam
20.08.2013, 20:27
sensor = SensorADXL345(1, 0x53)
mx, my, mz, = sensor.read_data_beschl()
#print mx, my, mz
pitchAccelXh = math.atan2(my / 1024, (mz / 1024))
rollAccelYh = math.atan2(mx / 1024, (mz / 1024))

cos_roll= math.cos(pitchAccelXh);
sin_roll = math.sin(pitchAccelXh);
cos_pitch = math.cos(rollAccelYh);
sin_pitch = math.sin(rollAccelYh);

mag_X = x;
mag_Y = y;
mag_Z = z;


Yh = mag_Y * cos_roll - mag_Z * sin_roll;
Xh = mag_X * cos_pitch + mag_Y * sin_roll * sin_pitch + mag_Z * cos_roll * sin_pitch;
ang = 180+round(math.atan2(x, y)*(180/math.pi),0)
realHeading = 180+round(math.atan2(Xh, Yh)*(180/math.pi),0)
print "alt",ang,"neu",realHeading
time.sleep(1)



jetzt geht es solange der Kompass grade ist.
In diesen fall stimmen alter und neuer wert überein (is ja normal) sobalt ich den Kompass + accelerometer kippe ist der alte wert fast besser als der neu ausgerechnete^^

jemand eine Idee woran das liegen könnte?

Torrentula
22.08.2013, 11:16
Sorry, dass ich erst jetzt antworte, du scheinst in deinem code bei der Berechnung von Xh und Yh Pitch und Roll teilweise durcheinander gebracht zu haben.

So müsste es sein:


Xh = mag_X * cos_pitch + mag_Z * sin_pitch
Yh = (mag_X * sin_roll * sin_pitch + mag_Y * cos_roll) - mag_Z * sin_roll * cos_pitch