151 lines
5.1 KiB
Python
151 lines
5.1 KiB
Python
|
|
import time
|
||
|
|
import setenv
|
||
|
|
|
||
|
|
from machine import I2C, Pin
|
||
|
|
|
||
|
|
ADDRESS = 0x40
|
||
|
|
ZMCO = 0x00
|
||
|
|
ZPOS = 0x01
|
||
|
|
MPOS = 0x03
|
||
|
|
MANG = 0x05
|
||
|
|
CONF_REG = 0x07
|
||
|
|
STATUS_REG = 0x0B
|
||
|
|
RAWANGLE = 0x0c
|
||
|
|
ANGLE_REG = 0x0E
|
||
|
|
AGC_REG = 0x1A
|
||
|
|
MAGNITUDE = 0x1b
|
||
|
|
BURN = 0xff
|
||
|
|
|
||
|
|
|
||
|
|
class AS5600L:
|
||
|
|
|
||
|
|
def __init__(self,
|
||
|
|
i2c_id = setenv.ENCODER_NUMBER,
|
||
|
|
sda = setenv.ENCODER_SDA_PIN,
|
||
|
|
scl = setenv.ENCODER_SCL_PIN,
|
||
|
|
i2c_freq = setenv.ENCODER_I2C_FREQUENCE,
|
||
|
|
hyst = setenv.ENCODER_HYST,
|
||
|
|
power_mode = 0,
|
||
|
|
watchdog = 0,
|
||
|
|
fast_filter_threshold = 0,
|
||
|
|
slow_filter = 0,
|
||
|
|
pwm_freq = 0,
|
||
|
|
output_stage = 0):
|
||
|
|
"""Init
|
||
|
|
Args:
|
||
|
|
i2c_id (int, optional): ID of the I2C bus. Defaults to 0.
|
||
|
|
sda (int, optional) : gpio of the I2C bus. Defaults to 0.
|
||
|
|
scl (int, optional) : gpio of clock for I2C bus. Defaults to 1.
|
||
|
|
i2c_freq (int, optional): I2C Ferequency. Default is max. Defaults to 1000000.
|
||
|
|
hyst (int, optional): Hysteresis: 0->3. Defaults to 0.
|
||
|
|
power_mode (int, optional): Power Mode: 0->3. Defaults to 0.
|
||
|
|
watchdog (int, optional): Enable the watchdog. Defaults to 0.
|
||
|
|
fast_filter_threshold (int, optional): Threshold value for the fast filter: 0->7. Defaults to 0.
|
||
|
|
slow_filter (int, optional): Slow filter mode: 0->3. Defaults to 0.
|
||
|
|
pwm_freq (int, optional): Output PWM frequency: 0->3. Defaults to 0.
|
||
|
|
output_stage (int, optional): Output mode (see datasheet): 0->2. Defaults to 0.
|
||
|
|
"""
|
||
|
|
self.i2c = I2C(i2c_id, scl=Pin(scl), sda=Pin(sda), freq=i2c_freq)
|
||
|
|
print(self.i2c.scan())
|
||
|
|
time.sleep_ms(100)
|
||
|
|
c1 = 0x00
|
||
|
|
c2 = 0x00
|
||
|
|
# # set watchdog 0,1
|
||
|
|
# if watchdog in range(0,2):
|
||
|
|
# c1 = c1 | (watchdog << 5)
|
||
|
|
# # set fast filter threshold 0->7
|
||
|
|
# if fast_filter_threshold in range(0,8):
|
||
|
|
# c1 = c1 | (fast_filter_threshold << 2)
|
||
|
|
# # set the slow filter 0->3
|
||
|
|
# if slow_filter in range(0,4):
|
||
|
|
# c1 = c1 | slow_filter
|
||
|
|
# # set PWM frequency 0->3
|
||
|
|
# if pwm_freq in range(0,4):
|
||
|
|
# c2 = c2 | (pwm_freq << 6)
|
||
|
|
# # set output stage 0->2
|
||
|
|
# if output_stage in range(0,2):
|
||
|
|
# c2 = c2 | (output_stage << 4)
|
||
|
|
# # set power_mode 0->3
|
||
|
|
# if power_mode in range(0, 4):
|
||
|
|
# c2 = c2 | power_mode
|
||
|
|
# # set Hysteresis 0->3
|
||
|
|
# if hyst in range(0, 4):
|
||
|
|
# c2 = c2 | (hyst << 2)
|
||
|
|
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([CONF_REG, c1, c2]))
|
||
|
|
|
||
|
|
def get_status(self):
|
||
|
|
"""Get the status of the ASL560L
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict: Dictionary of the different statuses
|
||
|
|
"""
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([STATUS_REG]))
|
||
|
|
status = int.from_bytes(self.i2c.readfrom(ADDRESS, 1), 'big')
|
||
|
|
mh = bool(status & 0b00001000)
|
||
|
|
ml = bool(status & 0b00010000)
|
||
|
|
md = bool(status & 0b00100000)
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([AGC_REG]))
|
||
|
|
agc = int.from_bytes(self.i2c.readfrom(ADDRESS, 1), 'big')
|
||
|
|
|
||
|
|
return {
|
||
|
|
"magnetDetected": md,
|
||
|
|
"magnetTooWeak": ml,
|
||
|
|
"magnetTooStrong": mh,
|
||
|
|
"agc": agc
|
||
|
|
}
|
||
|
|
|
||
|
|
def is_ok(self) -> bool:
|
||
|
|
"""Reads the status values to determine if the magnet is able to be read.
|
||
|
|
Returns:
|
||
|
|
bool: True if the magnet can be detercted accurately
|
||
|
|
"""
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([STATUS_REG]))
|
||
|
|
status = int.from_bytes(self.i2c.readfrom(ADDRESS, 1), 'big')
|
||
|
|
mh = bool(status & 0b00001000)
|
||
|
|
ml = bool(status & 0b00010000)
|
||
|
|
md = bool(status & 0b00100000)
|
||
|
|
|
||
|
|
if md and not mh and not ml:
|
||
|
|
return True
|
||
|
|
else:
|
||
|
|
return False
|
||
|
|
|
||
|
|
def get_angle(self) -> int:
|
||
|
|
"""Get the raw 12bit angle value
|
||
|
|
Returns:
|
||
|
|
int: 0->4095
|
||
|
|
"""
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([ANGLE_REG]))
|
||
|
|
return int.from_bytes(self.i2c.readfrom(ADDRESS, 2), 'big')
|
||
|
|
|
||
|
|
|
||
|
|
def get_angle_degrees(self):
|
||
|
|
"""Get the angle in degrees, IF the magnet can be read
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
float: Degrees (0->359) if magnet can be read otherwise None.
|
||
|
|
"""
|
||
|
|
if self.is_ok():
|
||
|
|
return (float(self.get_angle()))
|
||
|
|
else:
|
||
|
|
# if the magnet cannot be read then the angle is unreliable, so return None.
|
||
|
|
return None
|
||
|
|
|
||
|
|
def get_angle_degrees_fast(self):
|
||
|
|
"""Get the angle in degrees
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
float: Degrees (0->359) if magnet can be read otherwise None.
|
||
|
|
"""
|
||
|
|
self.i2c.writeto(ADDRESS, b'\x0c')
|
||
|
|
return (float(int.from_bytes(self.i2c.readfrom(ADDRESS, 2), 'big')))
|
||
|
|
|
||
|
|
def get_conf(self):
|
||
|
|
"""Internal healper function to read the raw config value
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
int: raw value
|
||
|
|
"""
|
||
|
|
self.i2c.writeto(ADDRESS, bytes([CONF_REG]))
|
||
|
|
return int.from_bytes(self.i2c.readfrom(ADDRESS, 2), 'big')
|