Skip to content

Add UART support #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 132 additions & 17 deletions adafruit_as726x.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,33 @@

_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.
# pylint: disable=invalid-name
# pylint: disable=no-else-return
# pylint: disable=inconsistent-return-statements


class AS726x:
"""AS726x spectral sensor base class.

:param ~busio.I2C i2c_bus: The I2C bus connected to the sensor
"""

MODE_0 = 0b00
Expand All @@ -120,18 +141,16 @@ 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)
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)

self.i2c_device = I2CDevice(i2c_bus, _AS726X_ADDRESS)

# reset device
self._virtual_write(_AS726X_CONTROL_SETUP, 0x80)

Expand All @@ -148,7 +167,7 @@ def __init__(self, i2c_bus):
)

self.integration_time = 140
self.conversion_mode = Adafruit_AS726x.MODE_2
self.conversion_mode = AS726x.MODE_2
self.gain = 64

@property
Expand Down Expand Up @@ -193,14 +212,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
Expand All @@ -215,14 +234,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
Expand Down Expand Up @@ -253,14 +272,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
Expand Down Expand Up @@ -372,6 +391,23 @@ 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 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)
super().__init__()

def _read_u8(self, command):
"""read a single byte from a specified register"""
buf = self.buf2
Expand Down Expand Up @@ -428,5 +464,84 @@ def _virtual_write(self, addr, value):
self.__write_u8(_AS726X_SLAVE_WRITE_REG, value)


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
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")
return None

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"))
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:
# 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:
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
# pylint: enable=invalid-name
# pylint: enable=no-else-return
# pylint: enable=inconsistent-return-statements
14 changes: 11 additions & 3 deletions examples/as726x_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
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
Expand All @@ -16,9 +20,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

Expand Down