From 2139ea7f3146482406e73c59ca800e44a5a551f3 Mon Sep 17 00:00:00 2001 From: caternuson Date: Fri, 17 Apr 2020 19:24:08 -0700 Subject: [PATCH 1/7] initial working --- adafruit_as726x.py | 91 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index 94d9e67..a2d6618 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -92,8 +92,15 @@ _AS726X_NUM_CHANNELS = const(6) +_COLOR_REGS = (_AS7262_VIOLET, _AS7262_BLUE, _AS7262_GREEN, + _AS7262_YELLOW, _AS7262_ORANGE,_AS7262_RED) +_COLOR_REGS_CALIBRATED = (_AS7262_VIOLET_CALIBRATED, _AS7262_BLUE_CALIBRATED, + _AS7262_GREEN_CALIBRATED, _AS7262_YELLOW_CALIBRATED, + _AS7262_ORANGE_CALIBRATED, _AS7262_RED_CALIBRATED) + # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-public-methods + class Adafruit_AS726x: """AS726x spectral sensor. @@ -120,7 +127,7 @@ class Adafruit_AS726x: DRIVER_CURRENT_LIMITS = (12.5, 25, 50, 100) - def __init__(self, i2c_bus): + def __init__(self): self._driver_led = False self._indicator_led = False self._driver_led_current = Adafruit_AS726x.DRIVER_CURRENT_LIMITS.index(12.5) @@ -130,8 +137,6 @@ def __init__(self, i2c_bus): self._gain = Adafruit_AS726x.GAIN.index(1) self.buf2 = bytearray(2) - self.i2c_device = I2CDevice(i2c_bus, _AS726X_ADDRESS) - # reset device self._virtual_write(_AS726X_CONTROL_SETUP, 0x80) @@ -372,6 +377,18 @@ def raw_red(self): """Raw red (650nm) 16-bit value""" return self.read_channel(_AS7262_RED) + def _virtual_read(self, addr): + raise NotImplementedError("Must be implemented.") + + def _virtual_write(self, addr, value): + raise NotImplementedError("Must be implemented.") + +class Adafruit_AS726x_I2C(Adafruit_AS726x): + + def __init__(self, i2c_bus, address=_AS726X_ADDRESS): + self.i2c_device = I2CDevice(i2c_bus, address) + super().__init__() + def _read_u8(self, command): """read a single byte from a specified register""" buf = self.buf2 @@ -427,6 +444,74 @@ def _virtual_write(self, addr, value): # Send the data to complete the operation. self.__write_u8(_AS726X_SLAVE_WRITE_REG, value) +class Adafruit_AS726x_UART(Adafruit_AS726x): + def __init__(self, uart): + self._uart = uart + self._uart.baudrate = 115200 + super().__init__() + + def read_channel(self, channel): + """Read an individual sensor channel""" + return self._virtual_read(channel) + + def read_calibrated_value(self, channel): + """Read a calibrated sensor channel""" + return self._virtual_read(channel) + + def _uart_xfer(self, cmd): + self._uart.reset_input_buffer() + cmd += '\n' + self._uart.write(cmd.encode()) + time.sleep(0.1) + if self._uart.in_waiting: + resp = self._uart.read(self._uart.in_waiting) + return resp.rstrip(b' OK\n') + else: + return None + + def _virtual_read(self, addr): + if addr == _AS726X_HW_VERSION: + return 0x40 + elif addr == _AS726X_DEVICE_TEMP: + return int(self._uart_xfer('ATTEMP')) + elif addr == _AS726X_LED_CONTROL: + LED_IND = int(self._uart_xfer('ATLED0')) + LED_DRV = int(self._uart_xfer('ATLED1')) + return LED_IND << 3 | LED_DRV + elif addr == _AS726X_CONTROL_SETUP: + GAIN = int(self._uart_xfer('ATGAIN')) + BANK = int(self._uart_xfer('ATTCSMD')) + return GAIN << 4 | BANK << 2 | 1 << 1 + elif addr in _COLOR_REGS: + resp = self._uart_xfer('ATDATA') + resp = resp.decode().split(',') + return int(resp[_COLOR_REGS.index(addr)]) + elif addr in _COLOR_REGS_CALIBRATED: + resp = self._uart_xfer('ATCDATA') + resp = resp.decode().split(',') + return float(resp[_COLOR_REGS_CALIBRATED.index(addr)]) + + def _virtual_write(self, addr, value): + if addr == _AS726X_CONTROL_SETUP: + RST = (value >> 7) & 0x01 + GAIN = (value >> 4) & 0x03 + BANK = (value >> 2) & 0x03 + if RST: + self._uart.write(b'ATRST\n') + return + self._uart_xfer('ATGAIN={}'.format(GAIN)) + self._uart_xfer('ATTCSMD={}'.format(BANK)) + elif addr == _AS726X_LED_CONTROL: + ICL_DRV = (value >> 4) & 0x07 + LED_DRV = 100 if value & 0x08 else 0 + ICL_IND = (value >> 1) & 0x07 + LED_IND = 100 if value & 0x01 else 0 + self._uart_xfer('ATLED0={}'.format(LED_IND)) + self._uart_xfer('ATLED1={}'.format(LED_DRV)) + self._uart_xfer('ATLEDC={}'.format(ICL_DRV << 4 | ICL_IND)) + elif addr == _AS726X_INT_T: + value = int(value / 2.8) + self._uart_xfer('ATINTTIME={}'.format(value)) # pylint: enable=too-many-instance-attributes # pylint: enable=too-many-public-methods From ead4d7b6f2806ae1512d0c37cb0b38a445f2251c Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 09:46:08 -0700 Subject: [PATCH 2/7] clean up --- adafruit_as726x.py | 50 +++++++++++++++++++++-------------- examples/as726x_simpletest.py | 13 ++++++--- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index a2d6618..8ffc510 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -101,10 +101,9 @@ # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-public-methods -class Adafruit_AS726x: - """AS726x spectral sensor. +class AS726x: + """AS726x spectral sensor base class. - :param ~busio.I2C i2c_bus: The I2C bus connected to the sensor """ MODE_0 = 0b00 @@ -130,11 +129,11 @@ class Adafruit_AS726x: def __init__(self): self._driver_led = False self._indicator_led = False - self._driver_led_current = Adafruit_AS726x.DRIVER_CURRENT_LIMITS.index(12.5) - self._indicator_led_current = Adafruit_AS726x.INDICATOR_CURRENT_LIMITS.index(1) - self._conversion_mode = Adafruit_AS726x.MODE_2 + self._driver_led_current = AS726x.DRIVER_CURRENT_LIMITS.index(12.5) + self._indicator_led_current = AS726x.INDICATOR_CURRENT_LIMITS.index(1) + self._conversion_mode = AS726x.MODE_2 self._integration_time = 0 - self._gain = Adafruit_AS726x.GAIN.index(1) + self._gain = AS726x.GAIN.index(1) self.buf2 = bytearray(2) # reset device @@ -153,7 +152,7 @@ def __init__(self): ) self.integration_time = 140 - self.conversion_mode = Adafruit_AS726x.MODE_2 + self.conversion_mode = AS726x.MODE_2 self.gain = 64 @property @@ -198,14 +197,14 @@ def driver_led_current(self): @driver_led_current.setter def driver_led_current(self, val): - if val not in Adafruit_AS726x.DRIVER_CURRENT_LIMITS: + if val not in AS726x.DRIVER_CURRENT_LIMITS: raise ValueError("Must be 12.5, 25, 50 or 100") if self._driver_led_current == val: return self._driver_led_current = val state = self._virtual_read(_AS726X_LED_CONTROL) state &= ~(0x3 << 4) - state = state | (Adafruit_AS726x.DRIVER_CURRENT_LIMITS.index(val) << 4) + state = state | (AS726x.DRIVER_CURRENT_LIMITS.index(val) << 4) self._virtual_write(_AS726X_LED_CONTROL, state) @property @@ -220,14 +219,14 @@ def indicator_led_current(self): @indicator_led_current.setter def indicator_led_current(self, val): - if val not in Adafruit_AS726x.INDICATOR_CURRENT_LIMITS: + if val not in AS726x.INDICATOR_CURRENT_LIMITS: raise ValueError("Must be 1, 2, 4 or 8") if self._indicator_led_current == val: return self._indicator_led_current = val state = self._virtual_read(_AS726X_LED_CONTROL) state &= ~(0x3 << 1) - state = state | (Adafruit_AS726x.INDICATOR_CURRENT_LIMITS.index(val) << 4) + state = state | (AS726x.INDICATOR_CURRENT_LIMITS.index(val) << 4) self._virtual_write(_AS726X_LED_CONTROL, state) @property @@ -258,14 +257,14 @@ def gain(self): @gain.setter def gain(self, val): - if val not in Adafruit_AS726x.GAIN: + if val not in AS726x.GAIN: raise ValueError("Must be 1, 3.7, 16 or 64") if self._gain == val: return self._gain = val state = self._virtual_read(_AS726X_CONTROL_SETUP) state &= ~(0x3 << 4) - state |= Adafruit_AS726x.GAIN.index(val) << 4 + state |= AS726x.GAIN.index(val) << 4 self._virtual_write(_AS726X_CONTROL_SETUP, state) @property @@ -383,7 +382,11 @@ def _virtual_read(self, addr): def _virtual_write(self, addr, value): raise NotImplementedError("Must be implemented.") -class Adafruit_AS726x_I2C(Adafruit_AS726x): +class AS726x_I2C(AS726x): + """AS726x spectral sensor via I2C. + + :param ~busio.I2C i2c_bus: The I2C bus connected to the sensor + """ def __init__(self, i2c_bus, address=_AS726X_ADDRESS): self.i2c_device = I2CDevice(i2c_bus, address) @@ -444,7 +447,12 @@ def _virtual_write(self, addr, value): # Send the data to complete the operation. self.__write_u8(_AS726X_SLAVE_WRITE_REG, value) -class Adafruit_AS726x_UART(Adafruit_AS726x): +class AS726x_UART(AS726x): + """AS726x spectral sensor via UART. + + :param ~busio.UART uart: The UART connected to the sensor + """ + def __init__(self, uart): self._uart = uart self._uart.baudrate = 115200 @@ -471,6 +479,7 @@ def _uart_xfer(self, cmd): def _virtual_read(self, addr): if addr == _AS726X_HW_VERSION: + # just return what is expected return 0x40 elif addr == _AS726X_DEVICE_TEMP: return int(self._uart_xfer('ATTEMP')) @@ -493,12 +502,13 @@ def _virtual_read(self, addr): def _virtual_write(self, addr, value): if addr == _AS726X_CONTROL_SETUP: - RST = (value >> 7) & 0x01 - GAIN = (value >> 4) & 0x03 - BANK = (value >> 2) & 0x03 - if RST: + # check for reset + if (value >> 7) & 0x01: self._uart.write(b'ATRST\n') return + # otherwise proceed + GAIN = (value >> 4) & 0x03 + BANK = (value >> 2) & 0x03 self._uart_xfer('ATGAIN={}'.format(GAIN)) self._uart_xfer('ATTCSMD={}'.format(BANK)) elif addr == _AS726X_LED_CONTROL: diff --git a/examples/as726x_simpletest.py b/examples/as726x_simpletest.py index d91a813..3c6549d 100644 --- a/examples/as726x_simpletest.py +++ b/examples/as726x_simpletest.py @@ -3,7 +3,10 @@ import board import busio -from adafruit_as726x import Adafruit_AS726x +# for I2C use: +from adafruit_as726x import AS726x_I2C +# for UART use: +#from adafruit_as726x import AS726x_UART # maximum value for sensor reading max_val = 16000 @@ -16,9 +19,13 @@ def graph_map(x): return min(int(x * max_graph / max_val), max_graph) -# Initialize I2C bus and sensor. +# for I2C use: i2c = busio.I2C(board.SCL, board.SDA) -sensor = Adafruit_AS726x(i2c) +sensor = AS726x_I2C(i2c) + +# for UART use: +#uart = busio.UART(board.TX, board.RX) +#sensor = AS726x_UART(uart) sensor.conversion_mode = sensor.MODE_2 From db60c0ffb53a57a0b731f4efdceb0172b0ff9c04 Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 10:00:11 -0700 Subject: [PATCH 3/7] linted, i mean blacked, or..whatever --- adafruit_as726x.py | 61 ++++++++++++++++++++++------------- examples/as726x_simpletest.py | 7 ++-- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index 8ffc510..608d533 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -92,15 +92,27 @@ _AS726X_NUM_CHANNELS = const(6) -_COLOR_REGS = (_AS7262_VIOLET, _AS7262_BLUE, _AS7262_GREEN, - _AS7262_YELLOW, _AS7262_ORANGE,_AS7262_RED) -_COLOR_REGS_CALIBRATED = (_AS7262_VIOLET_CALIBRATED, _AS7262_BLUE_CALIBRATED, - _AS7262_GREEN_CALIBRATED, _AS7262_YELLOW_CALIBRATED, - _AS7262_ORANGE_CALIBRATED, _AS7262_RED_CALIBRATED) +_COLOR_REGS = ( + _AS7262_VIOLET, + _AS7262_BLUE, + _AS7262_GREEN, + _AS7262_YELLOW, + _AS7262_ORANGE, + _AS7262_RED, +) +_COLOR_REGS_CALIBRATED = ( + _AS7262_VIOLET_CALIBRATED, + _AS7262_BLUE_CALIBRATED, + _AS7262_GREEN_CALIBRATED, + _AS7262_YELLOW_CALIBRATED, + _AS7262_ORANGE_CALIBRATED, + _AS7262_RED_CALIBRATED, +) # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-public-methods + class AS726x: """AS726x spectral sensor base class. @@ -382,6 +394,7 @@ def _virtual_read(self, addr): def _virtual_write(self, addr, value): raise NotImplementedError("Must be implemented.") + class AS726x_I2C(AS726x): """AS726x spectral sensor via I2C. @@ -447,6 +460,7 @@ def _virtual_write(self, addr, value): # Send the data to complete the operation. self.__write_u8(_AS726X_SLAVE_WRITE_REG, value) + class AS726x_UART(AS726x): """AS726x spectral sensor via UART. @@ -468,12 +482,12 @@ def read_calibrated_value(self, channel): def _uart_xfer(self, cmd): self._uart.reset_input_buffer() - cmd += '\n' + cmd += "\n" self._uart.write(cmd.encode()) time.sleep(0.1) if self._uart.in_waiting: resp = self._uart.read(self._uart.in_waiting) - return resp.rstrip(b' OK\n') + return resp.rstrip(b" OK\n") else: return None @@ -482,46 +496,47 @@ def _virtual_read(self, addr): # just return what is expected return 0x40 elif addr == _AS726X_DEVICE_TEMP: - return int(self._uart_xfer('ATTEMP')) + return int(self._uart_xfer("ATTEMP")) elif addr == _AS726X_LED_CONTROL: - LED_IND = int(self._uart_xfer('ATLED0')) - LED_DRV = int(self._uart_xfer('ATLED1')) + LED_IND = int(self._uart_xfer("ATLED0")) + LED_DRV = int(self._uart_xfer("ATLED1")) return LED_IND << 3 | LED_DRV elif addr == _AS726X_CONTROL_SETUP: - GAIN = int(self._uart_xfer('ATGAIN')) - BANK = int(self._uart_xfer('ATTCSMD')) + GAIN = int(self._uart_xfer("ATGAIN")) + BANK = int(self._uart_xfer("ATTCSMD")) return GAIN << 4 | BANK << 2 | 1 << 1 elif addr in _COLOR_REGS: - resp = self._uart_xfer('ATDATA') - resp = resp.decode().split(',') + resp = self._uart_xfer("ATDATA") + resp = resp.decode().split(",") return int(resp[_COLOR_REGS.index(addr)]) elif addr in _COLOR_REGS_CALIBRATED: - resp = self._uart_xfer('ATCDATA') - resp = resp.decode().split(',') + resp = self._uart_xfer("ATCDATA") + resp = resp.decode().split(",") return float(resp[_COLOR_REGS_CALIBRATED.index(addr)]) def _virtual_write(self, addr, value): if addr == _AS726X_CONTROL_SETUP: # check for reset if (value >> 7) & 0x01: - self._uart.write(b'ATRST\n') + self._uart.write(b"ATRST\n") return # otherwise proceed GAIN = (value >> 4) & 0x03 BANK = (value >> 2) & 0x03 - self._uart_xfer('ATGAIN={}'.format(GAIN)) - self._uart_xfer('ATTCSMD={}'.format(BANK)) + self._uart_xfer("ATGAIN={}".format(GAIN)) + self._uart_xfer("ATTCSMD={}".format(BANK)) elif addr == _AS726X_LED_CONTROL: ICL_DRV = (value >> 4) & 0x07 LED_DRV = 100 if value & 0x08 else 0 ICL_IND = (value >> 1) & 0x07 LED_IND = 100 if value & 0x01 else 0 - self._uart_xfer('ATLED0={}'.format(LED_IND)) - self._uart_xfer('ATLED1={}'.format(LED_DRV)) - self._uart_xfer('ATLEDC={}'.format(ICL_DRV << 4 | ICL_IND)) + self._uart_xfer("ATLED0={}".format(LED_IND)) + self._uart_xfer("ATLED1={}".format(LED_DRV)) + self._uart_xfer("ATLEDC={}".format(ICL_DRV << 4 | ICL_IND)) elif addr == _AS726X_INT_T: value = int(value / 2.8) - self._uart_xfer('ATINTTIME={}'.format(value)) + self._uart_xfer("ATINTTIME={}".format(value)) + # pylint: enable=too-many-instance-attributes # pylint: enable=too-many-public-methods diff --git a/examples/as726x_simpletest.py b/examples/as726x_simpletest.py index 3c6549d..4ed5e95 100644 --- a/examples/as726x_simpletest.py +++ b/examples/as726x_simpletest.py @@ -5,8 +5,9 @@ # for I2C use: from adafruit_as726x import AS726x_I2C + # for UART use: -#from adafruit_as726x import AS726x_UART +# from adafruit_as726x import AS726x_UART # maximum value for sensor reading max_val = 16000 @@ -24,8 +25,8 @@ def graph_map(x): sensor = AS726x_I2C(i2c) # for UART use: -#uart = busio.UART(board.TX, board.RX) -#sensor = AS726x_UART(uart) +# uart = busio.UART(board.TX, board.RX) +# sensor = AS726x_UART(uart) sensor.conversion_mode = sensor.MODE_2 From c60848f1ceef464b4a19ee50b125c0c1c9c91e41 Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 10:06:55 -0700 Subject: [PATCH 4/7] this one is lint --- adafruit_as726x.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index 608d533..04297af 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -111,7 +111,8 @@ # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-public-methods - +# pylint: disable=invalid-name +# pylint: disable=no-else-return class AS726x: """AS726x spectral sensor base class. @@ -488,8 +489,7 @@ def _uart_xfer(self, cmd): if self._uart.in_waiting: resp = self._uart.read(self._uart.in_waiting) return resp.rstrip(b" OK\n") - else: - return None + return None def _virtual_read(self, addr): if addr == _AS726X_HW_VERSION: @@ -540,3 +540,5 @@ def _virtual_write(self, addr, value): # pylint: enable=too-many-instance-attributes # pylint: enable=too-many-public-methods +# pylint: enable=invalid-name +# pylint: enable=no-else-return \ No newline at end of file From fb443643f8c46af35db59453dec76a96695f6acf Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 10:09:49 -0700 Subject: [PATCH 5/7] and now black is unhappy again? --- adafruit_as726x.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index 04297af..e4f5f31 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -114,6 +114,7 @@ # pylint: disable=invalid-name # pylint: disable=no-else-return + class AS726x: """AS726x spectral sensor base class. @@ -541,4 +542,4 @@ def _virtual_write(self, addr, value): # pylint: enable=too-many-instance-attributes # pylint: enable=too-many-public-methods # pylint: enable=invalid-name -# pylint: enable=no-else-return \ No newline at end of file +# pylint: enable=no-else-return From 1aa1ccb0e9563b674e65b5953fdfc718e5ef9b3a Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 10:15:16 -0700 Subject: [PATCH 6/7] they do --- adafruit_as726x.py | 1 + 1 file changed, 1 insertion(+) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index e4f5f31..e998891 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -493,6 +493,7 @@ def _uart_xfer(self, cmd): return None def _virtual_read(self, addr): + # pylint: disable=inconsistent-return-statements if addr == _AS726X_HW_VERSION: # just return what is expected return 0x40 From c15610edb2b5750ba985fe2b67b43500f35c84a8 Mon Sep 17 00:00:00 2001 From: caternuson Date: Sat, 18 Apr 2020 10:19:08 -0700 Subject: [PATCH 7/7] no, really, don't --- adafruit_as726x.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_as726x.py b/adafruit_as726x.py index e998891..2a715c5 100644 --- a/adafruit_as726x.py +++ b/adafruit_as726x.py @@ -113,6 +113,7 @@ # pylint: disable=too-many-public-methods # pylint: disable=invalid-name # pylint: disable=no-else-return +# pylint: disable=inconsistent-return-statements class AS726x: @@ -493,7 +494,6 @@ def _uart_xfer(self, cmd): return None def _virtual_read(self, addr): - # pylint: disable=inconsistent-return-statements if addr == _AS726X_HW_VERSION: # just return what is expected return 0x40 @@ -544,3 +544,4 @@ def _virtual_write(self, addr, value): # pylint: enable=too-many-public-methods # pylint: enable=invalid-name # pylint: enable=no-else-return +# pylint: enable=inconsistent-return-statements