简介
这款红外二氧化碳传感器利用非色散红外(NDIR技术)原理对空气中存在的CO2 进行探测,测量范围400~5000PPM,支持手动校正,测量数据更精准,响应时间为5s,每次响应指示灯闪烁一次,可直观查看传感器工作状态。
红外二氧化碳传感器采用RS485输出接口,标准Modbus-RTU通信协议,可以搭配Gravity: RS485转UART 有源隔离型信号转换模块(DFR0845)在Arduino UNO R3上读取CO2值,快速搭建测试环境,接线方式简单,使用方便。
红外二氧化碳传感器具有IP65的防护效果,探头处带有防水透气膜,高分子防水材料具有较好的透气性,可以有效防止水汽和灰尘进入,可用于室内CO2浓度监测、管道CO2浓度监测、大棚植物环境监测、新风系统环境检测。
特性
- NDIR技术,测量范围400~5000PPM
- 螺纹固定安装设计,安装方便
- 防护等级IP65,使用寿命更长
- 采用RS485接口,标准Modbus-RTU协议
应用场景
- 室内CO2浓度监测
- 管道CO2浓度监测
- 大棚植物环境监测
- 新风系统环境检测
技术规格
- 供电电压:DC12V
- 工作电流:<10mA
- 输出方式:RS485
- 测量范围:400-5000ppm
- 精度: 400-2000ppm@±50ppm,>2000ppm@±100ppm
- 响应时间:5s
- 稳定时间:60s
- 工作温度:-30~80°C
- 工作湿度:5~90%RH
- 存储温度:-30~80°C
- 存储湿度:5~90%RH
- 外壳材料:塑料
- 防护等级:IP65
- 安装螺纹直径:M18
- 尺寸:75*16.5mm
- 传感器线长:1m
引脚示意图
线序 | 功能描述 |
---|---|
红线 | DC12V供电 |
绿线 | GND |
黄线 | RS485-A |
蓝线 | RS485-B |
尺寸图

