From 8fe0fa656dc4217dc514bf01424820f86c4b7d3d Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Thu, 11 Jul 2024 22:59:35 +0100 Subject: [PATCH 1/6] Add support for veml6075 sensors. --- mqtt_io/modules/sensor/veml6075.py | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 mqtt_io/modules/sensor/veml6075.py diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py new file mode 100644 index 00000000..2f6bedbc --- /dev/null +++ b/mqtt_io/modules/sensor/veml6075.py @@ -0,0 +1,92 @@ +""" +VEML 6075 UV sensor +""" + +from mqtt_io.types import ConfigType, SensorValueType +from . import GenericSensor +import logging + +REQUIREMENTS = ("smbus2", "veml6075",) + +CONFIG_SCHEMA = { + "i2c_bus_num": {"type": "integer", "required": True, "empty": False}, +} + + +# UV COEFFICIENTS AND RESPONSIVITY +# See https://web.archive.org/web/20190416120825/http://www.vishay.com/docs/84339/designingveml6075.pdf +# For more details +################################################################################## +# Configuration # a # b # c # d # UVAresp # UVBresp # +################################################################################## +# No teflon (open air) # 2.22 # 1.33 # 2.95 # 1.74 # 0.001461 # 0.002591 # +# 0.1 mm teflon 4.5 mm window # 2.22 # 1.33 # 2.95 # 1.74 # 0.002303 # 0.004686 # +# 0.1 mm teflon 5.5 mm window # 2.22 # 1.33 # 2.95 # 1.74 # 0.002216 # 0.005188 # +# 0.1 mm teflon 10 mm window # 2.22 # 1.33 # 2.95 # 1.74 # 0.002681 # 0.004875 # +# 0.25 mm teflon 10 mm window # 2.22 # 1.33 # 2.95 # 1.74 # 0.002919 # 0.009389 # +# 0.4 mm teflon 10 mm window # 2.22 # 1.17 # 2.95 # 1.58 # 0.004770 # 0.006135 # +# 0.7 mm teflon 10 mm window # 2.22 # 1.17 # 2.95 # 1.58 # 0.007923 # 0.008334 # +# 1.0 mm teflon 5.5 mm window # 2.55 # 1.00 # 3.80 # 1.10 # 0.006000 # 0.003100 # +################################################################################## + +_LOG = logging.getLogger(__name__) + + +class Sensor(GenericSensor): + """ + Implementation of Sensor class for the VEML 6075 UV sensor. + """ + + SENSOR_SCHEMA = { + "alpha": {"type": "float", "required": False, "empty": False, "default": 1.0}, + "beta": {"type": "float", "required": False, "empty": False, "default": 1.0}, + "gamma": {"type": "float", "required": False, "empty": False, "default": 1.0}, + "delta": {"type": "float", "required": False, "empty": False, "default": 1.0}, + "a": {"type": "float", "required": False, "empty": False, "default": 2.22}, + "b": {"type": "float", "required": False, "empty": False, "default": 1.33}, + "c": {"type": "float", "required": False, "empty": False, "default": 2.95}, + "d": {"type": "float", "required": False, "empty": False, "default": 1.74}, + "UVAresp": {"type": "float", "required": False, "empty": False, "default": 0.001461}, + "UVBresp": {"type": "float", "required": False, "empty": False, "default": 0.002591}, + } + + def setup_module(self) -> None: + # pylint: disable=import-outside-toplevel,import-error + from smbus2 import SMBus # type: ignore + from veml6075 import VEML6075 # type: ignore + + self.bus = SMBus(self.config["i2c_bus_num"]) + self.sensor = VEML6075(i2c_dev=self.bus) + + + def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: + + uva_calc = uva - ((sens_conf["a"] * sens_conf["alpha"] * uv_comp1) / sens_conf["gamma"]) - ((sens_conf["b"] * sens_conf["alpha"] * uv_comp2) / sens_conf["delta"]) + _LOG.info("uva_calc " + str(uva_calc)) + uvb_calc = uvb - ((sens_conf["c"] * sens_conf["beta"] * uv_comp1) / sens_conf["gamma"]) - ((sens_conf["d"] * sens_conf["beta"] * uv_comp2) / sens_conf["delta"]) + _LOG.info("uvb_calc " + str(uvb_calc)) + uva_index = uva_calc * (1 / sens_conf["alpha"]) * sens_conf["UVAresp"] + _LOG.info("uva_index " + str(uva_index)) + uvb_index = uvb_calc * (1 / sens_conf["beta"]) * sens_conf["UVBresp"] + _LOG.info("uvb_index " + str(uvb_index)) + uv_index = (uva_index + uvb_index) / 2 + return uv_index + + def get_value(self, sens_conf: ConfigType) -> SensorValueType: + """ + Get the UV index from the sensor + """ + # Setup and turn on the sensor + self.sensor.set_shutdown(False) + self.sensor.set_high_dynamic_range(False) + self.sensor.set_integration_time('100ms') + + # Fetch the values + uva, uvb = self.sensor.get_measurements() + uv_comp1, uv_comp2 = self.sensor.get_comparitor_readings() + + # Turn off the sensor + self.sensor.set_shutdown(True) + + # Calculate and return the UV index + return self.calculate_uv_index(sens_conf, uva, uvb, uv_comp1, uv_comp2) From 337bd8a5a1343ef15fa8694f19e530a0c75bdbca Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Sun, 11 Aug 2024 13:39:41 +0100 Subject: [PATCH 2/6] Don't turn off the sensor and don't use high dynamic range. Also get rid of alpha-gamma values. --- mqtt_io/modules/sensor/veml6075.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py index 2f6bedbc..1e49d025 100644 --- a/mqtt_io/modules/sensor/veml6075.py +++ b/mqtt_io/modules/sensor/veml6075.py @@ -5,6 +5,7 @@ from mqtt_io.types import ConfigType, SensorValueType from . import GenericSensor import logging +import time REQUIREMENTS = ("smbus2", "veml6075",) @@ -38,10 +39,6 @@ class Sensor(GenericSensor): """ SENSOR_SCHEMA = { - "alpha": {"type": "float", "required": False, "empty": False, "default": 1.0}, - "beta": {"type": "float", "required": False, "empty": False, "default": 1.0}, - "gamma": {"type": "float", "required": False, "empty": False, "default": 1.0}, - "delta": {"type": "float", "required": False, "empty": False, "default": 1.0}, "a": {"type": "float", "required": False, "empty": False, "default": 2.22}, "b": {"type": "float", "required": False, "empty": False, "default": 1.33}, "c": {"type": "float", "required": False, "empty": False, "default": 2.95}, @@ -57,17 +54,21 @@ def setup_module(self) -> None: self.bus = SMBus(self.config["i2c_bus_num"]) self.sensor = VEML6075(i2c_dev=self.bus) + self.sensor.set_shutdown(True) + self.sensor.set_high_dynamic_range(False) + self.sensor.set_integration_time('100ms') + self.sensor.set_shutdown(False) def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: - - uva_calc = uva - ((sens_conf["a"] * sens_conf["alpha"] * uv_comp1) / sens_conf["gamma"]) - ((sens_conf["b"] * sens_conf["alpha"] * uv_comp2) / sens_conf["delta"]) + _LOG.info("UVA: " + str(uva) + " UVB: " + str(uvb) + " UV_comp1: " + str(uv_comp1) + " UV_comp2: " + str(uv_comp2)) + uva_calc = uva - (sens_conf["a"] * uv_comp1) - (sens_conf["b"] * uv_comp2) _LOG.info("uva_calc " + str(uva_calc)) - uvb_calc = uvb - ((sens_conf["c"] * sens_conf["beta"] * uv_comp1) / sens_conf["gamma"]) - ((sens_conf["d"] * sens_conf["beta"] * uv_comp2) / sens_conf["delta"]) + uvb_calc = uvb - (sens_conf["c"] * uv_comp1) - (sens_conf["d"] * uv_comp2) _LOG.info("uvb_calc " + str(uvb_calc)) - uva_index = uva_calc * (1 / sens_conf["alpha"]) * sens_conf["UVAresp"] + uva_index = uva_calc * sens_conf["UVAresp"] _LOG.info("uva_index " + str(uva_index)) - uvb_index = uvb_calc * (1 / sens_conf["beta"]) * sens_conf["UVBresp"] + uvb_index = uvb_calc * sens_conf["UVBresp"] _LOG.info("uvb_index " + str(uvb_index)) uv_index = (uva_index + uvb_index) / 2 return uv_index @@ -77,16 +78,14 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: Get the UV index from the sensor """ # Setup and turn on the sensor - self.sensor.set_shutdown(False) - self.sensor.set_high_dynamic_range(False) - self.sensor.set_integration_time('100ms') # Fetch the values + #time.sleep(.2) uva, uvb = self.sensor.get_measurements() uv_comp1, uv_comp2 = self.sensor.get_comparitor_readings() # Turn off the sensor - self.sensor.set_shutdown(True) + #self.sensor.set_shutdown(True) # Calculate and return the UV index return self.calculate_uv_index(sens_conf, uva, uvb, uv_comp1, uv_comp2) From cf1a75746b253eefbeb23d3cc47bc70da8ca18d5 Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Sun, 11 Aug 2024 13:41:42 +0100 Subject: [PATCH 3/6] Some cleanup and make the logging debug. --- mqtt_io/modules/sensor/veml6075.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py index 1e49d025..7cd3ec6e 100644 --- a/mqtt_io/modules/sensor/veml6075.py +++ b/mqtt_io/modules/sensor/veml6075.py @@ -5,7 +5,6 @@ from mqtt_io.types import ConfigType, SensorValueType from . import GenericSensor import logging -import time REQUIREMENTS = ("smbus2", "veml6075",) @@ -61,15 +60,15 @@ def setup_module(self) -> None: def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: - _LOG.info("UVA: " + str(uva) + " UVB: " + str(uvb) + " UV_comp1: " + str(uv_comp1) + " UV_comp2: " + str(uv_comp2)) + _LOG.debug("UVA: " + str(uva) + " UVB: " + str(uvb) + " UV_comp1: " + str(uv_comp1) + " UV_comp2: " + str(uv_comp2)) uva_calc = uva - (sens_conf["a"] * uv_comp1) - (sens_conf["b"] * uv_comp2) - _LOG.info("uva_calc " + str(uva_calc)) + _LOG.debug("uva_calc " + str(uva_calc)) uvb_calc = uvb - (sens_conf["c"] * uv_comp1) - (sens_conf["d"] * uv_comp2) - _LOG.info("uvb_calc " + str(uvb_calc)) + _LOG.debug("uvb_calc " + str(uvb_calc)) uva_index = uva_calc * sens_conf["UVAresp"] - _LOG.info("uva_index " + str(uva_index)) + _LOG.debug("uva_index " + str(uva_index)) uvb_index = uvb_calc * sens_conf["UVBresp"] - _LOG.info("uvb_index " + str(uvb_index)) + _LOG.debug("uvb_index " + str(uvb_index)) uv_index = (uva_index + uvb_index) / 2 return uv_index @@ -80,12 +79,8 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: # Setup and turn on the sensor # Fetch the values - #time.sleep(.2) uva, uvb = self.sensor.get_measurements() uv_comp1, uv_comp2 = self.sensor.get_comparitor_readings() - # Turn off the sensor - #self.sensor.set_shutdown(True) - # Calculate and return the UV index return self.calculate_uv_index(sens_conf, uva, uvb, uv_comp1, uv_comp2) From c0d71fd0059cb54f3ffbd96bc4c19406de40d839 Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Sun, 11 Aug 2024 13:42:20 +0100 Subject: [PATCH 4/6] Remove bogus comment. --- mqtt_io/modules/sensor/veml6075.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py index 7cd3ec6e..7d2dc05a 100644 --- a/mqtt_io/modules/sensor/veml6075.py +++ b/mqtt_io/modules/sensor/veml6075.py @@ -76,7 +76,6 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: """ Get the UV index from the sensor """ - # Setup and turn on the sensor # Fetch the values uva, uvb = self.sensor.get_measurements() From cc80f220a661c331c478c5dbe520485f20906ff2 Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Sun, 11 Aug 2024 14:08:51 +0100 Subject: [PATCH 5/6] Fix lint issues. --- mqtt_io/modules/sensor/veml6075.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py index 7d2dc05a..e377a0b9 100644 --- a/mqtt_io/modules/sensor/veml6075.py +++ b/mqtt_io/modules/sensor/veml6075.py @@ -2,9 +2,9 @@ VEML 6075 UV sensor """ +import logging from mqtt_io.types import ConfigType, SensorValueType from . import GenericSensor -import logging REQUIREMENTS = ("smbus2", "veml6075",) @@ -14,7 +14,8 @@ # UV COEFFICIENTS AND RESPONSIVITY -# See https://web.archive.org/web/20190416120825/http://www.vishay.com/docs/84339/designingveml6075.pdf +# More details here : +# https://web.archive.org/web/20190416120825/http://www.vishay.com/docs/84339/designingveml6075.pdf # For more details ################################################################################## # Configuration # a # b # c # d # UVAresp # UVBresp # @@ -45,7 +46,7 @@ class Sensor(GenericSensor): "UVAresp": {"type": "float", "required": False, "empty": False, "default": 0.001461}, "UVBresp": {"type": "float", "required": False, "empty": False, "default": 0.002591}, } - + def setup_module(self) -> None: # pylint: disable=import-outside-toplevel,import-error from smbus2 import SMBus # type: ignore @@ -60,15 +61,17 @@ def setup_module(self) -> None: def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: - _LOG.debug("UVA: " + str(uva) + " UVB: " + str(uvb) + " UV_comp1: " + str(uv_comp1) + " UV_comp2: " + str(uv_comp2)) + """ + Calculate the UV index from received values. + """ + + _LOG.debug("UVA: %f UVB: %f UV_comp1: %f UV_comp2: %f)", uva, uvb, uv_comp1, uv_comp2) uva_calc = uva - (sens_conf["a"] * uv_comp1) - (sens_conf["b"] * uv_comp2) - _LOG.debug("uva_calc " + str(uva_calc)) uvb_calc = uvb - (sens_conf["c"] * uv_comp1) - (sens_conf["d"] * uv_comp2) - _LOG.debug("uvb_calc " + str(uvb_calc)) + _LOG.debug("uva_calc: %f uvb_calc: %f", uva_calc, uvb_calc) uva_index = uva_calc * sens_conf["UVAresp"] - _LOG.debug("uva_index " + str(uva_index)) uvb_index = uvb_calc * sens_conf["UVBresp"] - _LOG.debug("uvb_index " + str(uvb_index)) + _LOG.debug("uva_index: %f uvb_index: %f", uva_index, uvb_index) uv_index = (uva_index + uvb_index) / 2 return uv_index From a0f828e159b67d3c9181acd06f0f348d7bfccdfc Mon Sep 17 00:00:00 2001 From: Guy Martin Date: Sun, 11 Aug 2024 21:33:49 +0100 Subject: [PATCH 6/6] Fix mypy errors. --- mqtt_io/modules/sensor/veml6075.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mqtt_io/modules/sensor/veml6075.py b/mqtt_io/modules/sensor/veml6075.py index e377a0b9..14817d4f 100644 --- a/mqtt_io/modules/sensor/veml6075.py +++ b/mqtt_io/modules/sensor/veml6075.py @@ -60,7 +60,9 @@ def setup_module(self) -> None: self.sensor.set_shutdown(False) - def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: + def calculate_uv_index(self, sens_conf: ConfigType, \ + uva: float, uvb: float, uv_comp1: float, uv_comp2: float) -> float: + """ Calculate the UV index from received values. """ @@ -72,7 +74,7 @@ def calculate_uv_index(self, sens_conf, uva, uvb, uv_comp1, uv_comp2) -> float: uva_index = uva_calc * sens_conf["UVAresp"] uvb_index = uvb_calc * sens_conf["UVBresp"] _LOG.debug("uva_index: %f uvb_index: %f", uva_index, uvb_index) - uv_index = (uva_index + uvb_index) / 2 + uv_index: float = (uva_index + uvb_index) / 2.0 return uv_index def get_value(self, sens_conf: ConfigType) -> SensorValueType: