Skip to content

Commit ac51a78

Browse files
committed
Add autolux capability.
1 parent 9977ed5 commit ac51a78

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

adafruit_veml7700.py

Lines changed: 116 additions & 0 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 UnaryStruct, 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.
@@ -205,6 +220,33 @@ def __init__(self, i2c_bus: I2C, address: int = 0x10) -> None:
205220
else:
206221
raise RuntimeError("Unable to enable VEML7700 device")
207222

223+
self.last_read = self.milliseconds()
224+
225+
@staticmethod
226+
def milliseconds() -> float:
227+
"""The time in milliseconds.
228+
229+
:return: The current time.
230+
:rtype: float
231+
"""
232+
return time.monotonic() * 1000
233+
234+
def compute_lux(self, als: int, use_correction: bool) -> float:
235+
"""Compute lux, possibly using non-linear correction.
236+
237+
:param int als: The ambient light level.
238+
:param bool use_correction: Flag for applying the non-linear correction.
239+
240+
:return: The calculated lux.
241+
:rtype: float
242+
"""
243+
lux = self.resolution() * als
244+
if use_correction:
245+
lux = (
246+
((6.0135e-13 * lux - 9.3924e-9) * lux + 8.1488e-5) * lux + 1.0023
247+
) * lux
248+
return lux
249+
208250
def integration_time_value(self) -> int:
209251
"""Integration time value in integer form. Used for calculating :meth:`resolution`."""
210252
integration_time = self.light_integration_time
@@ -253,3 +295,77 @@ def lux(self) -> float:
253295
time.sleep(0.1)
254296
"""
255297
return self.resolution() * self.light
298+
299+
@property
300+
def autolux(self) -> float:
301+
"""Light value in lux using auto checks and correction.
302+
303+
This property uses auto gain and auto integration time adjustments as well
304+
as a non-linear correction if necessary.
305+
306+
.. code-block:: python
307+
308+
import time
309+
import board
310+
import adafruit_veml7700
311+
312+
i2c = board.I2C() # uses board.SCL and board.SDA
313+
veml7700 = adafruit_veml7700.VEML7700(i2c)
314+
315+
while True:
316+
print("Lux:", veml7700.autolux)
317+
veml7700.wait_autolux(0.1)
318+
"""
319+
gain_index = 0
320+
it_index = 2
321+
use_correction = False
322+
323+
self.gain_settings.index(self.light_gain)
324+
self.integration_time_settings.index(self.light_integration_time)
325+
326+
als = self._read_als_wait()
327+
328+
if als <= 100:
329+
while als <= 100 and not (gain_index == 3 and it_index == 5):
330+
if gain_index < 3:
331+
gain_index += 1
332+
self.light_gain = self.gain_settings[gain_index]
333+
elif it_index < 5:
334+
it_index += 1
335+
self.light_integration_time = self.integration_time_settings[
336+
it_index
337+
]
338+
als = self._read_als_wait()
339+
else:
340+
use_correction = True
341+
while als > 10000 and it_index > 0:
342+
it_index -= 1
343+
self.light_integration_time = self.integration_time_settings[it_index]
344+
als = self._read_als_wait()
345+
346+
return self.compute_lux(als, use_correction)
347+
348+
def _read_als_wait(self) -> float:
349+
"""Read ambient light level, but wait on the integration time.
350+
351+
:return: The ambient light level value.
352+
:rtype: float
353+
"""
354+
time_to_wait = 2 * self.integration_time_value()
355+
time_waited = self.milliseconds() - self.last_read
356+
if time_waited < time_to_wait:
357+
time.sleep((time_to_wait - time_waited) / 1000)
358+
self.last_read = self.milliseconds()
359+
return self.light
360+
361+
def wait_autolux(self, wait_time: float) -> None:
362+
"""Wait minimum time between autolux measurements.
363+
364+
Ensure that the shortest wait time cannot be below the current
365+
integration time setting.
366+
367+
:param float wait_time: The requested time between measurements (seconds).
368+
"""
369+
minimum_wait_time = self.integration_time_value() / 1000
370+
actual_wait_time = max(minimum_wait_time, wait_time)
371+
time.sleep(actual_wait_time)

0 commit comments

Comments
 (0)