通讯协议
1、通讯基本参数
接口 | 编码 | 数据位 | 奇偶校验位 | 停止位 | 错误校验 | 波特率 |
---|---|---|---|---|---|---|
RS485 | 8位二进制 | 8 | 无 | 1 | CRC | 2400bit/s、4800bit/s、9600 bit/s、19200bit/s、38400bit/s、115200bit/s 可设,默认9600bit/s |
2、数据帧格式定义
采用 Modbus-RTU 通讯规约,格式如下:
初始结构 ≥4 字节的时间
地址码 = 1 字节
功能码 = 1 字节
数据区 = N 字节
错误校验 = 16 位 CRC 码
结束结构 ≥4 字节的时间
地址码:为传感器的地址,在通讯网络中是唯一的(出厂默认 0x01)。
功能码:主机所发指令功能指示,本传感器读取寄存器功能码0x03,写入寄存器功能码0x06
数据区:数据区是具体通讯数据,注意 16bits 数据高字节在前!
CRC 码:二字节的校验码。
主机问询帧结构:
地址码 | 功能码 | 寄存器起始地址 | 寄存器长度 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
1byte | 1byte | 2byte | 2byte | 1byte | 1byte |
从机应答帧结构:
地址码 | 功能码 | 有效字节数 | 数据一区 | 第二数据区 | 第N数据区 | 检验码 |
---|---|---|---|---|---|---|
1byte | 1byte | 1byte | 2byte | 2byte | 2byte | 2byte |
寄存器地址
寄存器地址 | PLC 或组态地址 | 内容 | 支持功能码 | 定义说明 |
---|---|---|---|---|
0000H | 40001 | 二氧化碳值 | 0x03 | 实际值 |
006BH | 二氧化碳校正值 | 0x03/0x06 | 可修改范围为±1000,即值范围为 0-1000 或 64535-65535 | |
0066H | 40103 | 设备地址 | 0x03/0x06 | 1~249(出厂默认1) |
0067H | 40104 | 设备波特率 | 0x03/0x06 | 1代表2400,2代表4800,3代表9600,4代表19200,5代表38400,6代表115200 |
3、通讯协议示例及解释
3.1、读取二氧化碳值
问询帧:读取数值功能码 0x03
地址码 | 功能码 | 寄存器起始地址 | 寄存器长度 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x00 0x00 | 0x00 0x01 | 0x84 | 0x0A |
应答帧:
地址码 | 功能码 | 返回有效字节数 | 二氧化碳值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x02 | 0x02 0xFC | 0xB9 | 0x65 |
二氧化碳值:
02FC(16进制) =764=> 二氧化碳值=764ppm
3.2、读取当前二氧化碳校正值(出厂默认为0)
问询帧:
地址码 | 功能码 | 寄存器起始地址 | 寄存器长度 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x00 0x6B | 0x00 0x01 | 0xF5 | 0xD6 |
应答帧:
地址码 | 功能码 | 返回有效字节数 | 校正值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x02 | 0x00 0x64 | 0xB9 | 0xAF |
校准值:
0064(16进制) =100=> 校准值=100ppm
3.3、修改二氧化碳校正值
当数据与参照标准有误差时,我们可以通过调整“校正值”来减小显示误差。校正差值可修改范围为±1000,即值范围为 0-1000 或 64535-65535。 比如当显示值偏小100 时,我们通过增加 100 来校正。在命令中 100 即十六进制 0x64;如果需要减小,则可以设置负值,比如-100,其计算方式为FFFF-64+1=FF9C,即十六进制 0xFF 9C
问询帧:
地址码 | 功能码 | 寄存器起始地址 | 修改数值 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0x6B | 0x00 0x64 | 0xF9 | 0xFD |
应答帧:
地址码 | 功能码 | 寄存器地址 | 校正值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0x6B | 0x00 0x64 | 0xF9 | 0xFD |
校正值:
0064(16进制) =100=> 校正值=100ppm
3.4、修改当前地址
问询帧:(修改当前地址为 0x02 )
地址码 | 功能码 | 寄存器地址 | 修改数值 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0x66 | 0x00 0x02 | 0xE8 | 0x14 |
应答帧:
地址码 | 功能码 | 寄存器地址 | 修改数值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x02 | 0x06 | 0x00 0x66 | 0x00 0x02 | 0xE8 | 0x27 |
3.5、修改当前波特率
问询帧:(修改当前波特率为38400 )
地址码 | 功能码 | 寄存器地址 | 修改数值 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0x67 | 0x00 0x05 | 0xF8 | 0x16 |
应答帧:
地址码 | 功能码 | 寄存器地址 | 修改数值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0x67 | 0x00 0x05 | 0xF8 | 0x16 |
3.6、查询当前地址、波特率
问询帧:
地址码 | 功能码 | 寄存器地址 | 数据长度 | 检验码低位 | 检验码高位 |
---|---|---|---|---|---|
0xFA | 0x03 | 0x00 0x66 | 0x00 0x02 | 0x31 | 0x9F |
应答帧:
地址码 | 功能码 | 返回有效字节数 | 地址 | 波特率 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|---|
0x01 | 0x03 | 0x04 | 0x00 0x01 | 0x00 0x03 | 0xEB | 0xF2 |
读取到设备的真实地址为 01,波特率为 0x03,即 9600。
使用教程
硬件准备
- Arduino UNO x1
- RS485 红外二氧化碳传感器 x1
- Gravity: RS485转UART 有源隔离型 信号转换模块 x1
软件准备
- 下载Arduino IDE: 点击下载Arduino IDE
硬件连接
若RS485设备的功率较小,需求电流小于12V-160mA,RS485转UART信号转换模块则无需12V外部供电,接线更方便。
演示代码
注意:预热时间输出的CO2浓度值会逐渐趋于稳定,预热5分钟内的CO2浓度值请忽略。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2,3);
uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
int CO2;
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop() {
readCO2();
Serial.print("CO2 = ");
Serial.print(CO2);
Serial.println(" ppm");
delay(4000);
}
void readCO2(void) {
uint8_t Data[10] = { 0 };
uint8_t ch = 0;
bool flag = 1;
while (flag) {
delay(100);
mySerial.write(Com, 8);
delay(10);
if (readN(&ch, 1) == 1) {
if (ch == 0x01) {
Data[0] = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x03) {
Data[1] = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x02) {
Data[2] = ch;
if (readN(&Data[3], 4) == 4) {
if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
CO2 = Data[3] * 256 + Data[4];
flag = 0;
}
}
}
}
}
}
}
}
mySerial.flush();
}
}
uint8_t readN(uint8_t *buf, size_t len) {
size_t offset = 0, left = len;
int16_t Tineout = 500;
uint8_t *buffer = buf;
long curr = millis();
while (left) {
if (mySerial.available()) {
buffer[offset] = mySerial.read();
offset++;
left--;
}
if (millis() - curr > Tineout) {
break;
}
}
return offset;
}
unsigned int CRC16_2(unsigned char *buf, int len) {
unsigned int crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (unsigned int)buf[pos];
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
return crc;
}
结果
打印采集到的CO2值
常见问题
1.电脑有多个 COM 口,选择的口不正确。
2.设备地址错误,或者存在地址重复的设备(出厂默认全部为 1)。
3.波特率,校验方式,数据位,停止位错误。
4.主机轮询间隔和等待应答时间太短,需要都设置在 200ms 以上。
5.485 总线有断开,或者 A、B 线接反。
6.设备数量过多或布线太长,应就近供电,加 485 增强器,同时增加120Ω终端电阻。
7.USB 转 485 驱动未安装或者损坏。
8.设备损坏。