@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))