Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
sgall17a committed Jul 16, 2021
1 parent e88019e commit 1c29477
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 0 deletions.
163 changes: 163 additions & 0 deletions as5600.py
@@ -0,0 +1,163 @@
from machine import I2C,Pin
from micropython import const
from ustruct import unpack, pack
from collections import namedtuple
from time import sleep

AS5600_id = const(0x36) #Device ID
m12 = const((1<<12)-1) #0xFFF



REGS=namedtuple('REGS','ZMCO ZPOS MPOS MANG CONF RAWANGLE ANGLE STATUS AGC MAGNITUDE BURN')
r = REGS(0,1,3,5,7,0xc,0xe,0x0b,0x1a,0xb,0xff)

#You cant overwrite __attribute__ in micropython but you can use Descriptors
class RegDescriptor:
"Read and write a bit field from a register"

def __init__(self,reg,shift,mask,buffsize=2):
"initialise with specific identifiers for the bit field"

self.reg = reg
self.shift = shift
self.mask = mask
self.buffsize = buffsize
self.writeable = (r.ZMCO,r.ZPOS,r.MPOS,r.MANG,r.CONF,r.BURN)
self.cache={}
#NB the I2c object and the device name come from the main class via an object

def get_register(self,obj):
"Read an I2C register"
#cache those registers with values that will not change.
#Dont bother caching bit fields.
if self.reg in self.cache:
return self.cache[self.reg]

#print ('reading now the actual device now')

buff = obj.i2c.readfrom_mem(obj.device,self.reg,self.buffsize)


if self.buffsize == 2:
v = unpack(">H",buff)[0] #2 bytes big endian
else:
v = unpack(">B",buff)[0]


#cache writeable values since they are the ones that will not change in useage
if self.reg in self.writeable:
self.cache[self.reg] = v

return v

def __get__(self,obj,objtype):
"Get the register then extract the bit field"
v = self.get_register(obj)
if self.reg == 11:
print(self.reg,self.shift,self.mask)
v >>= self.shift
v &= self.mask
return v

def __set__(self,obj,value):
"Insert a new value into the bit field of the old value then write it back"
if not self.reg in self.writeable:
raise AttributeError('Register is not writable')
oldvalue = self.get_register(obj)
#oldvalue <<= self.shift # get_register() does a shift, so we have to shift it back
insertmask = 0xffff - (self.mask << self.shift) #make a mask for a hole
oldvalue &= insertmask # AND a hole in the old value
value &= self.mask # mask our new value in case it is too big
value <<= self.shift
oldvalue |= value # OR the new value back into the hole
if self.buffsize == 2:
buff = pack(">H",oldvalue)
else:
buff = pack(">B",oldvalue)

obj.i2c.writeto_mem(obj.device,self.reg,buff) # write result back to the AS5600



class AS5600:
def __init__(self,i2c,device):
self.i2c = i2c
self.device = device
self.writeable =(r.ZMCO,r.ZPOS,r.MPOS,r.MANG,r.CONF,r.BURN)

#Use descriptors to read and write a bit field from a register
#1. we read one or two bytes from i2c
#2. We shift the value so that the least significant bit is bit zero
#3. We mask off the bits required (most values are 12 bits hence m12)
ZMCO= RegDescriptor(r.ZMCO,shift=0,mask=3,buffsize=1) #1 bit
ZPOS= RegDescriptor(r.ZPOS,0,m12)
MPOS= RegDescriptor(r.MPOS,0,m12)
MANG= RegDescriptor(r.MANG,0,m12)
CONF= RegDescriptor(r.CONF,0,(1<<14)-1) # this register has 14 bits
RAWANGLE= RegDescriptor(r.RAWANGLE,0,m12)
ANGLE = RegDescriptor(r.ANGLE,0,m12)
STATUS= RegDescriptor(r.STATUS,0,m12)
AGC= RegDescriptor(r.AGC,0,0xF,1)
MAGNITUDE= RegDescriptor(r.MAGNITUDE,0,m12)
BURN= RegDescriptor(r.BURN,0,0xF,1)

#Configuration bit fields
PM = RegDescriptor(r.CONF,0,0x3) #2bits
HYST = RegDescriptor(r.CONF,2,0x3)
OUTS = RegDescriptor(r.CONF,4,0x3)
PWMF = RegDescriptor(r.CONF,6,0x3)
SF = RegDescriptor(r.CONF,8,0x3)
FTH = RegDescriptor(r.CONF,10,0x7) #3 bits
WD = RegDescriptor(r.CONF,13,0x1) #1 bit

#status bit fields
MH = RegDescriptor(r.STATUS,3,0x1) #2bits Magnet too strong (high)
ML = RegDescriptor(r.STATUS,4,0x1) #2bits Magnet too weak (low)
MD = RegDescriptor(r.STATUS,5,0x1) #2bits Magnet just right

def scan(self):
"Debug utility function to check your i2c bus"
devices = self.i2c.scan()
print(devices)
if AS5600_id in devices:
print('Found AS5600 (id =',hex(AS5600_id),')')
print(self.CONF)

def burn_angle(self):
"Burn ZPOS and MPOS -(can only do this 3 times)"
self.BURN = 0x80

def burn_setting(self):
"Burn config and mang- (can only do this once)"
self.BURN = 0x40

def magnet_status(self):
s = "Magnet "
# print(self.MD)
return
if self.MD == 1:
s += " detected"
else:
s += " not detected"


if self.ML == 1:
s+ " (magnet too weak)"

if self.MH == 1:
s+ " (magnet too strong)"
return s


i2c = I2C(0,scl=Pin(17),sda=Pin(16),freq=400000)


z = AS5600(i2c,AS5600_id)
z.scan()
whatever = 89
while True:
print(z.MD)
sleep(1)


70 changes: 70 additions & 0 deletions as5600_example.py
@@ -0,0 +1,70 @@
from time import sleep
from as5600 import *



#The class AS5600 is pretty low level.
# This inherits adds some higher level functions

class AS5600_high(AS5600):

def __init__(self,i2c,device):
super().__init__( i2c,device)

def scan(self):
"Debug utility function to check your i2c bus"
devices = self.i2c.scan()
print(devices)
if AS5600_id in devices:
print('Found AS5600 (id =',hex(AS5600_id),')')
print(self.CONF)

def burn_angle(self):
"Burn ZPOS and MPOS -(can only do this 3 times)"
#uncomment if you need it
#self.BURN = 0x80

def burn_setting(self):
"Burn config and mang- (can only do this once)"
#uncomment if you need it
#self.BURN = 0x40

def magnet_status(self):
"Magnet status - this does not seem to make sense ? why"
s = "Magnet "

if self.MD == 1:
s += " detected"
else:
s += " not detected"

if self.ML == 1:
s+ " (magnet too weak)"

if self.MH == 1:
s+ " (magnet too strong)"
return s


i2c = I2C(0,scl=Pin(17),sda=Pin(16),freq=400000)


z = AS5600_high(i2c,AS5600_id)
z.scan()

#read write
#This will probably make your device crazy. Just poweron/poweroff
z.CONF = 0x38
sleep(2)
print ("should be 0x38", hex(z.CONF))
sleep(5)
z.CONF = 0x64
print ("should be 0x64", hex(z.CONF) )


for i in range(10):
#print(z.magnet_status())
print ('ZANGLE',z.RAWANGLE)
print ('ANGLE', z.ANGLE)
print ('Magnet detected',z.MD)
sleep(1)

0 comments on commit 1c29477

Please sign in to comment.