""" MMC5603 Micropython library for the MMC5603NJ(Magnetic) ======================================================= #Preliminary composition 20221017 dahanzimin From the Mixly Team """ import time,math from micropython import const MMC5603_ADDRESS = const(0x30) MMC5603_REG_DATA = const(0x00) MMC5603_REG_TMP = const(0x09) MMC5603_REG_ODR = const(0x1A) MMC5603_REG_CTRL0 = const(0x1B) MMC5603_REG_CTRL1 = const(0x1C) MMC5603_REG_CTRL2 = const(0x1D) MMC5603_REG_X_THD = const(0x1E) MMC5603_REG_Y_THD = const(0x1F) MMC5603_REG_Z_THD = const(0x20) MMC5603_REG_ST_X_VAL = const(0x27) MMC5603_REG_DEVICE_ID = const(0x39) class MMC5603: def __init__(self, i2c_bus): self._device = i2c_bus self._address = MMC5603_ADDRESS self.raw_x = 0.0 self.raw_y = 0.0 self.raw_z = 0.0 if self._chip_id() != 0x10: #Check product ID raise AttributeError("Cannot find a MMC5603") try: #Read calibration file import magnetic_cal self._offset_x = magnetic_cal._offset_x self._offset_y = magnetic_cal._offset_y self._offset_z = magnetic_cal._offset_z except: self._offset_x = 524288 self._offset_y = 524288 self._offset_z = 524288 #print("offset:",self._offset_x ,self._offset_y,self._offset_z) self._auto_selftest() #Auto self-test registers configuration self._set() self._continuous_mode(0x00, 50) #Work mode setting time.sleep(0.05) def _wreg(self, reg, val): '''Write memory address''' self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) def _rreg(self, reg,nbytes=1): '''Read memory address''' return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] def _chip_id(self): return self._rreg(MMC5603_REG_DEVICE_ID) def _auto_selftest(self): '''Auto self-test registers configuration''' st_thd_reg=[0,0,0] st_thr_data=[0,0,0] #/* Read trim data from reg 0x27-0x29 */ _buffer=self._rreg(MMC5603_REG_ST_X_VAL,3) for i in range(0, 3, 1): st_thr_data[i]=(_buffer[i]-128)*32 if st_thr_data[i] < 0: st_thr_data[i]=-st_thr_data[i] st_thd=(st_thr_data[i]-st_thr_data[i]//5)//8 if st_thd > 255: st_thd_reg[i]=0xFF else: st_thd_reg[i]=st_thd #/* Write threshold into the reg 0x1E-0x20 */ self._wreg(MMC5603_REG_X_THD, st_thd_reg[0]) self._wreg(MMC5603_REG_Y_THD, st_thd_reg[1]) self._wreg(MMC5603_REG_Z_THD, st_thd_reg[2]) def _set(self): '''Do SET operation''' self._wreg(MMC5603_REG_CTRL0, 0X08) time.sleep(0.005) def _continuous_mode(self,bandwith,sampling_rate): '''Work mode setting''' self._wreg(MMC5603_REG_CTRL1, bandwith) self._wreg(MMC5603_REG_ODR, sampling_rate) self._wreg(MMC5603_REG_CTRL0, 0X80|0X20) self._wreg(MMC5603_REG_CTRL2, 0x10) def getdata(self): _buf=self._rreg( MMC5603_REG_DATA,9) #/* Transform to unit Gauss */ self.raw_x=(_buf[0] << 12) | (_buf[1] << 4) | (_buf[6] >> 4) self.raw_y=(_buf[2] << 12) | (_buf[3] << 4) | (_buf[7] >> 4) self.raw_z=(_buf[4] << 12) | (_buf[5] << 4) | (_buf[8] >> 4) return (-0.0625*(self.raw_x-self._offset_x), -0.0625*(self.raw_y-self._offset_y), -0.0625*(self.raw_z-self._offset_z)) def calibrate(self): print("The magnetic field will be calibrated") print("Please pick up the board and rotate the '8' shape in the air") time.sleep(2) self.getdata() min_x = max_x = self.raw_x min_y = max_y = self.raw_y min_z = max_z = self.raw_z ticks_start = time.ticks_ms() while (time.ticks_diff(time.ticks_ms(), ticks_start) < 20000) : self.getdata() min_x = min(self.raw_x, min_x) max_x = max(self.raw_x, max_x) min_y = min(self.raw_y, min_y) max_y = max(self.raw_y, max_y) min_z = min(self.raw_z, min_z) max_z = max(self.raw_z, max_z) time.sleep_ms(20) if time.ticks_diff(time.ticks_ms(), ticks_start) % 20 ==0: print("=",end ="") print(" 100%") self._offset_x = (max_x + min_x) / 2 self._offset_y = (max_y + min_y) / 2 self._offset_z = (max_z + min_z) / 2 print("Save x_offset:{}, y_offset:{}, z_offset:{}".format(self._offset_x,self._offset_y,self._offset_z)) s_f = open("magnetic_cal.py", "w+") s_f.write("_offset_x="+str(self._offset_x)+"\n") s_f.write("_offset_y="+str(self._offset_y)+"\n") s_f.write("_offset_z="+str(self._offset_z)+"\n") s_f.close() time.sleep(2) def getstrength(self): _x,_y,_z=self.getdata() return (math.sqrt(math.pow(_x, 2) + pow(_y, 2) + pow(_z, 2))) def getangle(self,upright=False): _x,_y,_z=self.getdata() if upright: #vertical angle=math.atan2(_z, -_x)*(180 / math.pi) + 180 + 3 return angle if angle<360 else angle-360 else: #horizontal angle=math.atan2(_y, -_x)*(180 / math.pi) + 180 + 3 return angle if angle<360 else angle-360