add ambilight sensor class
This commit is contained in:
parent
e59712a7f9
commit
3942ac787e
|
|
@ -0,0 +1,34 @@
|
||||||
|
from sensors import Sensors
|
||||||
|
from machine import Pin, I2C
|
||||||
|
from utime import sleep
|
||||||
|
from lib.bh1750 import BH1750
|
||||||
|
|
||||||
|
|
||||||
|
class AmbilightSensor(Sensors):
|
||||||
|
|
||||||
|
|
||||||
|
most_recent_values = []
|
||||||
|
|
||||||
|
def __init__(self, settings):
|
||||||
|
super().__init__(settings)
|
||||||
|
print(settings) # TODO remove
|
||||||
|
self.sensor_pin_int = settings['pin_int']
|
||||||
|
# self.sensor = DHT22(Pin(self.sensor_pin_int, Pin.IN, Pin.PULL_UP))
|
||||||
|
self.sensor = BH1750(I2C(0, sda=Pin(settings['pin_int_sda']), scl=Pin(settings['pin_int_scl'])))
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
try:
|
||||||
|
measurement = self.sensor.luminance(BH1750.ONCE_HIRES_1)
|
||||||
|
print("ambilight ..")
|
||||||
|
print(measurement)
|
||||||
|
self.most_recent_values = [
|
||||||
|
{
|
||||||
|
'type': 'ambilight',
|
||||||
|
'value': measurement,
|
||||||
|
'unit': '-'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
except OSError:
|
||||||
|
print('Ambilight Error reading temperature/humidity. Check wires')
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from .bh1750 import BH1750
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
# https://github.com/flrrth/pico-bh1750
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
from micropython import const
|
||||||
|
from utime import sleep_ms
|
||||||
|
|
||||||
|
|
||||||
|
class BH1750:
|
||||||
|
"""Class for the BH1750 digital Ambient Light Sensor
|
||||||
|
|
||||||
|
The datasheet can be found at https://components101.com/sites/default/files/component_datasheet/BH1750.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
MEASUREMENT_MODE_CONTINUOUSLY = const(1)
|
||||||
|
MEASUREMENT_MODE_ONE_TIME = const(2)
|
||||||
|
|
||||||
|
RESOLUTION_HIGH = const(0)
|
||||||
|
RESOLUTION_HIGH_2 = const(1)
|
||||||
|
RESOLUTION_LOW = const(2)
|
||||||
|
|
||||||
|
MEASUREMENT_TIME_DEFAULT = const(69)
|
||||||
|
MEASUREMENT_TIME_MIN = const(31)
|
||||||
|
MEASUREMENT_TIME_MAX = const(254)
|
||||||
|
|
||||||
|
def __init__(self, address, i2c):
|
||||||
|
self._address = address
|
||||||
|
self._i2c = i2c
|
||||||
|
self._measurement_mode = BH1750.MEASUREMENT_MODE_ONE_TIME
|
||||||
|
self._resolution = BH1750.RESOLUTION_HIGH
|
||||||
|
self._measurement_time = BH1750.MEASUREMENT_TIME_DEFAULT
|
||||||
|
|
||||||
|
self._write_measurement_time()
|
||||||
|
self._write_measurement_mode()
|
||||||
|
|
||||||
|
def configure(self, measurement_mode: int, resolution: int, measurement_time: int):
|
||||||
|
"""Configures the BH1750.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
measurement_mode -- measure either continuously or once
|
||||||
|
resolution -- return measurements in either high, high2 or low resolution
|
||||||
|
measurement_time -- the duration of a single measurement
|
||||||
|
"""
|
||||||
|
if measurement_time not in range(BH1750.MEASUREMENT_TIME_MIN, BH1750.MEASUREMENT_TIME_MAX + 1):
|
||||||
|
raise ValueError("measurement_time must be between {0} and {1}"
|
||||||
|
.format(BH1750.MEASUREMENT_TIME_MIN, BH1750.MEASUREMENT_TIME_MAX))
|
||||||
|
|
||||||
|
self._measurement_mode = measurement_mode
|
||||||
|
self._resolution = resolution
|
||||||
|
self._measurement_time = measurement_time
|
||||||
|
|
||||||
|
self._write_measurement_time()
|
||||||
|
self._write_measurement_mode()
|
||||||
|
|
||||||
|
def _write_measurement_time(self):
|
||||||
|
buffer = bytearray(1)
|
||||||
|
|
||||||
|
high_bit = 1 << 6 | self._measurement_time >> 5
|
||||||
|
low_bit = 3 << 5 | (self._measurement_time << 3) >> 3
|
||||||
|
|
||||||
|
buffer[0] = high_bit
|
||||||
|
self._i2c.writeto(self._address, buffer)
|
||||||
|
|
||||||
|
buffer[0] = low_bit
|
||||||
|
self._i2c.writeto(self._address, buffer)
|
||||||
|
|
||||||
|
def _write_measurement_mode(self):
|
||||||
|
buffer = bytearray(1)
|
||||||
|
|
||||||
|
buffer[0] = self._measurement_mode << 4 | self._resolution
|
||||||
|
self._i2c.writeto(self._address, buffer)
|
||||||
|
sleep_ms(24 if self._measurement_time == BH1750.RESOLUTION_LOW else 180)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Clear the illuminance data register."""
|
||||||
|
self._i2c.writeto(self._address, bytearray(b'\x07'))
|
||||||
|
|
||||||
|
def power_on(self):
|
||||||
|
"""Powers on the BH1750."""
|
||||||
|
self._i2c.writeto(self._address, bytearray(b'\x01'))
|
||||||
|
|
||||||
|
def power_off(self):
|
||||||
|
"""Powers off the BH1750."""
|
||||||
|
self._i2c.writeto(self._address, bytearray(b'\x00'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def measurement(self) -> float:
|
||||||
|
"""Returns the latest measurement."""
|
||||||
|
if self._measurement_mode == BH1750.MEASUREMENT_MODE_ONE_TIME:
|
||||||
|
self._write_measurement_mode()
|
||||||
|
|
||||||
|
buffer = bytearray(2)
|
||||||
|
self._i2c.readfrom_into(self._address, buffer)
|
||||||
|
lux = (buffer[0] << 8 | buffer[1]) / (1.2 * (BH1750.MEASUREMENT_TIME_DEFAULT / self._measurement_time))
|
||||||
|
|
||||||
|
if self._resolution == BH1750.RESOLUTION_HIGH_2:
|
||||||
|
return lux / 2
|
||||||
|
else:
|
||||||
|
return lux
|
||||||
|
|
||||||
|
def measurements(self) -> float:
|
||||||
|
"""This is a generator function that continues to provide the latest measurement. Because the measurement time
|
||||||
|
is greatly affected by resolution and the configured measurement time, this function attemts to calculate the
|
||||||
|
appropriate sleep time between measurements.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
for measurement in bh1750.measurements(): # bh1750 is an instance of this class
|
||||||
|
print(measurement)
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
yield self.measurement
|
||||||
|
|
||||||
|
if self._measurement_mode == BH1750.MEASUREMENT_MODE_CONTINUOUSLY:
|
||||||
|
base_measurement_time = 16 if self._measurement_time == BH1750.RESOLUTION_LOW else 120
|
||||||
|
sleep_ms(math.ceil(base_measurement_time * self._measurement_time / BH1750.MEASUREMENT_TIME_DEFAULT))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
"""
|
||||||
|
Micropython BH1750 ambient light sensor driver.
|
||||||
|
* https://github.com/PinkInk/upylib/tree/master/bh1750
|
||||||
|
"""
|
||||||
|
|
||||||
|
from utime import sleep_ms
|
||||||
|
|
||||||
|
|
||||||
|
class BH1750():
|
||||||
|
"""Micropython BH1750 ambient light sensor driver."""
|
||||||
|
|
||||||
|
PWR_OFF = 0x00
|
||||||
|
PWR_ON = 0x01
|
||||||
|
RESET = 0x07
|
||||||
|
|
||||||
|
# modes
|
||||||
|
CONT_LOWRES = 0x13
|
||||||
|
CONT_HIRES_1 = 0x10
|
||||||
|
CONT_HIRES_2 = 0x11
|
||||||
|
ONCE_HIRES_1 = 0x20
|
||||||
|
ONCE_HIRES_2 = 0x21
|
||||||
|
ONCE_LOWRES = 0x23
|
||||||
|
|
||||||
|
# default addr=0x23 if addr pin floating or pulled to ground
|
||||||
|
# addr=0x5c if addr pin pulled high
|
||||||
|
def __init__(self, bus, addr=0x23):
|
||||||
|
self.bus = bus
|
||||||
|
self.addr = addr
|
||||||
|
self.off()
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def off(self):
|
||||||
|
"""Turn sensor off."""
|
||||||
|
self.set_mode(self.PWR_OFF)
|
||||||
|
|
||||||
|
def on(self):
|
||||||
|
"""Turn sensor on."""
|
||||||
|
self.set_mode(self.PWR_ON)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Reset sensor, turn on first if required."""
|
||||||
|
self.on()
|
||||||
|
self.set_mode(self.RESET)
|
||||||
|
|
||||||
|
def set_mode(self, mode):
|
||||||
|
"""Set sensor mode."""
|
||||||
|
self.mode = mode
|
||||||
|
self.bus.writeto(self.addr, bytes([self.mode]))
|
||||||
|
|
||||||
|
def luminance(self, mode):
|
||||||
|
"""Sample luminance (in lux), using specified sensor mode."""
|
||||||
|
# continuous modes
|
||||||
|
if mode & 0x10 and mode != self.mode:
|
||||||
|
self.set_mode(mode)
|
||||||
|
# one shot modes
|
||||||
|
if mode & 0x20:
|
||||||
|
self.set_mode(mode)
|
||||||
|
# earlier measurements return previous reading
|
||||||
|
sleep_ms(24 if mode in (0x13, 0x23) else 180)
|
||||||
|
data = self.bus.readfrom(self.addr, 2)
|
||||||
|
factor = 2.0 if mode in (0x11, 0x21) else 1.0
|
||||||
|
return (data[0]<<8 | data[1]) / (1.2 * factor)
|
||||||
Loading…
Reference in New Issue