440 lines
12 KiB
Python
440 lines
12 KiB
Python
import time
|
|
import struct
|
|
|
|
I2C_ADDR = 0x49
|
|
|
|
STATUS_REG = 0x00
|
|
WRITE_REG = 0x01
|
|
READ_REG = 0x02
|
|
TX_VALID = 0x02
|
|
RX_VALID = 0x01
|
|
|
|
#Register addresses
|
|
HW_VERSION_HIGH = 0x00
|
|
HW_VERSION_LOW = 0x01
|
|
FW_VERSION_HIGH = 0x02
|
|
FW_VERSION_LOW = 0x03
|
|
|
|
CONFIG = 0x04
|
|
INTEGRATION_TIME = 0x05
|
|
DEVICE_TEMP = 0x06
|
|
LED_CONFIG = 0x07
|
|
|
|
#Raw channel registers
|
|
R_G_A = 0x08
|
|
S_H_B = 0x0a
|
|
T_I_C = 0x0c
|
|
U_J_D = 0x0e
|
|
V_K_E = 0x10
|
|
W_L_F = 0x12
|
|
|
|
#Calibrated channel registers
|
|
R_G_A_CAL = 0x14
|
|
S_H_B_CAL = 0x18
|
|
T_I_C_CAL = 0x1c
|
|
U_J_D_CAL = 0x20
|
|
V_K_E_CAL = 0x24
|
|
W_L_F_CAL = 0x28
|
|
|
|
DEV_SELECT_CONTROL = 0x4F
|
|
|
|
COEF_DATA_0 = 0x50
|
|
COEF_DATA_1 = 0x51
|
|
COEF_DATA_2 = 0x52
|
|
COEF_DATA_3 = 0x52
|
|
COEF_DATA_READ = 0x54
|
|
COEF_DATA_WRITE = 0x55
|
|
|
|
#Settings
|
|
POLLING_DELAY = 0.01
|
|
NIR = 0x00
|
|
VISIBLE = 0x01
|
|
UV = 0x02
|
|
|
|
LED_WHITE = 0x00
|
|
LED_IR = 0x01
|
|
LED_UV = 0x02
|
|
LED_CURRENT_LIMIT_12_5MA = 0b00
|
|
LED_CURRENT_LIMIT_25MA = 0b01
|
|
LED_CURRENT_LIMIT_50MA = 0b10
|
|
LED_CURRENT_LIMIT_100MA = 0b11
|
|
|
|
INDICATOR_CURRENT_LIMIT_1MA = 0b00
|
|
INDICATOR_CURRENT_LIMIT_2MA = 0b01
|
|
INDICATOR_CURRENT_LIMIT_4MA = 0b10
|
|
INDICATOR_CURRENT_LIMIT_8MA = 0b11
|
|
|
|
GAIN_1X = 0b00
|
|
GAIN_37X = 0b01
|
|
GAIN_16X = 0b10
|
|
GAIN_64X = 0b11
|
|
|
|
MEASUREMENT_MODE_4CHAN = 0b00
|
|
MEASUREMENT_MODE_4CHAN_2 = 0b01
|
|
MEASUREMENT_MODE_6CHAN_CONTINUOUS = 0b10
|
|
MEASUREMENT_MODE_6CHAN_ONE_SHOT = 0b11
|
|
|
|
|
|
class AS7265X():
|
|
def __init__(self, i2c_bus):
|
|
self._bus = i2c_bus
|
|
|
|
def begin(self):
|
|
if not self.isConnected():
|
|
return False
|
|
|
|
value = self.virtualReadRegister(DEV_SELECT_CONTROL)
|
|
if (value & 0b00110000) == 0:
|
|
return False
|
|
|
|
self.setBulbCurrent(LED_CURRENT_LIMIT_12_5MA, LED_WHITE)
|
|
self.setBulbCurrent(LED_CURRENT_LIMIT_12_5MA, LED_IR)
|
|
self.setBulbCurrent(LED_CURRENT_LIMIT_12_5MA, LED_UV)
|
|
|
|
self.disableBulb(LED_WHITE)
|
|
self.disableBulb(LED_IR)
|
|
self.disableBulb(LED_UV)
|
|
|
|
self.setIndicatorCurrent(INDICATOR_CURRENT_LIMIT_8MA)
|
|
self.enableIndicator()
|
|
|
|
self.setIntegrationCycles(49) #50 * 2.8ms = 140ms.
|
|
self.setGain(GAIN_64X)
|
|
self.setMeasurementMode(MEASUREMENT_MODE_6CHAN_ONE_SHOT)
|
|
self.enableInterrupt()
|
|
return True
|
|
|
|
def getDeviceType(self):
|
|
return self.virtualReadRegister(HW_VERSION_HIGH)
|
|
|
|
def getHardwareVersion(self):
|
|
return self.virtualReadRegister(HW_VERSION_LOW)
|
|
|
|
def getMajorFirmwareVersion(self):
|
|
self.virtualWriteRegister(FW_VERSION_HIGH, 0x01)
|
|
self.virtualWriteRegister(FW_VERSION_LOW, 0x01)
|
|
|
|
return self.virtualReadRegister(FW_VERSION_LOW)
|
|
|
|
def getPatchFirmwareVersion(self):
|
|
self.virtualWriteRegister(FW_VERSION_HIGH, 0x02)
|
|
self.virtualWriteRegister(FW_VERSION_LOW, 0x02)
|
|
|
|
return self.virtualReadRegister(FW_VERSION_LOW)
|
|
|
|
def getBuildFirmwareVersion(self):
|
|
self.virtualWriteRegister(FW_VERSION_HIGH, 0x03)
|
|
self.virtualWriteRegister(FW_VERSION_LOW, 0x03)
|
|
|
|
return self.virtualReadRegister(FW_VERSION_LOW)
|
|
|
|
def isConnected(self):
|
|
try:
|
|
self._bus.read_byte_data(I2C_ADDR, STATUS_REG)
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
def takeMeasurements(self):
|
|
self.setMeasurementMode(MEASUREMENT_MODE_6CHAN_ONE_SHOT)
|
|
|
|
while not self.dataAvailable():
|
|
time.sleep(POLLING_DELAY)
|
|
|
|
def takeMeasurementsWithBulb(self):
|
|
self.enableBulb(LED_WHITE)
|
|
self.enableBulb(LED_IR)
|
|
self.enableBulb(LED_UV)
|
|
|
|
self.takeMeasurements()
|
|
|
|
self.disableBulb(LED_WHITE)
|
|
self.disableBulb(LED_IR)
|
|
self.disableBulb(LED_UV)
|
|
|
|
#Get the various color readings
|
|
def getG(self):
|
|
return self.getChannel(R_G_A, VISIBLE)
|
|
|
|
def getH(self):
|
|
return self.getChannel(S_H_B, VISIBLE)
|
|
|
|
def getI(self):
|
|
return self.getChannel(T_I_C, VISIBLE)
|
|
|
|
def getJ(self):
|
|
return self.getChannel(U_J_D, VISIBLE)
|
|
|
|
def getK(self):
|
|
return self.getChannel(V_K_E, VISIBLE)
|
|
|
|
def getL(self):
|
|
return self.getChannel(W_L_F, VISIBLE)
|
|
|
|
#Get the various NIR readings
|
|
def getR(self):
|
|
return self.getChannel(R_G_A, NIR)
|
|
|
|
def getS(self):
|
|
return self.getChannel(S_H_B, NIR)
|
|
|
|
def getT(self):
|
|
return self.getChannel(T_I_C, NIR)
|
|
|
|
def getU(self):
|
|
return self.getChannel(U_J_D, NIR)
|
|
|
|
def getV(self):
|
|
return self.getChannel(V_K_E, NIR)
|
|
|
|
def getW(self):
|
|
return self.getChannel(W_L_F, NIR)
|
|
|
|
#Get the various UV readings
|
|
def getA(self):
|
|
return self.getChannel(R_G_A, UV)
|
|
|
|
def getB(self):
|
|
return self.getChannel(S_H_B, UV)
|
|
|
|
def getC(self):
|
|
return self.getChannel(T_I_C, UV)
|
|
|
|
def getD(self):
|
|
return self.getChannel(U_J_D, UV)
|
|
|
|
def getE(self):
|
|
return self.getChannel(V_K_E, UV)
|
|
|
|
def getF(self):
|
|
return self.getChannel(W_L_F, UV)
|
|
|
|
def getChannel(self, channelRegister, device):
|
|
self.selectDevice(device)
|
|
colorData = self.virtualReadRegister(channelRegister) << 8
|
|
colorData |= self.virtualReadRegister(channelRegister + 1)
|
|
return colorData
|
|
|
|
#Returns the various calibration data
|
|
def getCalibratedA(self):
|
|
return self.getCalibratedValue(R_G_A_CAL, UV)
|
|
|
|
def getCalibratedB(self):
|
|
return self.getCalibratedValue(S_H_B_CAL, UV)
|
|
|
|
def getCalibratedC(self):
|
|
return self.getCalibratedValue(T_I_C_CAL, UV)
|
|
|
|
def getCalibratedD(self):
|
|
return self.getCalibratedValue(U_J_D_CAL, UV)
|
|
|
|
def getCalibratedE(self):
|
|
return self.getCalibratedValue(V_K_E_CAL, UV)
|
|
|
|
def getCalibratedF(self):
|
|
return self.getCalibratedValue(W_L_F_CAL, UV)
|
|
|
|
#Returns the various calibration data
|
|
def getCalibratedG(self):
|
|
return self.getCalibratedValue(R_G_A_CAL, VISIBLE)
|
|
|
|
def getCalibratedH(self):
|
|
return self.getCalibratedValue(S_H_B_CAL, VISIBLE)
|
|
|
|
def getCalibratedI(self):
|
|
return self.getCalibratedValue(T_I_C_CAL, VISIBLE)
|
|
|
|
def getCalibratedJ(self):
|
|
return self.getCalibratedValue(U_J_D_CAL, VISIBLE)
|
|
|
|
def getCalibratedK(self):
|
|
return self.getCalibratedValue(V_K_E_CAL, VISIBLE)
|
|
|
|
def getCalibratedL(self):
|
|
return self.getCalibratedValue(W_L_F_CAL, VISIBLE)
|
|
|
|
#Returns the various calibration data
|
|
def getCalibratedR(self):
|
|
return self.getCalibratedValue(R_G_A_CAL, NIR)
|
|
|
|
def getCalibratedS(self):
|
|
return self.getCalibratedValue(S_H_B_CAL, NIR)
|
|
|
|
def getCalibratedT(self):
|
|
return self.getCalibratedValue(T_I_C_CAL, NIR)
|
|
|
|
def getCalibratedU(self):
|
|
return self.getCalibratedValue(U_J_D_CAL, NIR)
|
|
|
|
def getCalibratedV(self):
|
|
return self.getCalibratedValue(V_K_E_CAL, NIR)
|
|
|
|
def getCalibratedW(self):
|
|
return self.getCalibratedValue(W_L_F_CAL, NIR)
|
|
|
|
#Given an address, read four bytes and return the floating point calibrated value
|
|
def getCalibratedValue(self, calAddress, device):
|
|
self.selectDevice(device)
|
|
|
|
b0 = self.virtualReadRegister(calAddress + 0)
|
|
b1 = self.virtualReadRegister(calAddress + 1)
|
|
b2 = self.virtualReadRegister(calAddress + 2)
|
|
b3 = self.virtualReadRegister(calAddress + 3)
|
|
|
|
#Channel calibrated values are stored big-endian
|
|
calBytes = 0
|
|
calBytes |= (b0 << (8 * 3))
|
|
calBytes |= (b1 << (8 * 2))
|
|
calBytes |= (b2 << (8 * 1))
|
|
calBytes |= (b3 << (8 * 0))
|
|
|
|
return self.convertBytesToFloat(calBytes)
|
|
|
|
#Given 4 bytes returns the floating point value
|
|
def convertBytesToFloat(self, value):
|
|
b = struct.pack('=L', value)
|
|
f = struct.unpack('f', b)
|
|
return f[0]
|
|
|
|
def setMeasurementMode(self, mode):
|
|
mode = 0b11 if mode > 0b11 else mode
|
|
|
|
value = self.virtualReadRegister(CONFIG)
|
|
value &= 0b11110011
|
|
value |= (mode << 2)
|
|
self.virtualWriteRegister(CONFIG, value)
|
|
|
|
def setGain(self, gain):
|
|
gain = 0b11 if gain > 0b11 else gain
|
|
|
|
value = self.virtualReadRegister(CONFIG)
|
|
value &= 0b11001111
|
|
value |= (gain << 4)
|
|
self.virtualWriteRegister(CONFIG, value)
|
|
|
|
def setIntegrationCycles(self, cycleValue):
|
|
self.virtualWriteRegister(INTEGRATION_TIME, cycleValue)
|
|
|
|
def enableInterrupt(self):
|
|
value = self.virtualReadRegister(CONFIG)
|
|
value |= 0b01000000
|
|
self.virtualWriteRegister(CONFIG, value)
|
|
|
|
def disableInterrupt(self):
|
|
value = self.virtualReadRegister(CONFIG)
|
|
value &= 0b10111111
|
|
self.virtualWriteRegister(CONFIG, value)
|
|
|
|
def dataAvailable(self):
|
|
value = self.virtualReadRegister(CONFIG)
|
|
return value & 0x02
|
|
|
|
def enableBulb(self, device):
|
|
self.selectDevice(device)
|
|
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value |= 0b00001000
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def disableBulb(self, device):
|
|
self.selectDevice(device)
|
|
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value &= 0b11110111
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def setBulbCurrent(self, current, device):
|
|
self.selectDevice(device)
|
|
current = 0b11 if current > 0b11 else current
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value &= 0b11001111
|
|
value |= (current << 4)
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def selectDevice(self, device):
|
|
self.virtualWriteRegister(DEV_SELECT_CONTROL, device)
|
|
|
|
def enableIndicator(self):
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value |= 0b00000001
|
|
|
|
self.selectDevice(NIR)
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def disableIndicator(self):
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value &= 0b11111110
|
|
|
|
self.selectDevice(NIR)
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def setIndicatorCurrent(self, current):
|
|
current = 0b11 if current > 0b11 else current
|
|
value = self.virtualReadRegister(LED_CONFIG)
|
|
value &= 0b11111001
|
|
value |= (current << 1)
|
|
|
|
self.selectDevice(NIR)
|
|
self.virtualWriteRegister(LED_CONFIG, value)
|
|
|
|
def getTemperature(self, deviceNumber):
|
|
self.selectDevice(deviceNumber)
|
|
return self.virtualReadRegister(DEVICE_TEMP)
|
|
|
|
def getTemperatureAverage(self):
|
|
average = 0
|
|
for x in range(3):
|
|
average += self.getTemperature(x)
|
|
return float(average) / 3
|
|
|
|
def softReset(self):
|
|
value = self.virtualReadRegister(CONFIG)
|
|
value |= 0x80
|
|
self.virtualWriteRegister(CONFIG, value)
|
|
|
|
def virtualReadRegister(self, virtualAddr):
|
|
status = self.readRegister(STATUS_REG)
|
|
if (status & RX_VALID) != 0:
|
|
incoming = self.readRegister(READ_REG)
|
|
|
|
while(1):
|
|
status = self.readRegister(STATUS_REG)
|
|
if (status & TX_VALID) == 0:
|
|
break
|
|
time.sleep(POLLING_DELAY)
|
|
|
|
self.writeRegister(WRITE_REG, virtualAddr)
|
|
|
|
while(1):
|
|
status = self.readRegister(STATUS_REG)
|
|
if (status & RX_VALID) != 0:
|
|
break
|
|
time.sleep(POLLING_DELAY)
|
|
|
|
incoming = self.readRegister(READ_REG)
|
|
return incoming
|
|
|
|
def virtualWriteRegister(self, virtualAddr, dataToWrite):
|
|
while(1):
|
|
status = self.readRegister(STATUS_REG)
|
|
if (status & TX_VALID) == 0:
|
|
break
|
|
time.sleep(POLLING_DELAY)
|
|
|
|
self.writeRegister(WRITE_REG, virtualAddr | 0x80)
|
|
|
|
while(1):
|
|
status = self.readRegister(STATUS_REG)
|
|
if (status & TX_VALID) == 0:
|
|
break
|
|
time.sleep(POLLING_DELAY)
|
|
|
|
self.writeRegister(WRITE_REG, dataToWrite)
|
|
|
|
def readRegister(self, addr):
|
|
return self._bus.read_byte_data(I2C_ADDR, addr)
|
|
|
|
def writeRegister(self, addr, val):
|
|
return self._bus.write_byte_data(I2C_ADDR, addr, val)
|
|
|