From 4556023a0c351e90e2d070f068f848c6865a929f Mon Sep 17 00:00:00 2001 From: Fredrik Strupe Date: Tue, 15 Nov 2022 12:14:07 +1100 Subject: [PATCH] sensor/mhz19: Add driver for MH-Z19 (CO2 sensor). Originally by Fredrik Strupe, updated for micropython-lib. Signed-off-by: Jim Mussared --- micropython/drivers/sensor/mhz19/manifest.py | 3 ++ micropython/drivers/sensor/mhz19/mhz19.py | 48 ++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 micropython/drivers/sensor/mhz19/manifest.py create mode 100644 micropython/drivers/sensor/mhz19/mhz19.py diff --git a/micropython/drivers/sensor/mhz19/manifest.py b/micropython/drivers/sensor/mhz19/manifest.py new file mode 100644 index 00000000..0647201b --- /dev/null +++ b/micropython/drivers/sensor/mhz19/manifest.py @@ -0,0 +1,3 @@ +metadata(description="Driver for MH-Z19 CO2 sensor.", version="0.1.0") + +module("mhz19.py", opt=3) diff --git a/micropython/drivers/sensor/mhz19/mhz19.py b/micropython/drivers/sensor/mhz19/mhz19.py new file mode 100644 index 00000000..40eff7ed --- /dev/null +++ b/micropython/drivers/sensor/mhz19/mhz19.py @@ -0,0 +1,48 @@ +# MH-Z19 CO2 sensor driver for MicroPython. +# MIT license; Copyright (c) 2018 Fredrik Strupe + +import machine +import utime + + +class TimeoutError(Exception): + pass + + +class MHZ19: + """MH-Z19 CO2 sensor driver""" + + def __init__(self, pin, max_value=5000): + """ + Args: + pin: the pin that the PWM pin on the MH-Z19 is connected to. + max_value: upper bound of measuring range. usually 2000 or 5000. + """ + self.pin = pin + self.max_value = max_value + + def _wait_on_condition(self, cond, timeout=5000): + start = utime.ticks_ms() + while not cond(): + if utime.ticks_diff(utime.ticks_ms(), start) > timeout: + raise TimeoutError + + def pwm_read(self): + """Read CO2 value via PWM pin. + + Reading usually takes 1-2 seconds. + + Returns: + CO2 value in ppm (parts per million), with an accuracy of + ±(50 + result * 0.05) ppm. + Raises: + TimeoutError: if the reading takes more than 5 seconds. + """ + # Wait until a new cycle starts + self._wait_on_condition(lambda: self.pin.value() == 0) + + # Measure high and low duration during cycle + t_h = machine.time_pulse_us(self.pin, 1, 1500000) + t_l = machine.time_pulse_us(self.pin, 0, 1500000) + + return self.max_value * (t_h - 2000) / (t_h + t_l - 4000)