Files
mixly3-server/mixly/boards/default/micropython/build/lib/mmc5603.py

150 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
MMC5603
Micropython library for the MMC5603NJMagnetic
=======================================================
#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