kopia lustrzana https://github.com/GuyCarver/MicroPython
Modifications to apds9960 driver.
Added comments and made some memory improvements using _ prefix on all constants.master
rodzic
92645e0524
commit
84e5e5ee34
172
lib/APDS9960.py
172
lib/APDS9960.py
|
@ -1,5 +1,7 @@
|
||||||
# MicroPython apds9960 motion detection device driver.
|
# MicroPython apds9960 motion detection device driver.
|
||||||
|
|
||||||
|
#NOTE: This code is derived from a mix of Sparkfun and Adafruit arduino drivers.
|
||||||
|
|
||||||
#todo: Have a mix of styles here. Some use properties for setters while others use functions.
|
#todo: Have a mix of styles here. Some use properties for setters while others use functions.
|
||||||
|
|
||||||
import pyb
|
import pyb
|
||||||
|
@ -129,64 +131,66 @@ class apds9960(object) :
|
||||||
_GPULSE_16US = const(2)
|
_GPULSE_16US = const(2)
|
||||||
_GPULSE_32US = const(3)
|
_GPULSE_32US = const(3)
|
||||||
|
|
||||||
|
#Value Location data.
|
||||||
#Following are the bytes describing the data packed into each 8 bit value on the chip.
|
#Following are the bytes describing the data packed into each 8 bit value on the chip.
|
||||||
#Nibble 1 = position, 0 = bits
|
#Nibble 1 = position, 0 = bits
|
||||||
|
#NOTE: Commented out currently unused locations.
|
||||||
|
|
||||||
ENABLE_PON = const(0x01)
|
_ENABLE_PON = const(0x01)
|
||||||
ENABLE_AEN = const(0x11)
|
_ENABLE_AEN = const(0x11)
|
||||||
ENABLE_PEN = const(0x21)
|
_ENABLE_PEN = const(0x21)
|
||||||
ENABLE_WEN = const(0x31)
|
# _ENABLE_WEN = const(0x31)
|
||||||
ENABLE_AIEN = const(0x41)
|
# _ENABLE_AIEN = const(0x41)
|
||||||
ENABLE_PIEN = const(0x51)
|
_ENABLE_PIEN = const(0x51)
|
||||||
ENABLE_GEN = const(0x61)
|
_ENABLE_GEN = const(0x61)
|
||||||
|
|
||||||
PERS_APERS = const(0x04)
|
# _PERS_APERS = const(0x04)
|
||||||
PERS_PPERS = const(0x44)
|
_PERS_PPERS = const(0x44)
|
||||||
|
|
||||||
PPULSE_PPULSE = const(0x06)
|
_PPULSE_PPULSE = const(0x06)
|
||||||
PPULSE_PPLEN = const(0x62)
|
_PPULSE_PPLEN = const(0x62)
|
||||||
|
|
||||||
CONTROL_AGAIN = const(0x02)
|
_CONTROL_AGAIN = const(0x02)
|
||||||
CONTROL_PGAIN = const(0x22)
|
_CONTROL_PGAIN = const(0x22)
|
||||||
CONTROL_LDRIVE = const(0x42)
|
_CONTROL_LDRIVE = const(0x42)
|
||||||
|
|
||||||
CONFIG2_LED_BOOST = const(0x42)
|
_CONFIG2_LED_BOOST = const(0x42)
|
||||||
CONFIG2_CPSIEN = const(0x61) #Clear photo diode saturation int enable.
|
# _CONFIG2_CPSIEN = const(0x61) #Clear photo diode saturation int enable.
|
||||||
CONFIG2_PSIEN = const(0x71) #Proximity saturation interrupt enable.
|
# _CONFIG2_PSIEN = const(0x71) #Proximity saturation interrupt enable.
|
||||||
|
|
||||||
CONFIG3_PMASK_R = const(0x01)
|
# _CONFIG3_PMASK_R = const(0x01)
|
||||||
CONFIG3_PMASK_L = const(0x11)
|
# _CONFIG3_PMASK_L = const(0x11)
|
||||||
CONFIG3_PMASK_D = const(0x21)
|
# _CONFIG3_PMASK_D = const(0x21)
|
||||||
CONFIG3_PMASK_U = const(0x31)
|
# _CONFIG3_PMASK_U = const(0x31)
|
||||||
CONFIG3_SAI = const(0x41)
|
# _CONFIG3_SAI = const(0x41)
|
||||||
CONFIG3_PCMP = const(0x51)
|
# _CONFIG3_PCMP = const(0x51)
|
||||||
|
|
||||||
GCONFIG1_GEXPERS = const(0x02)
|
# _GCONFIG1_GEXPERS = const(0x02)
|
||||||
GCONFIG1_GEXMSK = const(0x24)
|
# _GCONFIG1_GEXMSK = const(0x24)
|
||||||
GCONFIG1_GFIFOTH = const(0x62)
|
_GCONFIG1_GFIFOTH = const(0x62)
|
||||||
|
|
||||||
GCONFIG2_GWTIME = const(0x03)
|
_GCONFIG2_GWTIME = const(0x03)
|
||||||
GCONFIG2_GLDRIVE = const(0x32)
|
# _GCONFIG2_GLDRIVE = const(0x32)
|
||||||
GCONFIG2_GGAIN = const(0x52)
|
_GCONFIG2_GGAIN = const(0x52)
|
||||||
|
|
||||||
GCONFIG3_GDIMS = const(0x02)
|
_GCONFIG3_GDIMS = const(0x02)
|
||||||
|
|
||||||
GCONFIG4_GMODE = const(0x01)
|
# _GCONFIG4_GMODE = const(0x01)
|
||||||
GCONFIG4_GIEN = const(0x12)
|
# _GCONFIG4_GIEN = const(0x12)
|
||||||
|
|
||||||
GPULSE_GPULSE = const(0x06)
|
_GPULSE_GPULSE = const(0x06)
|
||||||
GPULSE_GPLEN = const(0x62)
|
_GPULSE_GPLEN = const(0x62)
|
||||||
|
|
||||||
STATUS_AVALID = const(0x01)
|
_STATUS_AVALID = const(0x01)
|
||||||
STATUS_PVALID = const(0x11)
|
# _STATUS_PVALID = const(0x11)
|
||||||
STATUS_GINT = const(0x21)
|
# _STATUS_GINT = const(0x21)
|
||||||
STATUS_AINT = const(0x41)
|
# _STATUS_AINT = const(0x41)
|
||||||
STATUS_PINT = const(0x51)
|
# _STATUS_PINT = const(0x51)
|
||||||
STATUS_PGSTAT = const(0x61)
|
# _STATUS_PGSTAT = const(0x61)
|
||||||
STATUS_CPSTAT = const(0x71)
|
# _STATUS_CPSTAT = const(0x71)
|
||||||
|
|
||||||
GSTATUS_GVALID = const(0x01)
|
_GSTATUS_GVALID = const(0x01)
|
||||||
GSTATUS_GFOV = const(0x11)
|
# _GSTATUS_GFOV = const(0x11)
|
||||||
|
|
||||||
# Gesture wait time values
|
# Gesture wait time values
|
||||||
_GWTIME_0MS = const(0)
|
_GWTIME_0MS = const(0)
|
||||||
|
@ -219,10 +223,10 @@ class apds9960(object) :
|
||||||
_DefaultIntTimeMS = const(10)
|
_DefaultIntTimeMS = const(10)
|
||||||
|
|
||||||
def __init__( self, aLoc ) :
|
def __init__( self, aLoc ) :
|
||||||
"""aLoc I2C pin location is either 1, 'X', 2 or'Y'."""
|
'''aLoc I2C pin location is either 1, 'X', 2 or'Y'.'''
|
||||||
self._i2c = pyb.I2C(aLoc, pyb.I2C.MASTER)
|
self._i2c = pyb.I2C(aLoc, pyb.I2C.MASTER)
|
||||||
|
|
||||||
#Mirrors data on the controller.
|
#Mirrors data on the controller in order to eliminate need to read data from the controller on modification.
|
||||||
self._enable = 0 #Enable
|
self._enable = 0 #Enable
|
||||||
self._pers = 0 #Pers
|
self._pers = 0 #Pers
|
||||||
self._ppulse = 0 #PPulse
|
self._ppulse = 0 #PPulse
|
||||||
|
@ -263,31 +267,31 @@ class apds9960(object) :
|
||||||
self.begin()
|
self.begin()
|
||||||
|
|
||||||
def read( self, aLoc ) :
|
def read( self, aLoc ) :
|
||||||
"""Read 8 bit value and return."""
|
'''Read 8 bit value and return.'''
|
||||||
self._i2c.mem_read(self._b1, _ADDRESS, aLoc)
|
self._i2c.mem_read(self._b1, _ADDRESS, aLoc)
|
||||||
return self._b1[0]
|
return self._b1[0]
|
||||||
|
|
||||||
def readbuffer( self, aBuffer, aLoc ) :
|
def readbuffer( self, aBuffer, aLoc ) :
|
||||||
"""Read 8 bit values into given buffer."""
|
'''Read 8 bit values into given buffer.'''
|
||||||
self._i2c.mem_read(aBuffer, _ADDRESS, aLoc)
|
self._i2c.mem_read(aBuffer, _ADDRESS, aLoc)
|
||||||
|
|
||||||
def read16( self, aLoc ) :
|
def read16( self, aLoc ) :
|
||||||
"""Read 16 bit value and return."""
|
'''Read 16 bit value and return.'''
|
||||||
self._i2c.mem_read(self._b2, _ADDRESS, aLoc)
|
self._i2c.mem_read(self._b2, _ADDRESS, aLoc)
|
||||||
return (self._b2[1] << 8) | self._b2[0]
|
return (self._b2[1] << 8) | self._b2[0]
|
||||||
|
|
||||||
def write( self, aLoc, aVal ) :
|
def write( self, aLoc, aVal ) :
|
||||||
"""Write 8 bit value to given address. aVal may be a byte array."""
|
'''Write 8 bit value to given address. aVal may be a byte array.'''
|
||||||
self._i2c.mem_write(aVal, _ADDRESS, aLoc)
|
self._i2c.mem_write(aVal, _ADDRESS, aLoc)
|
||||||
|
|
||||||
def write16( self, aLoc, aVal ) :
|
def write16( self, aLoc, aVal ) :
|
||||||
"""Write 16 bit value to given address."""
|
'''Write 16 bit value to given address.'''
|
||||||
self._b2[0] = aVal
|
self._b2[0] = aVal
|
||||||
self._b2[1] = aVal >> 8
|
self._b2[1] = aVal >> 8
|
||||||
self._i2c.mem_write(self._b2, _ADDRESS, aLoc)
|
self._i2c.mem_write(self._b2, _ADDRESS, aLoc)
|
||||||
|
|
||||||
def reset( self ):
|
def reset( self ):
|
||||||
"""Reset the controller and set default frequency."""
|
'''Reset the controller and set default frequency.'''
|
||||||
self.write(0, _MODE1)
|
self.write(0, _MODE1)
|
||||||
self.setfreq(_DEFAULTFREQ)
|
self.setfreq(_DEFAULTFREQ)
|
||||||
|
|
||||||
|
@ -371,10 +375,12 @@ class apds9960(object) :
|
||||||
|
|
||||||
#GStatus
|
#GStatus
|
||||||
def getgstatus( self, aMember ) :
|
def getgstatus( self, aMember ) :
|
||||||
|
'''Get member of gstatus'''
|
||||||
self._gstatus = self.read(_GSTATUS)
|
self._gstatus = self.read(_GSTATUS)
|
||||||
return getvalue(self._gstatus, aMember)
|
return getvalue(self._gstatus, aMember)
|
||||||
|
|
||||||
def resetcounts( self ) :
|
def resetcounts( self ) :
|
||||||
|
'''Reset the gesture reading counters.'''
|
||||||
self._gestCnt = 0
|
self._gestCnt = 0
|
||||||
#todo - put these in an array.
|
#todo - put these in an array.
|
||||||
self._ucount = 0
|
self._ucount = 0
|
||||||
|
@ -383,13 +389,13 @@ class apds9960(object) :
|
||||||
self._rcount = 0
|
self._rcount = 0
|
||||||
|
|
||||||
def enableproximityint( self, aValue ) :
|
def enableproximityint( self, aValue ) :
|
||||||
self.setenable(ENABLE_PIEN, aValue)
|
self.setenable(_ENABLE_PIEN, aValue)
|
||||||
self.clearInterrupt()
|
self.clearInterrupt()
|
||||||
|
|
||||||
def proximityintthreshold( self, aValue, aPersistance ) :
|
def proximityintthreshold( self, aValue, aPersistance ) :
|
||||||
self.write(_PILT, aValue & 0xFF)
|
self.write(_PILT, aValue & 0xFF)
|
||||||
self.write(_PIHT, aValue >> 8)
|
self.write(_PIHT, aValue >> 8)
|
||||||
self.setpers(PERS_PPERS, min(aPersistance, 7))
|
self.setpers(_PERS_PPERS, min(aPersistance, 7))
|
||||||
|
|
||||||
def proximity( self ) :
|
def proximity( self ) :
|
||||||
return self.read(_PDATA)
|
return self.read(_PDATA)
|
||||||
|
@ -409,19 +415,19 @@ class apds9960(object) :
|
||||||
def enablegesture( self, aEnable ) :
|
def enablegesture( self, aEnable ) :
|
||||||
#If disabling make sure we aren't currently in gesture mode.
|
#If disabling make sure we aren't currently in gesture mode.
|
||||||
# Gesture mode is auto entered when proximity enter threshold is hit
|
# Gesture mode is auto entered when proximity enter threshold is hit
|
||||||
# so we don't need to enable it.
|
# so we don't need to enable it even though we disable on gesture disable.
|
||||||
if not aEnable :
|
if not aEnable :
|
||||||
self.setgconfig4(GCONFIG4_GMODE, False)
|
self.setgconfig4(GCONFIG4_GMODE, False)
|
||||||
self.setenable(ENABLE_GEN, aEnable)
|
self.setenable(_ENABLE_GEN, aEnable)
|
||||||
self.resetcounts()
|
self.resetcounts()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gesturevalid( self ) :
|
def gesturevalid( self ) :
|
||||||
"""Return True if gesture data exists."""
|
'''Return True if gesture data exists.'''
|
||||||
return self.getgstatus(GSTATUS_GVALID)
|
return self.getgstatus(_GSTATUS_GVALID)
|
||||||
|
|
||||||
def gesturedata( self ) :
|
def gesturedata( self ) :
|
||||||
"""Read gesture data and return as (u,d,l,r). Returns None of no data ready."""
|
'''Read gesture data and return as (u,d,l,r). Returns None of no data ready.'''
|
||||||
level = self.read(_GFLVL)
|
level = self.read(_GFLVL)
|
||||||
if level == 0 :
|
if level == 0 :
|
||||||
return # no data
|
return # no data
|
||||||
|
@ -434,11 +440,11 @@ class apds9960(object) :
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def colordataready( self ) :
|
def colordataready( self ) :
|
||||||
"""Return true if color data ready to read."""
|
'''Return true if color data ready to read.'''
|
||||||
return self.getstatus(STATUS_AVALID)
|
return self.getstatus(_STATUS_AVALID)
|
||||||
|
|
||||||
def colordata( self ) :
|
def colordata( self ) :
|
||||||
"""Return color data as (c,r,g,b)."""
|
'''Return color data as (c,r,g,b).'''
|
||||||
c = self.read16(_CDATAL)
|
c = self.read16(_CDATAL)
|
||||||
r = self.read16(_RDATAL)
|
r = self.read16(_RDATAL)
|
||||||
g = self.read16(_GDATAL)
|
g = self.read16(_GDATAL)
|
||||||
|
@ -461,23 +467,24 @@ class apds9960(object) :
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enabled( self ) :
|
def enabled( self ) :
|
||||||
return self.getenable(ENABLE_PON)
|
return self.getenable(_ENABLE_PON)
|
||||||
|
|
||||||
@enabled.setter
|
@enabled.setter
|
||||||
def enabled( self, aValue ) :
|
def enabled( self, aValue ) :
|
||||||
self.setenable(ENABLE_PON, aValue)
|
self.setenable(_ENABLE_PON, aValue)
|
||||||
|
|
||||||
def proxpulse( self, aLen, aPulses ) :
|
def proxpulse( self, aLen, aPulses ) :
|
||||||
setvalue(self._ppulse, PPULSE_PPULSE, min(64, max(aPulses, 1)) - 1)
|
setvalue(self._ppulse, _PPULSE_PPULSE, min(64, max(aPulses, 1)) - 1)
|
||||||
setvalue(self._ppulse, PPULSE_PPLEN, aLen)
|
setvalue(self._ppulse, _PPULSE_PPLEN, aLen)
|
||||||
self.write(PPULSE_PPULSE, self._ppulse)
|
self.write(_PPULSE_PPULSE, self._ppulse)
|
||||||
|
|
||||||
def gpulse( self, aLen, aPulses ) :
|
def gpulse( self, aLen, aPulses ) :
|
||||||
setvalue(self._gpulse, GPULSE_GPULSE, min(64, max(aPulses, 1)) - 1)
|
setvalue(self._gpulse, _GPULSE_GPULSE, min(64, max(aPulses, 1)) - 1)
|
||||||
setvalue(self._gpulse, GPULSE_GPLEN, aLen)
|
setvalue(self._gpulse, _GPULSE_GPLEN, aLen)
|
||||||
self.write(PPULSE_PPULSE, self._gpulse)
|
self.write(_GPULSE_GPULSE, self._gpulse)
|
||||||
|
|
||||||
def begin( self ) :
|
def begin( self ) :
|
||||||
|
'''Initialize the board for use.'''
|
||||||
id = self.read(_ID)
|
id = self.read(_ID)
|
||||||
if id != _ID_1 and id != _ID_2:
|
if id != _ID_1 and id != _ID_2:
|
||||||
raise Exception('Incorrect apds9960 ID {}.'.format(id))
|
raise Exception('Incorrect apds9960 ID {}.'.format(id))
|
||||||
|
@ -491,41 +498,41 @@ class apds9960(object) :
|
||||||
self.write(_POFFSET_UR, 0)
|
self.write(_POFFSET_UR, 0)
|
||||||
self.write(_POFFSET_DL, 0)
|
self.write(_POFFSET_DL, 0)
|
||||||
self.write(_CONFIG1, 0x60)
|
self.write(_CONFIG1, 0x60)
|
||||||
self.setcontrol(CONTROL_LDRIVE, _LEDDRIVE_100MA)
|
self.setcontrol(_CONTROL_LDRIVE, _LEDDRIVE_100MA)
|
||||||
self.setcontrol(CONTROL_AGAIN, _AGAIN_16X)
|
self.setcontrol(_CONTROL_AGAIN, _AGAIN_16X)
|
||||||
self.setcontrol(CONTROL_PGAIN, _PGAIN_8X)
|
self.setcontrol(_CONTROL_PGAIN, _PGAIN_8X)
|
||||||
|
|
||||||
self.proxpulse(_PPULSELEN_16US, 10)
|
self.proxpulse(_PPULSELEN_16US, 10)
|
||||||
self.gpulse(_GPULSE_32US, 9)
|
self.gpulse(_GPULSE_32US, 9)
|
||||||
|
|
||||||
self.proximityintthreshold(0x3200, 1)
|
self.proximityintthreshold(0x3200, 1)
|
||||||
self.enableproximityint(False) #Proximity Interrupt
|
self.enableproximityint(False) #Proximity Interrupt
|
||||||
# self.intlimits(0xFFFF, 0)
|
|
||||||
|
|
||||||
#100 makes the results a bit more erratic, No value boosts distance. It seems
|
#100 makes the results a bit more erratic, No value boosts distance. It seems
|
||||||
# the higher the boost the more stable the data is.
|
# the higher the boost the more stable the data is.
|
||||||
self.setconfig2(CONFIG2_LED_BOOST, _LEDBOOST_300)
|
self.setconfig2(_CONFIG2_LED_BOOST, _LEDBOOST_300)
|
||||||
|
|
||||||
#NOTE: This must be 1 if enter threshold is < exit or we will never get gesture input because we
|
#NOTE: This must be 1 if enter threshold is < exit or we will never get gesture input because we
|
||||||
# won't stay in the gesture state for more than 1 cycle.
|
# won't stay in the gesture state for more than 1 cycle.
|
||||||
self.setgconfig1(GCONFIG1_GFIFOTH, _GFIFO_1)
|
self.setgconfig1(_GCONFIG1_GFIFOTH, _GFIFO_1)
|
||||||
self.setgconfig2(GCONFIG2_GWTIME, _GWTIME_2_8MS)
|
self.setgconfig2(_GCONFIG2_GWTIME, _GWTIME_2_8MS)
|
||||||
self.setgconfig2(GCONFIG2_GGAIN, _GGAIN_4)
|
self.setgconfig2(_GCONFIG2_GGAIN, _GGAIN_4)
|
||||||
self.setgconfig3(GCONFIG3_GDIMS, _DIMENSIONS_ALL)
|
self.setgconfig3(_GCONFIG3_GDIMS, _DIMENSIONS_ALL)
|
||||||
#NOTE: An enter value lower than the exit value means we are constantly entering/exiting the state machine.
|
#NOTE: An enter value lower than the exit value means we are constantly entering/exiting the state machine.
|
||||||
# If we don't do this we will not get proximity and color input because those are not updated when in gesture state.
|
# If we don't do this we will not get proximity and color input because those are not updated when in gesture state.
|
||||||
self.gestureenterthreshold(5) #When proximity value is above this we enter the gesture state machine.
|
self.gestureenterthreshold(5) #When proximity value is above this we enter the gesture state machine.
|
||||||
self.gestureexitthreshold(255) #When all gesture values are below this we exit the gesture state machine.
|
self.gestureexitthreshold(255) #When all gesture values are below this we exit the gesture state machine.
|
||||||
self.gestureoffset(0, 0, 0, 0)
|
self.gestureoffset(0, 0, 0, 0)
|
||||||
|
|
||||||
self.setenable(ENABLE_PEN, True) #enable proximity
|
self.setenable(_ENABLE_PEN, True) #enable proximity
|
||||||
self.setenable(ENABLE_AEN, True) #enable color
|
self.setenable(_ENABLE_AEN, True) #enable color
|
||||||
self.enablegesture(True)
|
self.enablegesture(True)
|
||||||
|
|
||||||
self.enabled = True
|
self.enabled = True
|
||||||
sleep_us(50)
|
sleep_us(50)
|
||||||
|
|
||||||
def resetgestureparams( self ) :
|
def resetgestureparams( self ) :
|
||||||
|
#NOTE: This function could probably be merged with resetcounts().
|
||||||
self._index = 0
|
self._index = 0
|
||||||
self._total_gestures = 0
|
self._total_gestures = 0
|
||||||
self._ud_delta = 0
|
self._ud_delta = 0
|
||||||
|
@ -538,11 +545,14 @@ class apds9960(object) :
|
||||||
self._motion = _DIR_NONE
|
self._motion = _DIR_NONE
|
||||||
|
|
||||||
def readgesture( self ) :
|
def readgesture( self ) :
|
||||||
|
'''Read gesture data and process for up, down, left, right movement.
|
||||||
|
Returns _DIR_???.'''
|
||||||
|
#NOTE: This function currently doesn't seem to return very accurate results.
|
||||||
if self.gesturevalid :
|
if self.gesturevalid :
|
||||||
while True :
|
while True :
|
||||||
sleep_us(30) #Wait a bit to make sure fifo buffer is full.
|
sleep_us(30) #Wait a bit to make sure fifo buffer is full.
|
||||||
|
|
||||||
gstatus = self.getgstatus(GSTATUS_GVALID)
|
gstatus = self.getgstatus(_GSTATUS_GVALID)
|
||||||
if gstatus :
|
if gstatus :
|
||||||
fifo_level = self.read(_GFLVL)
|
fifo_level = self.read(_GFLVL)
|
||||||
if fifo_level > 0 :
|
if fifo_level > 0 :
|
||||||
|
|
Ładowanie…
Reference in New Issue