main #3
|
|
@ -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