@tttadam Updated code. The name of the methods are changed to reflect PEP8. SO
readRaw() -> read_raw
and a new
read_scaled(), which returns the values as Gauss and °C.
The constructor has an optional second argument for the temperature offset in °C .
#
# initial code by Sebastian Folz, M.Sc. at
# http://nobytes.blogspot.com/2018/03/qmc5883-magnetic-field-sensor.html
# which, I assume, was itself ported from C-Code
# See also https://github.com/RigacciOrg/py-qmc5883l
#
# Changes and Additions:
# - port to micropython's I2C methods
# - add method read() for scaled values
# - reading register values into a static buffer
# - parsed register values in one single struct call
# - changed method names according to PEP8
# - apply PyLint and fixed bugs & warnings reported by it
#
import time
import struct
from machine import idle
class QMC5883:
#Default I2C address
ADDR = 0x0D
#QMC5883 Register numbers
X_LSB = 0
X_MSB = 1
Y_LSB = 2
Y_MSB = 3
Z_LSB = 4
Z_MSB = 5
STATUS = 6
T_LSB = 7
T_MSB = 8
CONFIG = 9
CONFIG2 = 10
RESET = 11
STATUS2 = 12
CHIP_ID = 13
#Bit values for the STATUS register
STATUS_DRDY = 1
STATUS_OVL = 2
STATUS_DOR = 4
#Oversampling values for the CONFIG register
CONFIG_OS512 = 0b00000000
CONFIG_OS256 = 0b01000000
CONFIG_OS128 = 0b10000000
CONFIG_OS64 = 0b11000000
#Range values for the CONFIG register
CONFIG_2GAUSS = 0b00000000
CONFIG_8GAUSS = 0b00010000
#Rate values for the CONFIG register
CONFIG_10HZ = 0b00000000
CONFIG_50HZ = 0b00000100
CONFIG_100HZ = 0b00001000
CONFIG_200HZ = 0b00001100
#Mode values for the CONFIG register
CONFIG_STANDBY = 0b00000000
CONFIG_CONT = 0b00000001
# Mode values for the CONFIG2 register
CONFIG2_INT_DISABLE = 0b00000001
CONFIG2_ROL_PTR = 0b01000000
CONFIG2_SOFT_RST = 0b10000000
def __init__(self, i2c, offset=50.0):
self.i2c = i2c
self.temp_offset = offset
self.oversampling = QMC5883.CONFIG_OS64
self.range = QMC5883.CONFIG_2GAUSS
self.rate = QMC5883.CONFIG_100HZ
self.mode = QMC5883.CONFIG_CONT
self.register = bytearray(9)
self.reset()
def reset(self):
self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.RESET, 0x01)
time.sleep(0.1)
self.reconfig()
def reconfig(self):
# print("{0:b}".format(self.oversampling | self.range | self.rate | self.mode))
self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.CONFIG,
self.oversampling | self.range | self.rate | self.mode)
time.sleep(0.01)
self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.CONFIG2, QMC5883.CONFIG2_INT_DISABLE)
time.sleep(0.01)
def set_oversampling(self, x):
self.oversampling = x
self.reconfig()
def set_range(self, x):
self.range = x
self.reconfig()
def set_sampling_rate(self, x):
self.rate = x
self.reconfig()
def ready(self):
status = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.STATUS, 1)[0]
# prevent hanging up here.
# Happens when reading less bytes then then all 3 axis and will end up in a loop.
# So, return any data but avoid the loop.
if status == QMC5883.STATUS_DOR:
print("Incomplete read")
return QMC5883.STATUS_DRDY
return status & QMC5883.STATUS_DRDY
def read_raw(self):
try:
while not self.ready():
idle()
self.i2c.readfrom_mem_into(QMC5883.ADDR, QMC5883.X_LSB, self.register)
except OSError as e:
print ("OSError", e)
pass # just silently re-use the old values
# Convert the axis values to signed Short before returning
x, y, z, _, t = struct.unpack('<hhhBh', self.register)
return (x, y, z, t)
def read_scaled(self):
x, y, z, t = self.read_raw()
scale = 12000 if self.range == QMC5883.CONFIG_2GAUSS else 3000
return (x / scale, y / scale , z / scale, (t / 100 + self.temp_offset))