Difference between revisions of "CO2MeterHacking"

From RevSpace
Jump to navigation Jump to search
m
(It just works and looks nice!)
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
   {{Project
 
   {{Project
 
   |Name=CO2MeterHacking
 
   |Name=CO2MeterHacking
   |Status=Initializing
+
  |Picture=Voltcraft-c100.jpg
 +
   |Status=Completed
 
   |Contact= bertrik
 
   |Contact= bertrik
 
   }}
 
   }}
 +
 +
'''status: it works'''
 +
We found out that the G, C, D, V signals are routed internally to the RJ45-plug, so there's actually no need to open the CO-100 and solder a connector on the G, C, D, V lines. 
  
 
== Introduction ==
 
== Introduction ==
Line 9: Line 13:
  
 
This particular CO2-sensor is present in the klusbunker at RevSpace and is currently used to control the ventilation in a crude manner (by monitoring the warning LEDs on the display module).
 
This particular CO2-sensor is present in the klusbunker at RevSpace and is currently used to control the ventilation in a crude manner (by monitoring the warning LEDs on the display module).
Having the CO2 ppm value available as a number allows for nice things such as logging the levels over time, announce them on IRC, show them on the LedBanner , etc.
+
Having the CO2 ppm value available as a number allows for nice things such as logging the levels over time, announce them on IRC, show them on the [[LedBanner]] , etc.
  
The user manual of the Voltcraft CO-100 says "Attention! The RJ45 connection (see chapter 7, item „K“) must not be used. The connection is only intended for the manufacturer". Of course, a claim like that can only be interpreted as a  challenge! :)
+
The user manual of the Voltcraft CO-100 says
 +
"Achtung!
 +
Der RJ45-Anschluss (siehe Kapitel 7, Position „K“) darf nicht verwendet werden. Der Anschluss ist nur für den Hersteller vorgesehen."
 +
Of course, a claim like that can only be interpreted as a  challenge! :)
  
== Investigation ==
+
== Investigation & findings ==
 
[[File:Co-100_overview.jpg|thumb|right|CO-100 internals]]
 
[[File:Co-100_overview.jpg|thumb|right|CO-100 internals]]
 
The CO2 sensor inside the CO-100 (in the left of the picture) has a sticker saying ZGw063RY.
 
