Dziś chciałbym przedstawić kolejny czujnik: HMC 5883L, który jest cyfrowym, o 12 bitowej rozdzielczości, 3-osiowym magnetometrem pozwalającym na pomiar w szerokim zakresie wielkości pola magnetycznego wynoszącego do ±8 gausa. Charakteryzuje się również bardzo niskim poborem prądu (100µA). HMC5883L komunikuje się ze światem za pomocą magistrali IIC.
Założenia:
- Cubietruck/Cubieboard/Raspberry Pi
- DVK570 (niewymagana, jednak jeśli nie masz kitu - musisz sam zadbać o odpowiednie parametry prądowe np dla diod LED)
- CTdebian 4.1 lub nowszy (do pobrania ze strony Igora Pecovnik-a lub z działu Wsady). W przypadku Raspberry Pi użyć można dystrybucji Raspian.
- Czujnik z układem HMC 5883L, ja wykorzystałem moduł firmy Geeetech:
Przestroga 1.
Wszystkie operacje wykonuję jako uprzywilejowany użytkownik root . Nie jest to dobra praktyka więc proponuję używać sudo i wykonywać wszystkie komendy z poziomu normalnego użytkownika...
Uwaga.
Dystrybucja, której używam to kompilacja ze źródeł CTDebian Igora Pecovnik-a. Możesz pobrać najnowszą wersję ze strony Igora lub skorzystać z mojej kompilacji.
Przestroga 2
Wszystko co robisz - robisz na własną odpowiedzialność. W trakcie tutoriala wykonywane są czynności, które mogą uszkodzić twoje urządzenie...
Zaczynamy
Do obsługi modułu z HMC5883L wymagane są tylko 2 linie sterujące SDA/SCL i zasilanie 3.3V do 5V. Ja korzystam z tego niższego napięcie 3V3, pamiętaj jednak, że chcąc skorzystać z wyższego napięcia zasilania musisz dopasować poziom linii SCL i SDA za pomocą odpowiedniego konwertera.
Wykrywanie HMC5883L:
Code: Select all
root@ctdev:~/HMC5883L# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@ctdev:~/HMC5883L#
Code: Select all
#!/usr/bin/env python
#vim: set fileencoding=UTF-8 :
# HMC5888L Magnetometer (Digital Compass) wrapper class
# Based on https://bitbucket.org/thinkbowl/i2clibraries/src/14683feb0f96,
# but uses smbus rather than quick2wire and sets some different init
# params.
import smbus
import math
import time
import sys
class hmc5883l:
__scales = {
0.88: [0, 0.73],
1.30: [1, 0.92],
1.90: [2, 1.22],
2.50: [3, 1.52],
4.00: [4, 2.27],
4.70: [5, 2.56],
5.60: [6, 3.03],
8.10: [7, 4.35],
}
def __init__(self, port=1, address=0x1E, gauss=1.3, declination=(0,0)):
self.bus = smbus.SMBus(port)
self.address = address
(degrees, minutes) = declination
self.__declDegrees = degrees
self.__declMinutes = minutes
self.__declination = (degrees + minutes / 60) * math.pi / 180
(reg, self.__scale) = self.__scales[gauss]
self.bus.write_byte_data(self.address, 0x00, 0x70) # 8 Average, 15 Hz, normal measurement
self.bus.write_byte_data(self.address, 0x01, reg << 5) # Scale
self.bus.write_byte_data(self.address, 0x02, 0x00) # Continuous measurement
def declination(self):
return (self.__declDegrees, self.__declMinutes)
def twos_complement(self, val, len):
# Convert twos compliment to integer
if (val & (1 << len - 1)):
val = val - (1<<len)
return val
def __convert(self, data, offset):
val = self.twos_complement(data[offset] << 8 | data[offset+1], 16)
if val == -4096: return None
return round(val * self.__scale, 4)
def axes(self):
data = self.bus.read_i2c_block_data(self.address, 0x00)
#print map(hex, data)
x = self.__convert(data, 3)
y = self.__convert(data, 7)
z = self.__convert(data, 5)
return (x,y,z)
def heading(self):
(x, y, z) = self.axes()
headingRad = math.atan2(y, x)
headingRad += self.__declination
# Correct for reversed heading
if headingRad < 0:
headingRad += 2 * math.pi
# Check for wrap and compensate
elif headingRad > 2 * math.pi:
headingRad -= 2 * math.pi
# Convert to degrees from radians
headingDeg = headingRad * 180 / math.pi
return headingDeg
def degrees(self, headingDeg):
degrees = math.floor(headingDeg)
minutes = round((headingDeg - degrees) * 60)
return (degrees, minutes)
def __str__(self):
(x, y, z) = self.axes()
return "Axis X: " + str(x) + "\n" \
"Axis Y: " + str(y) + "\n" \
"Axis Z: " + str(z) + "\n" \
"Declination: " + self.degrees(self.declination()) + "\n" \
"Heading: " + self.degrees(self.heading()) + "\n"
if __name__ == "__main__":
# http://magnetic-declination.com/Great%20Britain%20(UK)/Harrogate#
compass = hmc5883l(gauss = 4.7, declination = (-2,5))
while True:
sys.stdout.write("\rHeading: " + str(compass.degrees(compass.heading())) + " ")
sys.stdout.flush()
time.sleep(0.5)
Code: Select all
root@ctdev:~/HMC5883L# python hmc5883l.py
Heading: (165.0, 12.0)
Heading: (163.0, 58.0)
Heading: (157.0, 42.0)
Heading: (150.0, 46.0)
Heading: (150.0, 3.0)
Heading: (146.0, 11.0)
Heading: (138.0, 25.0)
Heading: (217.0, 8.0)
Heading: (223.0, 50.0) ^CTraceback (most recent call last):
File "hmc5883l.py", line 99, in <module>
time.sleep(0.5)
KeyboardInterrupt
root@ctdev:~/HMC5883L#