-
-
Save Gadgetoid/a7227b56f7d34277b3616225c5884976 to your computer and use it in GitHub Desktop.
MicroPython library for the AS7343
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import struct | |
from micropython import const | |
# Bank 1 | |
AUXID = 0x58 # AUXID = 0b00001111 | |
REVID = 0x59 # REVID = 0b00000111 | |
ID = 0x5A # ID = 0b11111111 | |
CFG12 = 0x66 # SP_TH_CH = 0b00000111 | |
# Bank 0 | |
ENABLE = 0x80 # FDEN = 0b01000000 | |
# SMUXEN = 0b00010000 | |
# WEN = 0b00001000 | |
# SP_EN = 0b00000010 | |
# PON = 0b00000001 | |
ATIME = 0x81 # ATIME = 0b11111111 | |
# Integration Time Step Size | |
# 0 = 2.87us | |
# n 2.87us x (n + 1) | |
ASTEP = 0xD4 # STEP = 0xFFFF | |
# Spectral Measurement Wait Time | |
# 0 = 1 cycle = 2.78ms | |
# n = 2.78ms x (n + 1) | |
WTIME = 0x83 # WTIME = 0b11111111 | |
SP_TH = 0x84 # SP_TH_L = 0xFFFF0000 Spectral Low Threshold | |
# SP_TH_H = 0x0000FFFF Spectral High Threshold | |
STATUS = 0x93 # ASAT = 0b10000000 Spectral Saturation (if ASIEN set) | |
# AINT = 0b00001000 Spectral Channel Interrupt (if SP_IEN set) | |
# FINT = 0b00000100 FIFO Buffer Interrupt | |
# SINT = 0b00000001 System Interrupt | |
ASTATUS = 0x94 # ASAT = 0b10000000 Saturation Status | |
# AGAIN = 0b00000111 Gain Status | |
DATA = 0x95 # 36 bytes, fields 0 to 17 (2 bytes eac) | |
STATUS2 = 0x90 # AVALID = 0b01000000 Spectral Data Valid | |
# ASAT_DIG = 0b00010000 Digital Saturation | |
# ASAT_ANA = 0b00001000 Analog Saturation | |
# FDSAT_ANA= 0b00000010 Flicker Analog Saturation | |
# FDSAT_DIG= 0b00000001 Flicker Digital Saturation | |
STATUS3 = 0x91 # INT_SP_H = 0b00100000 Spectral Above High Threshold | |
# INT_SP_L = 0b00010000 Spectral Below Low Threshold | |
STATUS5 = 0xBB # SINT_FD = 0b00001000 Flicker Detect Interrupt (if SIEN_FD set) | |
# SINT_SMUX= 0b00000100 SMUS Operation Interrupt (SMUX exec finished) | |
STATUS4 = 0xBC # FIFO_OV = 0b10000000 FIFO Buffer Overflow | |
# OVTEMP = 0b00100000 Over Temperature | |
# FD_TRIG = 0b00010000 Flicker Detect Trigger Error | |
# SD_TRIG = 0b00000100 Spectral Trigger Error | |
# SAI_ACT = 0b00000010 Sleep After Interrupt Active | |
# INT_BUSY = 0b00000001 Initialization busy (1 for ~300us after power on) | |
CFG0 = 0xBF # LOW_POWER= 0b00100000 | |
# REG_BANK = 0b00010000 0 - Register 0x80 and above | |
# 1 - Register 0x20 to 0x7f | |
# WLONG = 0b00000100 Increase WTIME by factor of 16 | |
# Spectral Engines Gain Setting | |
# 0 = 0.5x, # 1 = 1x, 2 = 2x, 12 = 2048x | |
# GAINx = 1 << (n - 1) | |
CFG1 = 0xC6 | |
CFG3 = 0xC7 # SAI = 0b00100000 Sleep after interrupt | |
CFG6 = 0xF5 # SMUS_CMD = 0b00011000 0 - ROM_init | |
# 1 - Read_SMUX | |
# 2 - Write_SMUX | |
CFG8 = 0xC9 # FIFO_TH = 0b11000000 0b00, 0b01, 0b10, 0b11 | |
CFG9 = 0xCA # SIEN_FD = 0b01000000 System Interrupt Flicker Detection | |
# SIEN_SMUX= 0b00010000 System Interrupt SMUX Operation | |
CFG10 = 0x65 # FD_PERS = 0b00000111 Flicker Detect Persistence | |
# Number of results that must differ before status change | |
PERS = 0xCF # APERS = 0b00001111 | |
GPIO = 0x6B # GPIO_INV = 0b00001000 Invert GPIO output | |
# GPIO_IN_EN=0b00000100 Enable GPIO input | |
# GPIO_OUT = 0b00000010 GPIO Output | |
# GPIO_IN = 0b00000001 GPIO Input | |
CFG20 = 0xD6 # FD_FIFO_8b=0b10000000 Enable 8bit FIFO mode for Flicker Detect (FD_TIME < 256) | |
# auto_SMUX= 0b01100000 Auto channel read-out | |
LED = 0xCD # LED_ACT = 0b10000000 External LED (LDR) Control | |
# LED_DRIVE= 0b01111111 External LED drive strength (N - 4) >> 1 | |
# Flicker Detection AGC Gain Max | |
# Max = 2^N (0 = 0.5x) | |
AGC_GAIN_MAX = 0xD7 # ADC_FD_GAIN_MAX = 0b11110000 | |
AZ_CONFIG = 0xDE # AT_NTH_ITERATION = 0b11111111 Auto-zero Frequency | |
# 0 - Never (Not Recommended) | |
# n - Every n integration cycles | |
# 255 - only before first measurement cycle | |
FD_TIME_1 = 0xE0 # FD_TIME=0b11111111 Flicker Detection Integration Time (Do not change if FDEN = 1 & PON = 1) | |
FD_TIME_2 = 0xE2 # FD_GAIN=0b11111000 Flicker Detection Gain (0 = 0.5x, 1 = 1x, 2 = 2x, 12 = 2048x) | |
# FD_TIME=0b00000111 Flicker Detection Time (Do not change if FDEN = 1 & PON = 1) | |
FD_CFG0 = 0xDF # FIFO_WRITE_FD = 0b10000000 Write flicker raw data to FIFO (1 byte per sample) | |
FD_STATUS = 0xE3 # FD_VALID=0b00100000 | |
# FD_SAT = 0b00010000 | |
# FD_120HZ_VALID = 0b00001000 | |
# FD_100HZ_VALID = 0b00000100 | |
# FD_120HZ = 0b00000010 | |
# FD_100HZ = 0b00000001 | |
INTERNAB = 0xF9 # ASIEN = 0b10000000 Saturation Interrupt Enable | |
# SP_IEN = 0b00001000 Spectral Interrupt Enable | |
# FIEN = 0b00000100 FIFO Buffer Interrupt Enable | |
# SIEN = 0b00000001 System Interrupt Enable | |
CONTROL = 0xFA # SW_RESET = 0b00001000 Software Reset | |
# SP_MAN_AZ= 0b00000100 Spectral Manual Auto-zero | |
# FIFO_CLR = 0b00000010 FIFO Buffer Clear | |
# CLEAR_SAI_ACT = 0b00000001 Clear sleep-after-interrupt | |
FIFO_MAP = 0xFC # CH5 = 0b01000000 | |
# CH4 = 0b00100000 | |
# CH3 = 0b00010000 | |
# CH2 = 0b00001000 | |
# CH1 = 0b00000100 | |
# CH0 = 0b00000010 | |
# ASTATUS = 0b00000001 | |
FIFO_LVL = 0xFD | |
FDATA = 0xFE # 0xFFFF | |
HARDWARE_ID = const(0b10000001) | |
CFG0_LOW_POWER = const(0b00100000) | |
CFG0_BANK = const(0b00010000) | |
CFG0_WLONG = const(0b00000100) | |
CFG20_6_CH = const(0b00000000) | |
CFG20_12_CH = const(0b01000000) | |
CFG20_18_CH = const(0b01100000) | |
ENABLE_FDEN = const(0b01000000) | |
ENABLE_SMUXEN = const(0b00010000) | |
ENABLE_WEN = const(0b00001000) | |
ENABLE_SP_EN = const(0b00000010) | |
ENABLE_PON = const(0b00000001) | |
FD_CFG0_FIFO_WRITE = const(0b10000000) | |
FD_VALID = const(0b00100000) | |
FD_SAT = const(0b00010000) | |
FD_120HZ_VALID = const(0b00001000) | |
FD_100HZ_VALID = const(0b00000100) | |
FD_120HZ = const(0b00000010) | |
FD_100HZ = const(0b00000001) | |
INTERNAB_ASIEN = const(0b10000000) | |
INTERNAB_SP_IEN = const(0b00001000) | |
INTERNAB_FIEN = const(0b00000100) | |
INTERNAB_SIEN = const(0b00000001) | |
CONTROL_SW_RESET = const(0b00001000) | |
CONTROL_SP_MAN_AZ = const(0b00000100) | |
CONTROL_FIFO_CLR = const(0b00000010) | |
CONTROL_CLEAR_SAI_ACT = const(0b00000001) | |
FIFO_MAP_CH5 = const(0b01000000) | |
FIFO_MAP_CH4 = const(0b00100000) | |
FIFO_MAP_CH3 = const(0b00010000) | |
FIFO_MAP_CH2 = const(0b00001000) | |
FIFO_MAP_CH1 = const(0b00000100) | |
FIFO_MAP_CH0 = const(0b00000010) | |
FIFO_MAP_ASTATUS = const(0b00000001) | |
AZ_NEVER = const(0) | |
AZ_BEFORE_FIRST_CYCLE = const(255) | |
class BreakoutAS7343: | |
def __init__(self, i2c): | |
self.address = 0x39 | |
self.i2c = i2c | |
self.num_channels = 18 | |
self.active = False | |
# Soft reset | |
self.w_uint8(CONTROL, CONTROL_SW_RESET) | |
time.sleep(0.5) | |
# Bank 0 | |
self.w_uint8(CFG0, 0) | |
# Set default AGAIN | |
self.w_uint8(CFG1, 9) | |
# Set default sensor settings | |
self.set_gain(256) | |
self.set_measurement_time(33) # Roughly 30fps at 16ms/measurement | |
self.set_integration_time(27800) | |
self.set_channels(18) | |
# Auto zero on measurement start | |
self.w_uint8(AZ_CONFIG, AZ_BEFORE_FIRST_CYCLE) | |
# Set the FIFO map | |
self.w_uint8(0xFC, FIFO_MAP_CH5 | FIFO_MAP_CH4 | FIFO_MAP_CH3 | FIFO_MAP_CH2 | FIFO_MAP_CH1 | FIFO_MAP_CH0 | FIFO_MAP_ASTATUS) | |
def set_gain(self, gain): | |
if gain == 0.5: | |
bitlength = 0 | |
else: | |
igain = int(gain) | |
bitlength = 0 | |
while igain > 0: | |
bitlength += 1 | |
igain >>= 1 | |
self.w_uint8(CFG1, bitlength) | |
def set_measurement_time(self, measurement_time_ms): | |
resolution = 2.78 | |
self.w_uint8(WTIME, int((measurement_time_ms - resolution) / resolution)) | |
def set_integration_time(self, integration_time_us, repeat=1): | |
resolution = 2.78 | |
max_astep = (65534 + 1) * resolution | |
if integration_time_us > max_astep: | |
raise ValueError("Integration time out of range!") | |
self.w_uint8(ATIME, repeat - 1) | |
self.w_uint16(ASTEP, int((integration_time_us - resolution) / resolution) & 0xfffe) | |
def set_illumination_current(self, current): | |
current = int((current - 4) / 2.0) | |
temp = self.r_uint8(LED) & 0b10000000 # Preserve on/off state | |
temp |= (current & 0b01111111) | |
self.w_uint8(LED, temp) | |
def set_illumination_led(self, state): | |
temp = self.r_uint8(LED) & ~0b10000000 # Preserve current | |
if state: | |
temp |= 0b10000000 | |
self.w_uint8(LED, temp) | |
def start_measurement(self): | |
if self.active: | |
return | |
self.active = True | |
# Enable things | |
self.w_uint8(ENABLE, ENABLE_WEN | ENABLE_SMUXEN | ENABLE_SP_EN | ENABLE_PON) | |
def stop_measurement(self): | |
self.w_uint8(ENABLE, ENABLE_PON) | |
self.w_uint8(CONTROL, CONTROL_FIFO_CLR) | |
def force_autorange(self): | |
self.w_uint8(CONTROL, CONTROL_SP_MAN_AZ) | |
time.sleep(0.1) | |
def set_channels(self, c): | |
self.num_channels = c | |
temp = self.r_uint8(0xD6) | |
def read_fifo(self): | |
expected_results = (self.num_channels // 6) * 7 | |
results = [] | |
while self.r_uint8(0xFD) < expected_results: | |
time.sleep(0.01) | |
while self.r_uint8(0xFD) > 0 and expected_results > 0: | |
results.append(self.r_uint16(0xFE)) | |
expected_results -= 1 | |
return results | |
def read(self): | |
self.start_measurement() | |
result = self.read_fifo() | |
return ( | |
result[0], # FZ | |
result[1], # FY | |
result[2], # FZL | |
result[3], # NIR | |
result[7], # F2 | |
result[8], # F3 | |
result[9], # F4 | |
result[10], # F6 | |
result[14], # F1 | |
result[15], # F5 | |
result[16], # F7 | |
result[17], # F8 | |
) | |
def r_uint8(self, reg): | |
self.i2c.writeto(self.address, bytes([reg])) | |
return struct.unpack("<B", self.i2c.readfrom(self.address, 1))[0] | |
def w_uint8(self, reg, value): | |
self.i2c.writeto(self.address, bytes([reg, value])) | |
def r_uint16(self, reg): | |
self.i2c.writeto(self.address, bytes([reg])) | |
return struct.unpack("<H", self.i2c.readfrom(self.address, 2))[0] | |
def w_uint16(self, reg, value): | |
self.i2c.writeto(self.address, struct.pack("<BH", reg, value)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment