diff --git a/.pylintrc b/.pylintrc index 946d694..81d8170 100644 --- a/.pylintrc +++ b/.pylintrc @@ -119,7 +119,8 @@ spelling-store-unknown-words=no [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO +# notes=FIXME,XXX,TODO +notes=FIXME,XXX [TYPECHECK] diff --git a/.travis.yml b/.travis.yml index 5153056..2db5b53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ deploy: file_glob: true file: bundles/* skip_cleanup: true + overwrite: true on: tags: true diff --git a/README.rst b/README.rst index de52776..1cc2e6e 100644 --- a/README.rst +++ b/README.rst @@ -44,18 +44,19 @@ Of course, you must import i2c bus device, board pins, and the library: from board import SCL, SDA, A1 - import adafruit_apds9960 as apds9960 + from adafruit_apds9960.apds9960 import APDS9960 import busio + import digitalio To set-up the device to gather data, initialize the I2CDevice using SCL -and SDA pins. Then initialize the libary. Optionally provide an interrupt +and SDA pins. Then initialize the library. Optionally provide an interrupt pin for proximity detection. .. code:: python - int_pin = digitalio.DigitalInOutput(A1) + int_pin = digitalio.DigitalInOut(A1) i2c = busio.I2C(SCL, SDA) - apds = apds9960.APDS9960(i2c, interrupt_pin=int_pin) + apds = APDS9960(i2c, interrupt_pin=int_pin) Gestures -------- @@ -65,14 +66,14 @@ To get a gesture, see if a gesture is available first, then get the gesture Code .. code:: python gesture = apds.gesture() - if gesture == apds.UP: + if gesture == 1: print("up") - if gesture == apds.DOWN: + if gesture == 2: print("down") - if gesture == apds.RIGHT: - print("right") - if gesture == apds.LEFT: + if gesture == 3: print("left") + if gesture == 4: + print("right") Color Measurement ----------------- @@ -105,11 +106,12 @@ To check for a object in proximity, see if a gesture is available first, then ge # enable the proximity interrupt apds.enable_proximity_interrupt = True - while not interrupt_pin.value: - print(apds.proximity()) + while True: + if not interrupt_pin.value: + print(apds.proximity()) - # clear the interrupt - apds.clear_interrupt() + # clear the interrupt + apds.clear_interrupt() API Reference diff --git a/adafruit_apds9960/apds9960.py b/adafruit_apds9960/apds9960.py index 9bca8c6..33f9864 100644 --- a/adafruit_apds9960/apds9960.py +++ b/adafruit_apds9960/apds9960.py @@ -20,10 +20,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ -`adafruit_APDS9960` +`APDS9960` ==================================================== -TODO(description) +Driver class for the APDS9960 board. Supports gesture, proximity, and color +detection. * Author(s): Michael McWethy """ @@ -93,7 +94,7 @@ APDS9960_GFIFO_U = const(0xFC) #pylint: enable-msg=bad-whitespace - +#pylint: disable-msg=too-many-instance-attributes class APDS9960: """ APDS9900 provide basic driver services for the ASDS9960 breakout board @@ -145,7 +146,7 @@ class APDS9960: self.gesture_fifo_threshold = 0x01 # fifo 4 self.gesture_gain = 0x02 # gain 4 self.gesture_proximity_threshold = 50 - self.reset_counts() + self._reset_counts() # gesture pulse length=0x2 pulse count=0x3 self.write8(APDS9960_GPULSE, (0x2 << 6) | 0x3) @@ -154,21 +155,25 @@ class APDS9960: ## BOARD @property def enable(self): + """Set or get board enable. True to enable, False to disable""" return self._enable @enable.setter def enable(self, enable_flag): self._enable = enable_flag - def reset_counts(self): - self._up_count = 0 - self._down_count = 0 - self._right_count = 0 - self._left_count = 0 + def _reset_counts(self): + """Gesture detection internal counts""" + self._saw_down_start = 0 + self._saw_up_start = 0 + self._saw_left_start = 0 + self._saw_right_start = 0 ## GESTURE DETECTION @property def enable_gesture(self): + """Set ot get gesture detection enable flag + Note that when disabled, the gesture mode is turned off""" return self._gesture_mode, self._gesture_enable @enable_gesture.setter @@ -177,10 +182,11 @@ class APDS9960: self._gesture_mode = False self._gesture_enable = enable_flag - def gesture(self): + def gesture(self): #pylint: disable-msg=too-many-branches """Return a gesture code if detected. =0 if no gesture =1 if an UP, =2 if a DOWN, =3 if an LEFT, =4 if a RIGHT """ + # buffer to read of contents of device FIFO buffer buffer = bytearray(129) buffer[0] = APDS9960_GFIFO_U if not self._gesture_valid: @@ -202,47 +208,51 @@ class APDS9960: i2c.readinto(buffer, start=1) upp, down, left, right = buffer[1:5] - # upp, down, left, right = self._gesture_fifo_read - # if upp or down or left or right: - # print(upp, down, left, right) - if abs(upp - down) > 13: up_down_diff = upp - down - # print("up down diff {}".format(up_down_diff)) if abs(left - right) > 13: left_right_diff = left - right - # print("left right diff {}".format(left_right_diff)) if up_down_diff != 0: if up_down_diff < 0: - if self._down_count > 0: - gesture_received = 0x01 + # either leading edge of down movement + # or trailing edge of up movement + if self._saw_up_start: + gesture_received = 0x01 # up else: - self._up_count += 1 + self._saw_down_start += 1 elif up_down_diff > 0: - if self._up_count > 0: - gesture_received = 0x02 + # either leading edge of up movement + # or trailing edge of down movement + if self._saw_down_start: + gesture_received = 0x02 # down else: - self._down_count += 1 + self._saw_up_start += 1 if left_right_diff != 0: if left_right_diff < 0: - if self._right_count > 0: - gesture_received = 0x03 + # either leading edge of right movement + # trailing edge of left movement + if self._saw_left_start: + gesture_received = 0x03 # left else: - self._left_count += 1 + self._saw_right_start += 1 elif left_right_diff > 0: - if self._left_count > 0: - gesture_received = 0x04 + # either leading edge of left movement + # trailing edge of right movement + if self._saw_right_start: + gesture_received = 0x04 #right else: - self._right_count += 1 + self._saw_left_start += 1 + # saw a leading or trailing edge; start timer if up_down_diff != 0 or left_right_diff != 0: time_mark = time.monotonic() + # finished when a gesture is detected or ran out of time (300ms) if gesture_received or time.monotonic() - time_mark > 0.300: - self.reset_counts() + self._reset_counts() break return gesture_received @@ -250,22 +260,25 @@ class APDS9960: @property def gesture_dimensions(self): + """Set of get gesture dimension value: range 0-3""" return self.read8(APDS9960_GCONF3) @gesture_dimensions.setter def gesture_dimensions(self, dims): - self.write8(APDS9960_GCONF3, dims & 0xff) + self.write8(APDS9960_GCONF3, dims & 0x03) @property def gesture_fifo_threshold(self): + """Set or get gesture fifo threshold value: range 0-3""" return self._gesture_fifo_threshold @gesture_fifo_threshold.setter def gesture_fifo_threshold(self, thresh): - self._gesture_fifo_threshold = thresh & 0x3 + self._gesture_fifo_threshold = thresh & 0x03 @property def gesture_gain(self): + """Set or get gesture gain value: range 0-3""" return self._gesture_gain @gesture_gain.setter @@ -276,7 +289,8 @@ class APDS9960: ## COLOR DETECTION @property def enable_color(self): - """returns True when color is enabled, else False""" + """Set of get color detection enable flag. + True when color detection is enabled, else False""" return self._color_enable @enable_color.setter @@ -285,15 +299,16 @@ class APDS9960: @property def color_data_ready(self): + """Get color data ready flag. zero if not ready, 1 is ready""" return self.read8(APDS9960_STATUS) & 0x01 @property def color_data(self): """Returns tuple containing r, g, b, c values""" - return self.read16(APDS9960_CDATAL + 2), \ - self.read16(APDS9960_CDATAL + 4), \ - self.read16(APDS9960_CDATAL + 6), \ - self.read16(APDS9960_CDATAL) + return self._color_data16(APDS9960_CDATAL + 2), \ + self._color_data16(APDS9960_CDATAL + 4), \ + self._color_data16(APDS9960_CDATAL + 6), \ + self._color_data16(APDS9960_CDATAL) ### PROXIMITY @property def enable_proximity(self): @@ -307,7 +322,7 @@ class APDS9960: @property def proximity_interrupt_threshold(self): """Returns a tuple containing low and high threshold - followed by the proximity interrupt persistance. + followed by the proximity interrupt persistance. Set the proximity interrupt threshold values using a tuple of zero to three values: low threshold, high threshold, persistance """ return self.read8(APDS9960_PILT), \ @@ -326,6 +341,8 @@ class APDS9960: @property def enable_proximity_interrupt(self): + """Set or get proximity interrupt enable flag. True if enabled, + False to disable""" return self._proximity_enable_interrupt @enable_proximity_interrupt.setter @@ -334,6 +351,7 @@ class APDS9960: @property def gesture_proximity_threshold(self): + """Set or get proximity threshold value: range 0-255""" return self.read8(APDS9960_GPENTH) @gesture_proximity_threshold.setter @@ -341,13 +359,16 @@ class APDS9960: self.write8(APDS9960_GPENTH, thresh & 0xff) def proximity(self): + """Set or get proximity value: range 0-255""" return self.read8(APDS9960_PDATA) def clear_interrupt(self): + """Clear all interrupts""" self.writecmdonly(APDS9960_AICLEAR) @property def integration_time(self): + """Set or get the proximity integration time: range 0-255""" return self.read8(APDS9960_ATIME) @integration_time.setter @@ -356,6 +377,7 @@ class APDS9960: # method for reading and writing to I2C def write8(self, command, abyte): + """Write a command and 1 byte of data to the I2C device""" buf = bytearray(2) buf[0] = command buf[1] = abyte @@ -364,12 +386,14 @@ class APDS9960: i2c.write(buf) def writecmdonly(self, command): + """Writes a command and 0 bytes of data to the I2C device""" buf = bytearray(1) buf[0] = command with self.i2c_device as i2c: i2c.write(buf) def read8(self, command): + """Sends a command and reads 1 byte of data from the I2C device""" buf = bytearray(1) buf[0] = command with self.i2c_device as i2c: @@ -377,7 +401,9 @@ class APDS9960: i2c.readinto(buf) return buf[0] - def read16(self, command): + def _color_data16(self, command): + """Sends a command and reads 2 byte of data from the I2C device + The returned data is low byte first followed by high byte""" buf = bytearray(2) buf[0] = command with self.i2c_device as i2c: diff --git a/adafruit_apds9960/colorutility.py b/adafruit_apds9960/colorutility.py index fea45db..79b1472 100644 --- a/adafruit_apds9960/colorutility.py +++ b/adafruit_apds9960/colorutility.py @@ -1,4 +1,33 @@ -"""Helper functions for color calculations""" +# The MIT License (MIT) +# +# Copyright (c) 2017 Michael McWethy for Adafruit Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`colorutility` +==================================================== + +Helper functions for color calculations + +* Author(s): Michael McWethy +""" + def calculate_color_temperature(r, g, b): """Converts the raw R/G/B values to color temperature in degrees Kelvin""" diff --git a/api.rst b/api.rst index 9768c38..57c6e0e 100644 --- a/api.rst +++ b/api.rst @@ -1,5 +1,10 @@ -.. If you created a package, create one automodule per module in the package. - -.. automodule:: adafruit_apds9960 +`APDS9960` - Driver for Gesture/Proximity/Color detection board +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +.. automodule:: adafruit_apds9960.apds9960 :members: + +`Color Utility Functions` - Utility function related to Color detection ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + .. automodule:: adafruit_apds9960.colorutility + :members: diff --git a/examples/color.py b/examples/color.py index 8f71e9f..fba761d 100644 --- a/examples/color.py +++ b/examples/color.py @@ -28,4 +28,4 @@ while True: print("color temp {}".format(colorutility.calculate_color_temperature(r, b, g))) print("light lux {}".format(colorutility.calculate_lux(r, b, g))) - time.sleep(0.5) \ No newline at end of file + time.sleep(0.5) diff --git a/examples/gesture.py b/examples/gesture.py index 3cc239c..fcac7ad 100644 --- a/examples/gesture.py +++ b/examples/gesture.py @@ -1,8 +1,8 @@ -import board +from board import SCL, SDA import busio from adafruit_apds9960.apds9960 import APDS9960 -i2c = busio.I2C(board.SCL, board.SDA) +i2c = busio.I2C(SCL, SDA) apds = APDS9960(i2c) apds.enable_proximity = True @@ -18,4 +18,4 @@ while True: elif gesture == 0x03: print("left") elif gesture == 0x04: - print("right") \ No newline at end of file + print("right") diff --git a/examples/proximity.py b/examples/proximity.py index 53fc2a2..265e59d 100644 --- a/examples/proximity.py +++ b/examples/proximity.py @@ -8,7 +8,7 @@ int_pin = digitalio.DigitalInOut(board.A2) apds = APDS9960(i2c, interrupt_pin=int_pin) apds.enable_proximity = True -apds.proximity_interrupt_threshold = (10, 175) +apds.proximity_interrupt_threshold = (0, 175) apds.enable_proximity_interrupt = True while True: @@ -19,4 +19,4 @@ while True: print(prox_value) # clear the interrupt - apds.clear_interrupt() \ No newline at end of file + apds.clear_interrupt() diff --git a/requirements.txt b/requirements.txt index 4deed95..7053ecf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -circuitpython-travis-build-tools - +adafruit-circuitpython-bus-device +adafruit-circuitpython-register