Because of the needs of one of our projects, we have to extract data from a CO2 sensor. We got this one, 7722 from AZ Instrument :
This device is a simple CO2 sensor. It gives you a measure result each second. It measures too the temperature and the relative humidity. You can set an alarm (that can activate a relay output) and it has a RS232 port to extract the measures.
This serial port is the reason of this article. You have no info about it in the manufacturer manual. Just that it sends the data each 2 seconds at 9600 bps, 8 bits of data, 1 stop bit and none flow control (classic 8N1). There are an optional cable and software to use it. We didn’t have that cable nor software.
Hardware needs
The RS-232 port in the 7722 AZ is “special”. The physical port is a 3.5mm jack and it doesn’t generate any signal. It just has an optocoupler that switchs (and inverts the signal) with the different pulses associated to a serial communication at 9600 bps. The device only transmits. It has no Rx line. With these particular characteristics, we decide to build our own cable adaptor.
Here we have a simple schema:
As you can see, we need to supply the voltage to get the signal. To make that, we use a pull-up resistor in the signal line, to be switched with GND. The value of the resistor could be changed. If you have problems, you could try to change 5k for 1k ohm. Keep in mind that this simple circuit will not generate a pure RS232 signal (-12V to +12V). This will generate a signal between 0 and Vcc (5V in our case).
Now, we need some kind of adaptor to provide any voltage to Vdd and to convert the signal to a computer. Luckily there are a lot of very cheap USB to TTL serial adaptors that fit like a charm in this case. You can get any of them for a few Euros/Dollars.
In the example model we can check the available lines:
- DTR. Control line. Unused for us in this porject
- RXD. Receive line. We’ll conect the TX line of the peer at this line
- TXD. Transmision line. As our device only transmits, this line is unused for us in this project
- +5V. This will be our Vcc line
- GND. Nothing to comment, I guess
- 3V3. Another alternative Vcc line
So the conections we have to make are clear:
Vcc -> +5V
Rx -> RXD
Gnd -> GND
The application
The application example was made in Python 3. So it’s mandatory to have Python3 installed in our computer.
# ____ # ____ Copyright 2021 BlackDevice @ IPGLOBAL # ____ Author: Francisco Dominguez # ____ import serial import time SERIAL_PORT='/dev/ttyUSB1' PARAM_ERR=-1000 # parse the result line read from the sensor def parse_line(src): tkns = src.split(':') if (len(tkns) < 3): return PARAM_ERR, PARAM_ERR, PARAM_ERR # parse co2 if (len(tkns[0]) < 7 and tkns[0] != ord('C')): return PARAM_ERR, PARAM_ERR, PARAM_ERR co2 = int(tkns[0][1:len(tkns[0])-3]) # parse temp if (len(tkns[1]) < 5 and tkns[1] != ord('T')): return co2, PARAM_ERR, PARAM_ERR temp = float(tkns[1][1:len(tkns[1])-1]) # parse RH if (len(tkns[2]) < 5 and tkns[2] != ord('H')): return co2, temp, PARAM_ERR rh = float(tkns[2][1:len(tkns[2])-1]) return co2, temp, rh # read the sensor and returns CO2 (ppm), Temperature (ºC) and Relative Humidity (%) def read_sensor(): # configure the serial connection ser = serial.Serial( port=SERIAL_PORT, baudrate=9600, timeout=1, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS ) ser.isOpen() line = ser.readline() if len(line) > 0 and line[0] == ord('C'): return parse_line(line.decode('utf-8')) else: line = ser.readline() if len(line) > 0 and line[0] == ord('C'): return parse_line(line.decode('utf-8')) return PARAM_ERR, PARAM_ERR, PARAM_ERR ################################################################## while(1): co2, temp, rh = read_sensor() if (co2 == PARAM_ERR or temp == PARAM_ERR or rh == PARAM_ERR): continue print(f"CO2 = {co2} ppm; Temp = {temp} ºC; RH = {rh} %") time.sleep(5)
Before to launch the application is necesary to determine the name of the serial port in our host. This name must be set in the line of the code that begins with SERIALPORT
. In Linux it would be something like /dev/ttyUSBX
. In Windows would be COMX
.
The program makes a serial port read each 5 seconds. In that operation, the program reads the port and parse the content. The device transmit something similar like this each 2 seconds:
$CO2:Air:RH:DP:WBTf9 C1130ppm:T22.2C:H60.2%:d14.1C:w17.0C4a
The interesting part is the second line that is analized in the function def parse_line(src)
. In that function we read each parameter that are returned to be -in our case as example- printed in the console.
Thanks guys – great writeup!
Just wanted to add (in case anyone is looking to do this) that I found out that the official cable is using a CP2102 driver. I purchased a CP2102-M USB – TTL converter and it works out of the box (without the need for a pull-up resistor) as it is based on 5V TTL logic.
Hope this helps!