diff --git a/ambilight_sensor.py b/ambilight_sensor.py new file mode 100644 index 0000000..c8f0a3c --- /dev/null +++ b/ambilight_sensor.py @@ -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() + diff --git a/bh1750.old_1/__init__.py b/bh1750.old_1/__init__.py new file mode 100644 index 0000000..ab5e217 --- /dev/null +++ b/bh1750.old_1/__init__.py @@ -0,0 +1 @@ +from .bh1750 import BH1750 diff --git a/bh1750.old_1/bh1750.py b/bh1750.old_1/bh1750.py new file mode 100644 index 0000000..21cebbe --- /dev/null +++ b/bh1750.old_1/bh1750.py @@ -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)) + + diff --git a/lib/bh1750.py b/lib/bh1750.py new file mode 100644 index 0000000..0f91b49 --- /dev/null +++ b/lib/bh1750.py @@ -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) \ No newline at end of file