Skip to content

Commit d8708fd

Browse files
authored
Merge pull request #29 from mareuter/add_autolux
Add autolux
2 parents a08de09 + ac75b0e commit d8708fd

File tree

1 file changed

+118
-2
lines changed

1 file changed

+118
-2
lines changed

adafruit_veml7700.py

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
https://github.com/adafruit/Adafruit_CircuitPython_Register
3232
"""
3333

34+
import time
35+
3436
from micropython import const
3537
import adafruit_bus_device.i2c_device as i2cdevice
3638
from adafruit_register.i2c_struct import ROUnaryStruct
@@ -78,6 +80,9 @@ class VEML7700:
7880
ALS_GAIN_1_8: 0.125,
7981
}
8082

83+
# Convenience list of gains
84+
gain_settings = [ALS_GAIN_1_8, ALS_GAIN_1_4, ALS_GAIN_1, ALS_GAIN_2]
85+
8186
# Integration time value integers
8287
integration_time_values = {
8388
ALS_25MS: 25,
@@ -88,6 +93,16 @@ class VEML7700:
8893
ALS_800MS: 800,
8994
}
9095

96+
# Convenience list of integration times
97+
integration_time_settings = [
98+
ALS_25MS,
99+
ALS_50MS,
100+
ALS_100MS,
101+
ALS_200MS,
102+
ALS_400MS,
103+
ALS_800MS,
104+
]
105+
91106
# ALS - Ambient light sensor high resolution output data
92107
light = ROUnaryStruct(0x04, "<H")
93108
"""Ambient light data.
@@ -144,7 +159,7 @@ class VEML7700:
144159
import adafruit_veml7700
145160
146161
i2c = board.I2C() # uses board.SCL and board.SDA
147-
veml7700 = adafruit_vcnl4040.VCNL4040(i2c)
162+
veml7700 = adafruit_veml7700.VEML7700(i2c)
148163
149164
veml7700.light_gain = veml7700.ALS_GAIN_2
150165
@@ -167,7 +182,7 @@ class VEML7700:
167182
import adafruit_veml7700
168183
169184
i2c = board.I2C() # uses board.SCL and board.SDA
170-
veml7700 = adafruit_vcnl4040.VCNL4040(i2c)
185+
veml7700 = adafruit_veml7700.VEML7700(i2c)
171186
172187
veml7700.light_integration_time = veml7700.ALS_400MS
173188
@@ -191,6 +206,33 @@ def __init__(self, i2c_bus: I2C, address: int = 0x10) -> None:
191206
else:
192207
raise RuntimeError("Unable to enable VEML7700 device")
193208

209+
self.last_read = self.milliseconds()
210+
211+
@staticmethod
212+
def milliseconds() -> float:
213+
"""The time in milliseconds.
214+
215+
:return: The current time.
216+
:rtype: float
217+
"""
218+
return time.monotonic() * 1000
219+
220+
def compute_lux(self, als: int, use_correction: bool) -> float:
221+
"""Compute lux, possibly using non-linear correction.
222+
223+
:param int als: The ambient light level.
224+
:param bool use_correction: Flag for applying the non-linear correction.
225+
226+
:return: The calculated lux.
227+
:rtype: float
228+
"""
229+
lux = self.resolution() * als
230+
if use_correction:
231+
lux = (
232+
((6.0135e-13 * lux - 9.3924e-9) * lux + 8.1488e-5) * lux + 1.0023
233+
) * lux
234+
return lux
235+
194236
def integration_time_value(self) -> int:
195237
"""Integration time value in integer form. Used for calculating :meth:`resolution`."""
196238
integration_time = self.light_integration_time
@@ -239,3 +281,77 @@ def lux(self) -> float:
239281
time.sleep(0.1)
240282
"""
241283
return self.resolution() * self.light
284+
285+
@property
286+
def autolux(self) -> float:
287+
"""Light value in lux using auto checks and correction.
288+
289+
This property uses auto gain and auto integration time adjustments as well
290+
as a non-linear correction if necessary.
291+
292+
.. code-block:: python
293+
294+
import time
295+
import board
296+
import adafruit_veml7700
297+
298+
i2c = board.I2C() # uses board.SCL and board.SDA
299+
veml7700 = adafruit_veml7700.VEML7700(i2c)
300+
301+
while True:
302+
print("Lux:", veml7700.autolux)
303+
veml7700.wait_autolux(0.1)
304+
"""
305+
gain_index = 0
306+
it_index = 2
307+
use_correction = False
308+
309+
self.gain_settings.index(self.light_gain)
310+
self.integration_time_settings.index(self.light_integration_time)
311+
312+
als = self._read_als_wait()
313+
314+
if als <= 100:
315+
while als <= 100 and not (gain_index == 3 and it_index == 5):
316+
if gain_index < 3:
317+
gain_index += 1
318+
self.light_gain = self.gain_settings[gain_index]
319+
elif it_index < 5:
320+
it_index += 1
321+
self.light_integration_time = self.integration_time_settings[
322+
it_index
323+
]
324+
als = self._read_als_wait()
325+
else:
326+
use_correction = True
327+
while als > 10000 and it_index > 0:
328+
it_index -= 1
329+
self.light_integration_time = self.integration_time_settings[it_index]
330+
als = self._read_als_wait()
331+
332+
return self.compute_lux(als, use_correction)
333+
334+
def _read_als_wait(self) -> float:
335+
"""Read ambient light level, but wait on the integration time.
336+
337+
:return: The ambient light level value.
338+
:rtype: float
339+
"""
340+
time_to_wait = 2 * self.integration_time_value()
341+
time_waited = self.milliseconds() - self.last_read
342+
if time_waited < time_to_wait:
343+
time.sleep((time_to_wait - time_waited) / 1000)
344+
self.last_read = self.milliseconds()
345+
return self.light
346+
347+
def wait_autolux(self, wait_time: float) -> None:
348+
"""Wait minimum time between autolux measurements.
349+
350+
Ensure that the shortest wait time cannot be below the current
351+
integration time setting.
352+
353+
:param float wait_time: The requested time between measurements (seconds).
354+
"""
355+
minimum_wait_time = self.integration_time_value() / 1000
356+
actual_wait_time = max(minimum_wait_time, wait_time)
357+
time.sleep(actual_wait_time)

0 commit comments

Comments
 (0)