Merge pull request #14 from caternuson/uart

Add UART support
This commit is contained in:
Kattni 2020-05-04 12:20:18 -04:00 committed by GitHub
commit 8df00d8992
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 143 additions and 20 deletions

View file

@ -92,12 +92,33 @@ _AS7262_RED_CALIBRATED = const(0x28)
_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
@ -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)
@ -148,7 +167,7 @@ class Adafruit_AS726x:
)
self.integration_time = 140
self.conversion_mode = Adafruit_AS726x.MODE_2
self.conversion_mode = AS726x.MODE_2
self.gain = 64
@property
@ -193,14 +212,14 @@ class Adafruit_AS726x:
@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
@ -215,14 +234,14 @@ class Adafruit_AS726x:
@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
@ -253,14 +272,14 @@ class Adafruit_AS726x:
@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
@ -372,6 +391,23 @@ class Adafruit_AS726x:
"""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
@ -428,5 +464,84 @@ class Adafruit_AS726x:
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

View file

@ -3,7 +3,11 @@ import time
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 +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