<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://revspace.nl/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Disasm</id>
	<title>RevSpace - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://revspace.nl/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Disasm"/>
	<link rel="alternate" type="text/html" href="https://revspace.nl/Special:Contributions/Disasm"/>
	<updated>2026-05-14T04:55:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22718</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22718"/>
		<updated>2019-10-01T22:53:28Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Completed&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[4] - (temperature in C) + 40&lt;br /&gt;
r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3..4] || r[2..3]=b[3..4] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || Reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || Changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || Reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range. Note that parameter bytes differ from those in the datasheet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || Returns sensor range (r[2..5])&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MHZ19&amp;diff=22717</id>
		<title>MHZ19</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MHZ19&amp;diff=22717"/>
		<updated>2019-10-01T22:52:58Z</updated>

		<summary type="html">&lt;p&gt;Disasm: Add link to MH-Z19B&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MHZ19&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19 CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Completed&lt;br /&gt;
   |Contact=bertrik&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This page is about the MH-Z19 CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor and some experiments done with it.&lt;br /&gt;
&lt;br /&gt;
This sensor gives a digital (serial) output of the CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; concentration in air, in parts-per-million (ppm).&lt;br /&gt;
It uses the optical measurement principle of measuring CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, which should be much more accurate than the inexpensive electro-chemical sensors you can find.&lt;br /&gt;
As far as I know, the optical measurement principle uses a broadband light-source to send some light through an air-sample.&lt;br /&gt;
The sensor then looks at the relative intensity of the light at two different frequencies.&lt;br /&gt;
The CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; gas inside the air absorbs light strongly at very specific wavelengths, allowing a determination of the concentration (ppm) of CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;.&lt;br /&gt;
This is then compensated for temperature (and pressure?) for increased accuracy.&lt;br /&gt;
See also [https://en.wikipedia.org/wiki/Nondispersive_infrared_sensor wikipedia] for this measurement principle.&lt;br /&gt;
A new measurement is started every 5 seconds, you can actually see a small amount of light coming out of the sensor while it&#039;s measuring.&lt;br /&gt;
&lt;br /&gt;
The MH-Z19 is the cheapest optical CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor I could find on AliExpress, about E22,-.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&lt;br /&gt;
UPDATE:&lt;br /&gt;
See also [https://geektimes.ru/post/285572/ this page on geektimes.ru] that explains some of the mysteries around this sensor that I didn&#039;t figure out.&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also: [[MH-Z19B]]&lt;br /&gt;
&lt;br /&gt;
== Status ==&lt;br /&gt;
The sensor works as intended, some software has been written to read the CO2 level and publish measurements it on MQTT.&lt;br /&gt;
It is also clear how to change the measurement range from 0-2000ppm to 0-5000ppm in software.&lt;br /&gt;
&lt;br /&gt;
Currently, it&#039;s running in Space3, publishing its value on a topic on MQTT, you can read this as follows:&lt;br /&gt;
  mosquitto_sub -h revspace.nl -t revspace/sensors/co2/# -v&lt;br /&gt;
&lt;br /&gt;
See also https://revgraph.bewaar.me/dashboard/db/all-co2&lt;br /&gt;
&lt;br /&gt;
Next steps:&lt;br /&gt;
* play a bit more with the MH-Z19B commands and document what works and what doesn&#039;t.&lt;br /&gt;
* in particular, look at the alarm output (officially this output is not supported) and try to find if it is possible to set the alarm limit setting. The alarm output seems to toggle low/high on reboot of the sensor, so at least the required hardware to pull it low / high is present inside the sensor module.&lt;br /&gt;
* figure out what the unknown value is that comes out of the sensor.&lt;br /&gt;
&lt;br /&gt;
== Hardware and reference data ==&lt;br /&gt;
See [http://www.winsen-sensor.com/products/ndir-co2-sensor/mh-z19.html the manufacturer MH-Z19 page].&lt;br /&gt;
&lt;br /&gt;
[https://forum.mysensors.org/topic/7761/mh-z19-teardown/2 Here&#039;s a teardown] of the MH-Z19 showing what it actually looks like inside.&lt;br /&gt;
Basically a light source and curved mirror focusing the light onto a photo diode with an optical filter tuned to a CO2 peak.&lt;br /&gt;
It has an STM32F103 processor inside, the same kind as the one on the famous &#039;blue pill&#039; board.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
See [https://github.com/bertrik/mhz19 this github repo] for code using this sensor with an ESP8266 board (WeMos D1 mini).&lt;br /&gt;
It publishes the CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; concentration to a MQTT topic every 5 seconds.&lt;br /&gt;
&lt;br /&gt;
To connect the Wemos to the MHZ19:&lt;br /&gt;
* GND to both the Wemos and MHZ19 GND pin&lt;br /&gt;
* 5V to the Wemos +5V pin and MHZ19 Vin pin&lt;br /&gt;
* Wemos D1 pin to the MHZ19 TX pin&lt;br /&gt;
* Wemos D2 pin to the MHZ19 RX pin&lt;br /&gt;
&lt;br /&gt;
It seems that support for this sensor was recently added to [https://www.esp8266.nu/index.php/ESPEasy ESPEasy].&lt;br /&gt;
&lt;br /&gt;
== Setting the measurement range ==&lt;br /&gt;
The following command sequences can be used to configure the measurement range of the sensor:&lt;br /&gt;
&lt;br /&gt;
* 1000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x03, 0xE8, 0x7B&lt;br /&gt;
* 2000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x8F&lt;br /&gt;
* 3000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x0B, 0xB8, 0xA3&lt;br /&gt;
* 5000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB&lt;br /&gt;
&lt;br /&gt;
== Experimentation ==&lt;br /&gt;
Normally, this sensor is read out using a command/response sequence over serial (9600,8N1).&lt;br /&gt;
The following commands are known from the datasheet:&lt;br /&gt;
* 0x86: gas concentration reading&lt;br /&gt;
* 0x87: calibrate zero point, I advise to AVOID SENDING THIS COMMAND, unless you know exactly what you are doing&lt;br /&gt;
* 0x88: calibrate span point, I advise to AVOID SENDING THIS COMMAND, unless you know exactly what you are doing&lt;br /&gt;
&lt;br /&gt;
The MH-Z19B datasheet additionally mentions to following commands:&lt;br /&gt;
* 0x79: ABC logic on/off (ABC = automatic baseline correction)&lt;br /&gt;
* 0x99: Sensor detection range setting, this command can be used to set the measurement range (e.g. 0-2000ppm or 0-5000ppm)&lt;br /&gt;
It appears that these commands work on the MH-Z19 too, although with a little different command layout.&lt;br /&gt;
Specifically, the range for command 0x99 is not put into bytes 3/4 but in bytes 6/7 of the command.&lt;br /&gt;
&lt;br /&gt;
This paragraph describes some experiments done to discover other commands than the ones mentioned in the datasheet.&lt;br /&gt;
=== command 0x00-0x30 ===&lt;br /&gt;
No response.&lt;br /&gt;
&lt;br /&gt;
=== command 0x31-0x6F ===&lt;br /&gt;
Untested.&lt;br /&gt;
&lt;br /&gt;
=== command 0x62 (device name / id) ===&lt;br /&gt;
According to the information at https://geektimes.ru/post/285572/&lt;br /&gt;
this command should return a kind of string, I couldn&#039;t get this to work unfortunately&lt;br /&gt;
&amp;lt;s&amp;gt;&lt;br /&gt;
Command 0x62 seems to query the sensor for a device name, either &amp;quot;KB200&amp;quot; or &amp;quot;MODBUS&amp;quot;&lt;br /&gt;
&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== command 0x70 ===&lt;br /&gt;
This command gives a response as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 9F 83 07 7D 00 00&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The value 0x9F83 (40835 in decimal) looks similar to the output of command 0x84.&lt;br /&gt;
&lt;br /&gt;
The value 0x077d (1917 in decimal) looks similar to the output of command 0x85.&lt;br /&gt;
&lt;br /&gt;
=== command 0x71, 0x72 ===&lt;br /&gt;
These commands give a response as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;00 00 00 00 00 00&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== command 0x73 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;9F 86 00 00 3D 40&amp;lt;/pre&amp;gt;&lt;br /&gt;
0x9F86 = 40838 decimal, looks similar to output of command 0x84.&lt;br /&gt;
0x3d40 = 15680 decimal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;07 8C 00 00 3D 04&amp;lt;/pre&amp;gt;&lt;br /&gt;
* 0x078c = 1932 decimal&lt;br /&gt;
* the 0x3D is temperature I think&lt;br /&gt;
* the 0x04 is the &#039;status&#039; byte&lt;br /&gt;
&lt;br /&gt;
=== command 0x80 - 0x83 ===&lt;br /&gt;
No response.&lt;br /&gt;
=== command 0x84 ===&lt;br /&gt;
This command gives a response as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;9F 88 00 00 00 00&amp;lt;/pre&amp;gt;&lt;br /&gt;
The 0x88 byte seems to go up and down a bit.&lt;br /&gt;
&lt;br /&gt;
Some other time&lt;br /&gt;
&amp;lt;pre&amp;gt;9F A1 00 80 00 00&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== command 0x85 (read CO2 + alarm level?) ===&lt;br /&gt;
This command gives a response as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 07 7D 01 D5 27 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The 0x1D5 value is the same as the CO2 concentration reading from command 0x86!&lt;br /&gt;
0x077D is equivalent to 1917 decimal.&lt;br /&gt;
0x2710 is equivalent to 10000 decimal exactly.&lt;br /&gt;
&lt;br /&gt;
Perhaps the 0x2710 value is the alarm value?&lt;br /&gt;
&lt;br /&gt;
=== Command 0x86 (read concentration) ===&lt;br /&gt;
Command 0x86 is the command to send to just read out the most recent ppm value.&lt;br /&gt;
&lt;br /&gt;
A response to command 0x86 typically looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0xFF CM HH LL TT SS Uh Ul CS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
where&lt;br /&gt;
* CM is the command repeated back&lt;br /&gt;
* HH/LL is the CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; ppm value, high/low part&lt;br /&gt;
* TT is the temperature in degrees Celcius, plus 40. For example, when temperature is 25 deg C, then TT = 0x41&lt;br /&gt;
* SS is some kind of status byte, this byte always has only one bit set!&lt;br /&gt;
* Uh/Ul is some unknown value, perhaps related to pressure? After booting the sensor, it starts out at 15000 exactly, then typically settles to about 10500.&lt;br /&gt;
According to the geektimes.ru page, this unknown value is related to the minimum CO2 uncorrected concentration measured in the past day. So I guess this is a relevant parameter from the ABC-algorithm.&lt;br /&gt;
* Cs is the checksum&lt;br /&gt;
&lt;br /&gt;
Values TT, SS and Uh/Ul are undocumented.&lt;br /&gt;
&lt;br /&gt;
=== command 0x89-0x8F ===&lt;br /&gt;
No response is returned, however command 0x8d seems to reset the sensor.&lt;br /&gt;
&lt;br /&gt;
=== command 0x99 (range) ===&lt;br /&gt;
According to the MH-Z19B datasheet, you can configure the measurement range by putting the desired range in byte 3 and 4.&lt;br /&gt;
However, unlike what the MH-Z19B datasheet says, you can set the range using the following command (in this case 0x07d0 = 2000 ppm in byte 6 and 7):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0xFF 0x01 0x99 0x00 0x00 0x00 0x07 0xD0 0x8F&lt;br /&gt;
          &amp;lt;cmd&amp;gt;               ^-range-^&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Experimenting a bit:&lt;br /&gt;
Sending all zeros gives a response of&lt;br /&gt;
&amp;lt;pre&amp;gt;01 00 00 00 00 00&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Log of MH-Z19 response at startup ==&lt;br /&gt;
Below is a log of the sensor response to the 0x86 measurement command while starting up.&lt;br /&gt;
The first couple of measurement seem to be invalid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     HH LL TT SS U1 U2&lt;br /&gt;
RAW: 00 80 47 01 3A 98 -&amp;gt; CO2 = 128 ppm&lt;br /&gt;
RAW: 07 D0 47 01 3A 98 -&amp;gt; 0x7d0 = 2000 decimal, this is the configured measurement range of the sensor with command 0x99&lt;br /&gt;
RAW: 00 05 47 01 3A 98 -&amp;gt; CO2 = 5 ppm&lt;br /&gt;
RAW: 01 2D 47 01 3A 98 -&amp;gt; CO2 = ..&lt;br /&gt;
RAW: 28 97 47 01 3A 98 -&amp;gt; CO2 = 10391&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 01 3A 98&lt;br /&gt;
RAW: 28 97 47 40 3A 98&lt;br /&gt;
RAW: 28 97 47 40 3A 98&lt;br /&gt;
RAW: 03 84 47 40 2B 43 -&amp;gt; first sample with U different from 0x3a98 (15000 decimal)&lt;br /&gt;
RAW: 03 85 47 40 2B 19&lt;br /&gt;
RAW: 03 86 47 40 2A F9&lt;br /&gt;
RAW: 03 87 47 40 2A E1 -&amp;gt; CO2 = 903 ppm, T = 31 deg C, Status = 0x40, Unknown = 10977&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first measurement shows a ppm value of 128, a temperature of 31 degrees C, a &amp;quot;status&amp;quot; byte of 01 and the &amp;quot;unknown&amp;quot; value of 0x3a98 (= 15000).&lt;br /&gt;
The second measurement shows a high ppm value of 2000 ppm (the max value within the ppm range).&lt;br /&gt;
The third measurement shows a low ppm value of 5 ppm.&lt;br /&gt;
The fourth measurement shows a ppm value of 301 ppm.&lt;br /&gt;
The fifth measurement shows a very high ppm value of 10391.&lt;br /&gt;
The final measurement shows a realistic indoors ppm value of 0x387 = 903 ppm.&lt;br /&gt;
The &amp;quot;unknown value&amp;quot; (byte 4/5) typically settles down to 10500 or so.&lt;br /&gt;
&lt;br /&gt;
So, it takes some time before the measurement stabilizes, proposed heuristic for a valid reading:&lt;br /&gt;
* &amp;quot;status byte&amp;quot; has to be 0x40&lt;br /&gt;
* &amp;quot;unknown value&amp;quot; has to be lower than 15000&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22716</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22716"/>
		<updated>2019-10-01T22:51:44Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[4] - (temperature in C) + 40&lt;br /&gt;
r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3..4] || r[2..3]=b[3..4] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || Reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || Changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || Reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range. Note that parameter bytes differ from those in the datasheet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || Returns sensor range (r[2..5])&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22715</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22715"/>
		<updated>2019-10-01T22:49:29Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3..4] || r[2..3]=b[3..4] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || Reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || Changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || Reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range. Note that parameter bytes differ from those in the datasheet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || Returns sensor range (r[2..5])&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22714</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22714"/>
		<updated>2019-10-01T22:45:42Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3..4] || r[2..3]=b[3..4] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range. Note that parameter bytes differ from those in the datasheet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || r[2..5] - sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22710</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22710"/>
		<updated>2019-10-01T17:13:22Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3..4] || r[2..3]=b[3..4] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || r[2..5] - sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22709</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22709"/>
		<updated>2019-10-01T17:07:19Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3] || ??? || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || r[2..5] - sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0 || || r[2..5] || Firmware version string? &amp;quot;0430&amp;quot; and &amp;quot;0443&amp;quot; observed&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1 || b[3] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA2 || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA3 || || r[2..3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xA4 || b[3..4], b[5..6] || r[2] || Setting bounds for DAC output, r[2]==1 on success&lt;br /&gt;
|-&lt;br /&gt;
| 0xA5 ||  || r[2..3], r[4..5] || Reading bounds for DAC output&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB || b[3], b[4] || r[2], r[3] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC || b[3] || r[2], r[3..6] || ???&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22708</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22708"/>
		<updated>2019-10-01T16:59:20Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Protocol (operation mode 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;br /&gt;
&lt;br /&gt;
For short, hereinafter this response will be called &amp;quot;ACK&amp;quot;: 0xFF, CMD, &#039;&#039;&#039;0x01&#039;&#039;&#039;, 0x00, 0x00, 0x00, 0x00, 0x00, CKSUM&lt;br /&gt;
&lt;br /&gt;
In the following table in Request and Response fields only the meaningful bytes will be shown.&lt;br /&gt;
For example, b[3] is the first parameter byte and b[3..4] is the first two parameter bytes forming a word. &amp;quot;???&amp;quot; means &amp;quot;isn&#039;t investigated yet&amp;quot;, an empty field means &amp;quot;no parameters&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Request !! Response !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || b[3] || no response || Changes operation mode and performs MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || b[3] || ACK || Turns ABC logic on or off (b[3] == 0xA0 - on, 0x00 - off)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D ||  || r[7] || Returns ABC logic status (1 - enabled, 0 - disabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || b[3], b[4..5] || r[2..3] || Sets timer cycle length (b[4..5]) in seconds and returns current value. b[3] should be 2 to update the length&lt;br /&gt;
|-&lt;br /&gt;
| 0x80..0x83 || b[3], b[4..7] || no response || Writes one double word to the 1024-byte configuration area (offset = b[3] + (CMD - 0x80) * 256).&lt;br /&gt;
Command 0x80 with b[3]==0 clears the whole configuration area. On timeout this configuration area will be written to flash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. r[2..3] is a half of the raw light sensor value. r[4..5] is constant 32000.&lt;br /&gt;
r[6..7] is different in different versions of firmware: bit field or maximum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || || r[2..3], r[4..5], r[6..7] || Returns &amp;quot;raw&amp;quot; values. b[2..3] is smoothed temperature ADC value. b[4..5] is CO2 level before clamping.&lt;br /&gt;
b[6..7] is minimum light ADC value&lt;br /&gt;
|-&lt;br /&gt;
| 0x86 || || r[2..3], r[4], r[5], r[6], r[7] || r[2..3] - &amp;quot;final&amp;quot; CO2 level. r[6] and r[7] - if ABC turned on - counter in &amp;quot;ticks&amp;quot; within a calibration cycle and the number of performed calibration cycles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87 || b[5], b[6], b[7] || r[2], r[3..6] || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || b[3] || ??? || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D || || no response || MCU reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x90..0x93 || b[3] || r[2..5] || reads a double word from configuration area by offset (b[3] + (CMD - 0x90) * 256)&lt;br /&gt;
|-&lt;br /&gt;
| 0x94 || b[3], b[4..6] || r[2..6] || changes 3 bytes (b[4..6]) of &amp;quot;id string&amp;quot; with offset (3*(b[3] - 1))&lt;br /&gt;
|-&lt;br /&gt;
| 0x95 || b[3] || r[2], r[3], r[4..6] || reads 3 bytes of &amp;quot;id string&amp;quot; (b[4..6]) with offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x99 || b[4..7] || ACK || Sets sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A || b[4] || ACK || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B || || r[2..5], r[6], r[7] || r[2..5] - sensor range&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C || || r[2..5], r[6]=1 || ???&lt;br /&gt;
|-&lt;br /&gt;
| 0x?? || ??? || ??? || &lt;br /&gt;
|-&lt;br /&gt;
| 0x?? || ??? || ??? || &lt;br /&gt;
|-&lt;br /&gt;
| 0x?? || ??? || ??? || &lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22707</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22707"/>
		<updated>2019-10-01T16:12:38Z</updated>

		<summary type="html">&lt;p&gt;Disasm: /* Operation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when MH-Z19B is exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22706</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22706"/>
		<updated>2019-10-01T16:11:13Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
As stated in the datasheet, MH-Z19B should be kept away from heat. Experiment showed that the light sensor inside MH-Z19B stops working when exposed to an air stream from a heat gun.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-heating.png]]&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-heating.png&amp;diff=22705</id>
		<title>File:MH-Z19B-heating.png</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-heating.png&amp;diff=22705"/>
		<updated>2019-10-01T16:09:11Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B heating response&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22704</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22704"/>
		<updated>2019-10-01T16:01:04Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
Datasheet: https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;br /&gt;
&lt;br /&gt;
== Operation ==&lt;br /&gt;
&lt;br /&gt;
Firmware turns on lamp for 400 ms and measures sensor response along with the voltage of the voltage reference. This happens again and again in cycle. Default cycle length is 5s.&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-operation.png]]&lt;br /&gt;
&lt;br /&gt;
Firmware measures only a part of the response signal: 180..980 ms interval in 10ms steps. It integrates 180..680 ms interval and removes constant component (1.026V on the image above) based on values from the 930..980 ms interval. Obtained result after some smoothing is available (divided by 2) via command 0x84. This value is used for subsequent computations.&lt;br /&gt;
&lt;br /&gt;
Another firmware turns on lamp for 500 ms and measures 450..500 ms and 1800..1850 ms intervals, then uses the second one to remove constant component from the first one.&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
Sensor provides UART, PWM and analog output interfaces. Both PWM and analog output provide CO2 measurement result limited by some bounds.&lt;br /&gt;
UART interface implements one of several protocols. Default protocol (&amp;quot;operation mode 0&amp;quot;) is the richest one.&lt;br /&gt;
&lt;br /&gt;
=== Protocol (operation mode 0) ===&lt;br /&gt;
&lt;br /&gt;
All commands and responses are 9 bytes in size. Most of the commands have a response, but some -- don&#039;t. Response contains command code, both command and response contain checksum value.&lt;br /&gt;
&lt;br /&gt;
Command format: 0xFF, 0x01, CMD, (5 bytes of parameters), CKSUM&lt;br /&gt;
&lt;br /&gt;
Response format: 0xFF, CMD, (6 bytes of response), CKSUM&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-operation.png&amp;diff=22703</id>
		<title>File:MH-Z19B-operation.png</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-operation.png&amp;diff=22703"/>
		<updated>2019-10-01T15:31:59Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B signals (lamp and light sensor)&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22702</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22702"/>
		<updated>2019-10-01T15:13:30Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Partial schematics:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-schematics.png|800px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-schematics.png&amp;diff=22701</id>
		<title>File:MH-Z19B-schematics.png</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-schematics.png&amp;diff=22701"/>
		<updated>2019-10-01T15:11:59Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B schematics&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22700</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22700"/>
		<updated>2019-10-01T14:32:08Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Teardown ==&lt;br /&gt;
&lt;br /&gt;
Back side of the MH-Z19B sensor with unlabeled SWD pads on the right:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Front side of the (4-layer) PCB:&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-pcb.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-markings.jpg|400px]]&lt;br /&gt;
[[File:MH-Z19B-pcb-tracks.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb-tracks.jpg&amp;diff=22699</id>
		<title>File:MH-Z19B-pcb-tracks.jpg</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb-tracks.jpg&amp;diff=22699"/>
		<updated>2019-10-01T14:30:17Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B PCB tracks&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb-markings.jpg&amp;diff=22698</id>
		<title>File:MH-Z19B-pcb-markings.jpg</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb-markings.jpg&amp;diff=22698"/>
		<updated>2019-10-01T14:28:12Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B PCB markings&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb.jpg&amp;diff=22697</id>
		<title>File:MH-Z19B-pcb.jpg</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-pcb.jpg&amp;diff=22697"/>
		<updated>2019-10-01T14:25:49Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MH-Z19B PCB front side&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22696</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22696"/>
		<updated>2019-10-01T14:00:33Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
[[File:MH-Z19B-back.jpg|thumb|Back side of the MH-Z19B sensor with unlabeled SWD pads on the right]]&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD test pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=File:MH-Z19B-back.jpg&amp;diff=22695</id>
		<title>File:MH-Z19B-back.jpg</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=File:MH-Z19B-back.jpg&amp;diff=22695"/>
		<updated>2019-10-01T13:57:51Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Back side of the MH-Z19B sensor&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22694</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22694"/>
		<updated>2019-10-01T13:52:18Z</updated>

		<summary type="html">&lt;p&gt;Disasm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Picture=mhz19.jpg&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
MH-Z19B is an updated version of the [[MHZ19|MH-Z19]] sensor.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* STM32F051K86 MCU&lt;br /&gt;
* Unknown analog light+temperature sensor&lt;br /&gt;
* Two 3.3V regulators&lt;br /&gt;
* 1.5V voltage reference&lt;br /&gt;
* Lamp&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
MCU firmware can be easily dumped through SWD test pads. Pinout:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Pin !! Signal&lt;br /&gt;
|-&lt;br /&gt;
| 1 (square) || 3V3&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GND&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SWDIO&lt;br /&gt;
|-&lt;br /&gt;
| 4 || SWCLK&lt;br /&gt;
|-&lt;br /&gt;
| 5 || RESET (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, bootloader asks for a firmware update during the first 20s of startup.&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
	<entry>
		<id>https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22693</id>
		<title>MH-Z19B</title>
		<link rel="alternate" type="text/html" href="https://revspace.nl/wiki/index.php?title=MH-Z19B&amp;diff=22693"/>
		<updated>2019-10-01T13:18:02Z</updated>

		<summary type="html">&lt;p&gt;Disasm: Created page with &amp;quot;  {{Project    |Name=MH-Z19B    |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor    |Status=Initializing    |Contact=Disasm   }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;  {{Project&lt;br /&gt;
   |Name=MH-Z19B&lt;br /&gt;
   |Omschrijving=Some research into the MH-Z19B CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; sensor&lt;br /&gt;
   |Status=Initializing&lt;br /&gt;
   |Contact=Disasm&lt;br /&gt;
  }}&lt;/div&gt;</summary>
		<author><name>Disasm</name></author>
	</entry>
</feed>