-
Notifications
You must be signed in to change notification settings - Fork 37
PWM support.
PWM is supported at version 3.0.0 and later.
According to the data sheet, the MH_Z19 sensor module periodically provide a CO2 concentration value in the manner they called "PWM" as follows:
- cycle The signal is started with a 2 millisecond high-level of Cycle start mark, and following high levels duration which is 500 or fewer times of 2millisecond, then following the low-level signals until 1000 millisecond from the end of Cycle start mark, then following 2millisecond low level. Illustrated as follows:
<-><---------------------- 1000ms ---------------------------------------------------------------><->Next cycle
2ms high-level of Cycle start mark and following N (500 or less) 2ms high-levels 2ms low-level of Cycle end mark
_|¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________ __ |¯|
2ms 2ms
With N as the number of 2ms high-level signal (not include start mark) is in a range of 0 - 500.
- The number of the 2ms high-level indicate co2 concentration as follows:
co2 concentration = N * current setting range /500
The range setting can be any of 2000, 5000, 10000.
Connect with 3 wires as follows:
RPi | MH_Z19 |
---|---|
5V | Vin |
GND | GND |
Any gpio, 12(BCM) is recommended) | PWM |
- with --pwm, using default gpio(12 by BCM) and range(5000)
pi@raspberrypi:~/mh-z19 $ python -m mh_z19 --pwm
{'co2': 540}
- To specify gpio and/or range, use --pwm_gpio and/or --pwm_range
python -m mh_z19 --pwm --pwm_gpio 12 --pwm_range 2000
{'co2': 220}
- Return timeout error as following in case can't catch any PWM signal.
pi@raspberrypi:~/mh-z19 $ python -m mh_z19 --pwm --pwm_gpio 13
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/home/pi/mh-z19/mh_z19.py", line 324, in <module>
print read_from_pwm(gpio=args.pwm_gpio, range=args.pwm_range, )
File "/home/pi/mh-z19/mh_z19.py", line 212, in read_from_pwm
raise GPIO_Edge_Timeout("gpio {} edge timeout".format(gpio))
__main__.GPIO_Edge_Timeout: gpio 13 edge timeout
The possible cause of the above timeout is cabling problem including the wrong pin specification, or a physical problem of the sensor module.
- The gpio pin number is specified by the BCM system. For example, the pin GPIO 12 is specified as the 5th pin from the bottom right to top.
pi@raspberrypi:~/mh-z19 $ gpio readall
+-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5v | | |
| 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | |
| 4 | 7 | GPIO. 7 | IN | 0 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 |
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
| 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
| 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
| 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 |
| | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 |
| 0 | 30 | SDA.0 | ALT0 | 1 | 27 || 28 | 1 | ALT0 | SCL.0 | 31 | 1 |
| 5 | 21 | GPIO.21 | IN | 0 | 29 || 30 | | | 0v | | |
| 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | <= GPIO 12 by BCM system
| 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
| 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
| 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
| | | 0v | | | 39 || 40 | 1 | IN | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+
Import mh_z19 and call read_from_pwm as follows:
pi@raspberrypi:~/mh-z19 $ python
Python 2.7.16 (default, Oct 10 2019, 22:02:15)
[GCC 8.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mh_z19
>>> mh_z19.read_from_pwm()
{'co2': 620}
>>> mh_z19.read_from_pwm(range=2000)
{'co2': 244}
>>> mh_z19.read_from_pwm(gpio=12, range=2000)
{'co2': 244}
>>>
The function is defined as follows:
def read_from_pwm(gpio=12, range=5000):
- Simple to use
- Only 3 cables are required, despite 4 cables are necessary by the serial protocol.
- No need to prepare any additional drivers and to stop/start any services.
- Can run without root privilege without any settings.
- Slow, in about 1 second necessary to get data.
- Low resolution
Since version 3.1.5, using gpio library has changed from the RPi.GPIO to the gpiozero because of an issue report #53 which reports that RPi.GPIO is not working on the RPi 5.
gpiozero's API is quite different from that of other gpio libraries; it is not for reading whether a specific GPIO is turned on or off, or waiting for it to rise or fall, instead gpiozero has many classes for specific devices like LED, Motion Sensor, and so on, and has many hi level functionalities to handle these devices. For that reason, at first I was confused as to how to migrate from RPi.GPIO to gpiozero.
Fortunately, I was able to find the document of the Migrating from RPi.GPIO right away, but I saw soon that it was a quirky article that said, "When you used RPi.GPIO to read values, use Button class after migrating to gpiozero."
Therefore, for the purpose of making it easier for kind reviewers to see the migration details, and for the sake of reference for new migraters who feel the same confusion as me, I commented out old lines and added new lines in the same place as here. Any comments on this would be greatly appreciated, thx!