The CO2 sensor inside the CO-100 (in the left of the picture) has a sticker saying ZGw063RY.
Googling for this number reveals a CO2 module that looks just like the Voltcraft CO-100, so it appears that the CO-100 is basically just a rebranded [http://www.zyaura.com/products/ZGw063.asp ZyAura ZGw063RY] module.
+
Googling for this number reveals a CO2 module that looks just like the Voltcraft CO-100, so it appears that the CO-100 is basically a rebranded [http://www.zyaura.com/products/ZGw063.asp ZyAura ZGw063RY] module.
  
 
The CO-100 seems to miss a bunch of components that can be mounted on the PCB, close to the RJ45 connection (most likely an RS232 chip with charge pump capacitors).
 
The CO-100 seems to miss a bunch of components that can be mounted on the PCB, close to the RJ45 connection (most likely an RS232 chip with charge pump capacitors).
 
[[File:Co-100.jpg|thumb|left|components around the RJ45 connector]]
 
[[File:Co-100.jpg|thumb|left|components around the RJ45 connector]]
  
=== CO2 sensor ===
+
The CO2 sensor in the CO-100 is a [http://www.zyaura.com/products/ZG_module.asp ZyAura ZG-01 module].
The CO2 sensor in the CO-100 looks very much like the [http://www.zyaura.com/products/ZG_module.asp ZyAura ZG-01 module].
+
This sensor uses the ZyAura protocol, which vaguely resembles SPI, see [[File:ZyAura_CO2_Monitor_Carbon_Dioxide_ZG01_Module_english_manual-1.pdf|ZG01 CO2 Monitor Module user manual]].
The ZG-01 sensor uses the ZyAura protocol, which vaguely resembles SPI, see [[File:ZyAura_CO2_Monitor_Carbon_Dioxide_ZG01_Module_english_manual-1.pdf|ZG01 CO2 Monitor Module user manual]].
+
 
 +
On the bottom left of the PCB is a set of pads that are marked with G, C, D, V, meaning Ground, Clock, Data, Voltage of the ZG01 sensor.
 +
The voltage level on the clock and data pins is 3.3V (the voltage on V pin is 3.3V too).
 +
 
 +
The ZG-01 sends 5-byte frames containing measurement values:
 +
* byte 0 is an identifier for the measurement item, e.g. whether it is a CO2 ppm value or a temperature.
 +
* byte 1 and 2 contain the value of the item (byte 1 is the MSB, byte 2 is the LSB)
 +
* byte 3 is a checksum over bytes 0-2, just the sum modulo 256.
 +
* byte 4 is always 0x0D
 +
Besides the CO2 ppm value and temperature, it also sends various other (so far unknown) measurement items.
 +
 
 +
Measurement items encountered so far:
  
Other sensors on the market:
+
{| class="wikitable"
* [http://www.ge-mcs.com/en/co2/co2-modules/6615.html Telaire T6613/T6615]
+
! Item
* [http://www.winsensor.com/en/ProShow223.html Winsensor MH-Z14], looks nearly identical to the Telaire module
+
! Value
 +
! Remark
 +
|-
 +
| 0x41 'A' || 3290 || Relative humidity in units of 0.01%
 +
|-
 +
| 0x42 'B' || 4708 || Temperature in Kelvin (unit of 1/16th K)
 +
|-
 +
| 0x43 'C' || 2964 || ?
 +
|-
 +
| 0x46 'F' || 6882 || Temperature in degrees Fahrenheit (unit of 0.01)?
 +
|-
 +
| 0x4F 'O' || 7754 || ?
 +
|-
 +
| 0x50 'P' || 857 || CO2 concentration in ppm
 +
|-
 +
| 0x52 'R' || 10438 || Barometric pressure?
 +
|-
 +
| 0x56 'V' || 10443 || Barometric pressure?
 +
|-
 +
| 0x57 'W' || 7880 || ?
 +
|-
 +
| 0x6D 'm' || 2559 || Seems to always have same value
 +
|-
 +
| 0x6E 'n' || 17146 || ?
 +
|-
 +
| 0x71 'q' || 855 || Always close to value of item 0x50
 +
|}
 +
 
 +
== Integration into Revspace infrastructure ==
 +
Measurements of the CO2 meter are integrated into the existing infrastructure as follows:
 +
* The G, C, D, V lines from the ZG-01 have been broken out using a standard 2.54mm pitch header
 +
* The ZG-01 ground, clock and data lines are attached to an arduino which decodes the ZG-01 protocol
 +
* Also attached to the arduino is an NRF24L01+ wireless transceiver, through which the CO2 measurement is sent to a central receiver (the one that also handles the Nomz-bell, Skip-button, etc.).
 +
 
 +
== Hardware ==
 +
The ZG-01 module and NRF24L01+ transceiver are connected to the Arduino as follows:
 +
{| class="wikitable"
 +
! Arduino
 +
! Module
 +
! Remark
 +
|-
 +
| D2 || 'C' || ZG01 clock signal
 +
|-
 +
| D3 || 'D' || ZG01 data signal
 +
|-
 +
| GND || 1 || NRF ground
 +
|-
 +
| 3V3 || 2 || NRF power
 +
|-
 +
| D8 || 3 || NRF CE
 +
|-
 +
| D9 || 4 || NRF CSN
 +
|-
 +
| D13 || 5 || NRF SCK
 +
|-
 +
| D11 || 6 || NRF MOSI
 +
|-
 +
| D12 || 7 || NRF MISO
 +
|-
 +
| - || 8 || NRF IRQ - not connected
 +
|}
  
 
== Software ==
 
== Software ==
Some software has been written (so far untested) to interface an arduino to the clock and data lines of the ZG-01.
+
The basic function of the software on the arduino is to wait until a CO2 measurement is received from the ZG-01, then send it using the wireless transceiver.
It consists of an finite state machine (FSM) that processes the data line on each falling edge of the clock line.
 
The FSM assumes that a new frame is starting when the time between bits is more than 3 milliseconds.
 
  
Arduino pin mapping:
+
The source code can be found [https://github.com/bertrik/co2sensor on github].
* digital pin 2 (PD2): ZG01 clock signal
 
* digital pin 3 (PD3): ZG01 data signal
 
  
The source code can be found [https://github.com/bertrik/co2sensor on github].
+
=== ZG-01 decoding ===
 +
The ZG-01 protocol is decoded using a simple state machine.
 +
On each falling edge of the clock line, a sample of the data line is taken until a total of 40 bits is received.
 +
If the time between a bit and the previous bit is longer than 2 milliseconds, it is assumed that a new 5-byte frame has started.
 +
 
 +
=== Wireless protocol ===
 +
To control the NRF24L01+ wireless transceiver, we use the
 +
[https://github.com/gcopeland/RF24a gcopeland fork of the RF24 library].
 +
This library has several important fixes over the original RF24 library (and is used in the receiver as well).
  
== Future work ==
+
The wireless message consist of 7 bytes:
Possible further investigation:
+
* 0x06 "CO_2" <MSB> <LSB> for the CO2 concentration message (in ppm)
* Sniff the ZG01 SPI connection, e.g. using a bus pirate, Arduino or a Raspberry pi
+
* 0x06 "HUMI" <MSB> <LSB> for the relative humidity message (in units of 0.01%)
** figure out if the CO2 sensor SPI message uses HEX or BCD format
 
* Check if the pads in the lower-left of the PCB say "G C D V", that could be the Ground, Clock, Data, Vcc lines from/to the ZG-01 sensor, just like in the user manual document.
 
  
== Idea ==
+
=== Heat map generation ===
A practical solution could be as follows:
+
Flok420 is generating heat maps. [http://keetweej.vanheusden.com/revspace/co2.php keetweej.vanheusden.com/revspace/co2.php]
* Wire the Vcc, Gnd, Data, Clock lines of the ZG-01 to the unused pads around the RJ45 connector, such that these signals become available on the RJ45 connector;
+
He also has a large data set you might be able to use for your own data-mining purpose.
* Attach an arduino (pro mini) through a cable on the RJ45. The arduino takes power from the RJ45 and decodes the SPI-like signals from the ZG-01.
 
* Connect an NRF24L01+ module to the arduino SPI port and send the CO2/temperature frames over the air to a central NRF24L01+ receiver (e.g. the one which handles the SkipButton, Nomz Bell).
 
* From there on, the CO2/temperature data can be further processed (to be logged, sent to the ledbanner, announced on IRC, etc.)
 
  
This requires only minimal modifications to the CO-100 modules itself and makes uses of the existing wireless infrastructure.
+
== Future work ==
 +
Future investigation:
 +
* consider powering the Arduino from the 3.3V line coming from the CO2 sensor
 +
* investigate further into the unknown measurement items sent by the ZG01
 +
* make a nicer case for the arduino+nrf module

Revision as of 10:37, 28 March 2016

Project CO2MeterHacking
Voltcraft-c100.jpg
Status Completed
Contact bertrik
Last Update 2016-03-28

status: it works We found out that the G, C, D, V signals are routed internally to the RJ45-plug, so there's actually no need to open the CO-100 and solder a connector on the G, C, D, V lines.

Introduction

This project is about hacking the Voltcraft CO-100 CO2-sensor, such that we can read the exact ppm value as displayed on the LCD.

This particular CO2-sensor is present in the klusbunker at RevSpace and is currently used to control the ventilation in a crude manner (by monitoring the warning LEDs on the display module). Having the CO2 ppm value available as a number allows for nice things such as logging the levels over time, announce them on IRC, show them on the LedBanner , etc.

The user manual of the Voltcraft CO-100 says "Achtung! Der RJ45-Anschluss (siehe Kapitel 7, Position „K“) darf nicht verwendet werden. Der Anschluss ist nur für den Hersteller vorgesehen." Of course, a claim like that can only be interpreted as a challenge! :)

Investigation & findings

CO-100 internals

The CO2 sensor inside the CO-100 (in the left of the picture) has a sticker saying ZGw063RY. Googling for this number reveals a CO2 module that looks just like the Voltcraft CO-100, so it appears that the CO-100 is basically a rebranded ZyAura ZGw063RY module.

The CO-100 seems to miss a bunch of components that can be mounted on the PCB, close to the RJ45 connection (most likely an RS232 chip with charge pump capacitors).

components around the RJ45 connector

The CO2 sensor in the CO-100 is a ZyAura ZG-01 module. This sensor uses the ZyAura protocol, which vaguely resembles SPI, see File:ZyAura CO2 Monitor Carbon Dioxide ZG01 Module english manual-1.pdf.

On the bottom left of the PCB is a set of pads that are marked with G, C, D, V, meaning Ground, Clock, Data, Voltage of the ZG01 sensor. The voltage level on the clock and data pins is 3.3V (the voltage on V pin is 3.3V too).

The ZG-01 sends 5-byte frames containing measurement values:

  • byte 0 is an identifier for the measurement item, e.g. whether it is a CO2 ppm value or a temperature.
  • byte 1 and 2 contain the value of the item (byte 1 is the MSB, byte 2 is the LSB)
  • byte 3 is a checksum over bytes 0-2, just the sum modulo 256.
  • byte 4 is always 0x0D

Besides the CO2 ppm value and temperature, it also sends various other (so far unknown) measurement items.

Measurement items encountered so far:

Item Value Remark
0x41 'A' 3290 Relative humidity in units of 0.01%
0x42 'B' 4708 Temperature in Kelvin (unit of 1/16th K)
0x43 'C' 2964 ?
0x46 'F' 6882 Temperature in degrees Fahrenheit (unit of 0.01)?
0x4F 'O' 7754 ?
0x50 'P' 857 CO2 concentration in ppm
0x52 'R' 10438 Barometric pressure?
0x56 'V' 10443 Barometric pressure?
0x57 'W' 7880 ?
0x6D 'm' 2559 Seems to always have same value
0x6E 'n' 17146 ?
0x71 'q' 855 Always close to value of item 0x50

Integration into Revspace infrastructure

Measurements of the CO2 meter are integrated into the existing infrastructure as follows:

  • The G, C, D, V lines from the ZG-01 have been broken out using a standard 2.54mm pitch header
  • The ZG-01 ground, clock and data lines are attached to an arduino which decodes the ZG-01 protocol
  • Also attached to the arduino is an NRF24L01+ wireless transceiver, through which the CO2 measurement is sent to a central receiver (the one that also handles the Nomz-bell, Skip-button, etc.).

Hardware

The ZG-01 module and NRF24L01+ transceiver are connected to the Arduino as follows:

Arduino Module Remark
D2 'C' ZG01 clock signal
D3 'D' ZG01 data signal
GND 1 NRF ground
3V3 2 NRF power
D8 3 NRF CE
D9 4 NRF CSN
D13 5 NRF SCK
D11 6 NRF MOSI
D12 7 NRF MISO
- 8 NRF IRQ - not connected

Software

The basic function of the software on the arduino is to wait until a CO2 measurement is received from the ZG-01, then send it using the wireless transceiver.

The source code can be found on github.

ZG-01 decoding

The ZG-01 protocol is decoded using a simple state machine. On each falling edge of the clock line, a sample of the data line is taken until a total of 40 bits is received. If the time between a bit and the previous bit is longer than 2 milliseconds, it is assumed that a new 5-byte frame has started.

Wireless protocol

To control the NRF24L01+ wireless transceiver, we use the gcopeland fork of the RF24 library. This library has several important fixes over the original RF24 library (and is used in the receiver as well).

The wireless message consist of 7 bytes:

  • 0x06 "CO_2" <MSB> <LSB> for the CO2 concentration message (in ppm)
  • 0x06 "HUMI" <MSB> <LSB> for the relative humidity message (in units of 0.01%)

Heat map generation

Flok420 is generating heat maps. keetweej.vanheusden.com/revspace/co2.php He also has a large data set you might be able to use for your own data-mining purpose.

Future work

Future investigation:

  • consider powering the Arduino from the 3.3V line coming from the CO2 sensor
  • investigate further into the unknown measurement items sent by the ZG01
  • make a nicer case for the arduino+nrf module