File size: 4,125 Bytes
4bec42e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"""Sterling Baird: wrapper class for AS7341 sensor."""
from math import log
from as7341 import AS7341, AS7341_MODE_SPM
from machine import I2C, Pin
class ExternalDeviceNotFound(OSError):
pass
class Sensor:
def __init__(
self, atime=100, astep=999, gain=8, i2c=I2C(1, scl=Pin(27), sda=Pin(26))
):
"""Wrapper for Rob Hamerling's AS7341 implementation.
Mimics the original CircuitPython class a bit more, specific to the needs of
SDL-Demo.
Rob Hamerling's implementation:
- https://gitlab.com/robhamerling/micropython-as7341
Original Circuit Python repo:
- https://github.com/adafruit/Adafruit_CircuitPython_AS7341
Parameters
----------
atime : int, optional
The integration time step size in 2.78 microsecond increments, by default 100
astep : int, optional
The integration time step count. Total integration time will be (ATIME + 1)
* (ASTEP + 1) * 2.78µS, by default 999, meaning 281 ms assuming atime=100
gain : int, optional
The ADC gain multiplier, by default 128
i2c : I2C, optional
The I2C bus, by default machine.I2C(1, scl=machine.Pin(27),
sda=machine.Pin(26))
Raises
------
ExternalDeviceNotFound
Couldn't connect to AS7341.
Examples
--------
>>> sensor = Sensor(atime=29, astep=599, again=4)
>>> channel_data = sensor.all_channels
"""
# i2c = machine.SoftI2C(scl=Pin(27), sda=Pin(26))
self.i2c = i2c
addrlist = " ".join(["0x{:02X}".format(x) for x in i2c.scan()]) # type: ignore
print("Detected devices at I2C-addresses:", addrlist)
sensor = AS7341(i2c)
if not sensor.isconnected():
raise ExternalDeviceNotFound("Failed to contact AS7341, terminating")
sensor.set_measure_mode(AS7341_MODE_SPM)
sensor.set_atime(atime)
sensor.set_astep(astep)
sensor.set_again(gain)
self.sensor = sensor
self.__atime = atime
self.__astep = astep
self.__gain = gain
@property
def _atime(self):
return self.__atime
@_atime.setter
def _atime(self, value):
self.__atime = value
self.sensor.set_atime(value)
@property
def _astep(self):
return self.__astep
@_astep.setter
def _astep(self, value):
self.__atime = value
self.sensor.set_astep(value)
@property
def _gain(self):
return self.__gain
@_gain.setter
def _gain(self, gain):
"""set AGAIN (code in range 0..10 -> gain factor 0.5 .. 512)
gain: *0.5 | *1 | *2 | *4 | *8 | *16 | *32 | *64 | *128 | *256 | *512
code 0 1 2 3 4 5 6 7 8 9 10
"""
self.__gain = gain
# gain == 0.5 * 2 ** code --> code == 1.4427 Ln[2 * gain] (via Mathematica)
code = int(round(1.4427 * log(2 * gain)))
self.sensor.set_again(code)
@property
def all_channels(self):
self.sensor.start_measure("F1F4CN")
f1, f2, f3, f4, clr, nir = self.sensor.get_spectral_data()
self.sensor.start_measure("F5F8CN")
f5, f6, f7, f8, clr, nir = self.sensor.get_spectral_data()
clr, nir # to ignore "unused" linting warnings
return [f1, f2, f3, f4, f5, f6, f7, f8]
@property
def all_channels_clr_nir(self):
self.sensor.start_measure("F1F4CN")
f1, f2, f3, f4, clr, nir = self.sensor.get_spectral_data()
self.sensor.start_measure("F5F8CN")
f5, f6, f7, f8, clr, nir = self.sensor.get_spectral_data()
clr, nir # to ignore "unused" linting warnings
return [f1, f2, f3, f4, f5, f6, f7, f8, clr, nir]
def disable(self):
self.sensor.disable()
# %% Code Graveyard
# gain_to_code_lookup = {
# 0.5: 1,
# 1: 1,
# 2: 2,
# 4: 3,
# 8: 4,
# 16: 5,
# 32: 6,
# 64: 7,
# 128: 8,
# 256: 9,
# 512: 10,
# }
# code = gain_to_code_lookup[gain]
|