使用Python读取甲醛传感器

甲醛是比较出名的致癌气体,本文介绍如何使用Python通过串口读取福申FS005甲醛传感器的数据。

连接USB转串口设备

由于传感器使用的波特率只有9600,你可以使用普通的USB转串口设备,基于CH340或CP2102芯片的都可以。传感器共有7个管脚,我们只需要使用其中的如下4个管脚:

FS005USB转串口设备
3GND
45V
5TX
6RX
  • FS005要求的最低输入电压为3.7V,所以需要注意选择USB转串口设备的5V输出。
  • 甲醛传感器上面的白色贴纸不能撕掉。

读取数据

传感器上电后会每秒上报一次数据。数据的格式如下:

# 0       1         2     3         4             5               6            7       8
# 起始位  设备类型  单位  小数位数  气体浓度高位  气体浓度低位    满量程高位    满量程低位   校验值
# ff      17       04     00        00            1b              07          d0       f3

气体浓度值=气体浓度高位*256+气体浓度低位, 单位为:ug/m3. 通常会将输出值除以1000得到mg/m3的值。

输出示例:

ff 17 04 00 00 1b 07 d0 f3

知道协议后剩下的就比较简单了,下面是Python的实现:

# FS005009 Formaldehyde (HCHO) sensor
# 0       1         2     3         4             5               6            7       8
# 起始位  设备类型  单位  小数位数  气体浓度高位  气体浓度低位    满量程高位    满量程低位   校验值
# ff      17       04     00        00            1b              07          d0       f3
#
# 气体浓度值=气体浓度高位*256+气体浓度低位, 单位:ug/m3
# Sample output:
# ff 17 04 00 00 1b 07 d0 f3


import _thread as thread
import time
import serial
import json
import base64
import re


class FS005():
    def __init__(self, port='/dev/ttyUSB0'):
        self.port = port
        self.baudrate = 9600
        self.concentration = 0
        self.ser = None

    def start(self):
        # 参考文档设置串口参数
        self.ser = serial.Serial(
            # 这里设置串口端口
            port=self.port,
            baudrate=self.baudrate,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
        )
        thread.start_new_thread(self.start_reader, ())


    def read(self):
        return self.concentration

    def start_reader(self):
        # 等待串口连接
        while not self.ser.isOpen():
            print(f'Waiting device on port {self.port} ...')
            time.sleep(3)

        # 先清除串口之前的数据
        while self.ser.inWaiting() > 0:
            n = self.ser.inWaiting()
            self.ser.read(self.ser.inWaiting())
            time.sleep(0.1)

        # 开始读取数据
        while True:
            data = self.ser.read_all()
            if not data:
                time.sleep(1)
                continue
            if len(data) != 9:
                print(f'Invalid data len: {data}')
                continue

            if list(data[:4]) != [0xff, 0x17, 0x04, 0x00]:
                print(f'Invalid data: {data[:4]}')
                continue

            low = data[5]
            high = data[4]
            val = (high * 256 + low) / 1000.0
            self.concentration = val

if __name__ == '__main__':
    reader = FS005('/dev/ttyUSB0')
    reader.start()
    while True:
        print(f'val: {reader.read()}')
        time.sleep(2)

如果你的串口路径位置不同,需要修改下面这行:

    reader = FS005('/dev/ttyUSB0')

Linux下可在插入串口设备后使用sudo dmesg | tail |grep ttyUSB命令查询串口号。Windows下需要在设备管理器里查看,通常名称格式为COM加数字。

运行程序将能看到如下输出,单位为mg/m3:

...
val: 0.008
val: 0.007
val: 0.007
val: 0.007
val: 0.007
val: 0.007
val: 0.007
...

中国室内空气质量标准规定甲醛浓度不得高于0.1mg/m3.

使用建议

  • 传感器预热需要约5分钟。
  • 如需测量甲醛浓度,可先将传感器置于通风但无强风的窗边获取基准值,然后再关闭门窗后测量。
  • 需要了解,存在干扰气体时测得的浓度是不准确的。