一. 获取485传感器的Modbus报文

如果你没有传感器的文档,本章介绍如何获取RS485 传感器 Modbus 报文,如果已知传感器报文可直接转至第二章。本章参考博客: 获取485温湿度传感器的Modbus报文

1.1 硬件准备

  • USB 转 RS485 模块:这是连接电脑与传感器的桥梁,能将电脑的 USB 接口转换为 RS485 通信接口 。​
  • RS485 温湿度传感器:确认传感器型号与线序
  • 电源模块:12V 独立电源,注意不同型号传感器的供电要求可能存在差异。​
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.2 软件准备

  • 串口调试工具
  • 485传感器配置软件
  • 串口监视器
    各类工具可自行下载,亦可使用本文提供的链街下载:
    链接: 百度网盘
    提取码:yuv8

1.3 硬件连接

传感器引脚 USB 转 RS485 模块引脚
485A A
485B B
传感器引脚 直流电源
电源正 12V
电源负 GND

在这里插入图片描述

将转换模块的USB连接至电脑,打开设备管理器查看设备COM号,记住自己的COM号,例如我的是COM16。(下载文件中有CH341驱动,未安装过的提前安装)
在这里插入图片描述

注:可能不同电脑此处略有差异,例如下图为COM6

在这里插入图片描述
(此处图片来源: 获取485温湿度传感器的Modbus报文

打开软件中的串口监视精灵,文件->新建会话
在这里插入图片描述

选择刚才查看的串口,进行如下设置在这里插入图片描述

打开485送变器配置软件,选择自己的传感器串口号,点击测试波特率,显示波特率(注:485传感器波特率可能有所不同,但是可以在此软件中更改,在设备波特率更改成自己想要的值,然后点击设置即可更改成功,为方便后面使用ESP32开发连接,这里我将波特率改成了9600)

在这里插入图片描述

点击确定后,在传感器可测定的项目后点击查询可获取数值,
在这里插入图片描述
返回串口精灵,可看到对应的Modbus报文

在这里插入图片描述
指令解析
此款传感器具备温湿度以及二氧化碳浓度的测定,其中温湿度测定发送的报文格式是:01 03 00 00 00 02 C4 0B
在这里插入图片描述
返回的报文格式是: 01 03 04 湿度(16位) 温度(16位) CRC校验码

以一组数据为例::01 03 04 01 D7 00 D6 CA 69
在这里插入图片描述
温湿度输出格式及计算示例
温湿度分辨率是 16Bit,温湿度以实际的正负数格式输出,且串出的数值是实际温湿度值的 10 倍
(湿度):01 D7 → 471(十六进制 → 十进制 471)=>湿度=256÷10=47.1%RH
(温度):00 D6 → 214(十六进制 → 十进制 214)=>温度=275÷10=21.4℃

(传感器的二氧化碳测试发送的报文格式可看出是01 03 00 02 00 01 25 CA
以一个返回例子:01 03 02 03 06 38 B6,其中03 06是寄存器的数据位,将03 06转换成十进制为774,此时二氧化碳浓度为774ppm)

二. ESP32 连接 RS485 温湿度传感器

2.1 硬件准备

  • ESP32 开发板
  • RS485 温湿度传感器
  • TTL 转 RS485 模块
  • 电源模块
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.2 软件准备

2.3 硬件连接

ESP32 TTL 转 RS485 模块
GND GND
GPIO17 RXD
GPIO16 TXD
3.3V VCC
RS485 温湿度传感器 TTL 转 RS485 模块
485A A+
485A B-

最后将485温湿度传感器连直接12v电源,如1.3章节。
在这里插入图片描述

2.4 程序编写

完整代码

#include <SoftwareSerial.h>

unsigned char item[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B}; // 温湿度传感器的16进制命令
String data = ""; // 接收到的数据
SoftwareSerial tempSerial(16, 17);  // RX, TX

struct SensorData {
 float temperature;
 float humidity;
};

SensorData parseSensorData(String data) {
 SensorData result;
 
 // 去掉末尾的逗号
 if (data.endsWith(",")) {
   data = data.substring(0, data.length() - 1);
 }
 
 // 分割数据
 String info[9];
 int commaPosition = -1;
 for (int i = 0; i < 9; i++) {
   commaPosition = data.indexOf(',');
   if (commaPosition != -1) {
     info[i] = data.substring(0, commaPosition);
     data = data.substring(commaPosition + 1);
   } else {
     if (data.length() > 0) {
       info[i] = data;
     }
   }
 }
 
 // 解析湿度值(第四和第五位)
 int humidityHigh = info[3].toInt(); // 使用16进制解析
 int humidityLow = info[4].toInt();  // 使用16进制解析
 result.humidity = (humidityHigh * 256 + humidityLow) / 10.0; // 假设湿度值以百分比形式返回
 
 // 解析温度值(第六和第七位)
 int temperatureHigh = info[5].toInt(); // 使用16进制解析
 int temperatureLow = info[6].toInt();  // 使用16进制解析
 result.temperature = (temperatureHigh * 256 + temperatureLow) / 10.0; // 假设温度值以10倍形式存储
 
 return result;
}

void setup() {
 tempSerial.begin(9600);
 Serial.begin(9600);
}

void loop() {
 delay(500);  // 放慢输出频率
 
 // 发送测温命令
 for (int i = 0 ; i < 8; i++) {
   tempSerial.write(item[i]);
 }
 
 delay(100);  // 等待数据返回
 
 data = "";
 while (tempSerial.available()) { // 读取数据
   unsigned char in = (unsigned char)tempSerial.read();
   Serial.print(in, HEX);
   Serial.print(',');
   data += in;
   data += ',';
 }
 
 if (data.length() > 0) {
   Serial.println();
   Serial.println(data);
   
   SensorData sensorData = parseSensorData(data);
   Serial.print("Temperature: ");
   Serial.print(sensorData.temperature);
   Serial.println(" °C");
   Serial.print("Humidity: ");
   Serial.print(sensorData.humidity);
   Serial.println(" %");
 }
}

打开Arduino IDE的串口监视器,波特率设置为9600,即可看到输出的温湿度数值。
使用Arduino IDE编写ESP32代码过程可以看我之前的文章。

附录

顺便一提,如果想要同时测量二氧化碳的浓度,代码如下

#include <SoftwareSerial.h>

unsigned char tempHumidityItem[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B}; // 温湿度传感器的16进制命令
unsigned char co2Item[8] = {0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x25, 0xCA}; // 二氧化碳传感器的16进制命令
String tempHumidityData = ""; // 接收到的温湿度数据
String co2Data = ""; // 接收到的二氧化碳数据
SoftwareSerial tempSerial(16, 17);  // RX, TX

struct SensorData {
  float temperature;
  float humidity;
  float co2;
};

SensorData parseSensorData(String data) {
  SensorData result;
  
  // 去掉末尾的逗号
  if (data.endsWith(",")) {
    data = data.substring(0, data.length() - 1);
  }
  
  // 分割数据
  String info[9];
  int commaPosition = -1;
  for (int i = 0; i < 9; i++) {
    commaPosition = data.indexOf(',');
    if (commaPosition != -1) {
      info[i] = data.substring(0, commaPosition);
      data = data.substring(commaPosition + 1);
    } else {
      if (data.length() > 0) {
        info[i] = data;
      }
    }
  }
  
  // 解析湿度值(第四和第五位)
  int humidityHigh = info[3].toInt(); // 使用16进制解析
  int humidityLow = info[4].toInt();  // 使用16进制解析
  result.humidity = (humidityHigh * 256 + humidityLow) / 10.0; // 假设湿度值以百分比形式返回
  
  // 解析温度值(第六和第七位)
  int temperatureHigh = info[5].toInt(); // 使用16进制解析
  int temperatureLow = info[6].toInt();  // 使用16进制解析
  result.temperature = (temperatureHigh * 256 + temperatureLow) / 10.0; // 假设温度值以10倍形式存储
  
  return result;
}

float parseCO2Data(String data) {
  // 去掉末尾的逗号
  if (data.endsWith(",")) {
    data = data.substring(0, data.length() - 1);
  }
  
  // 分割数据
  String info[7];
  int commaPosition = -1;
  for (int i = 0; i < 7; i++) {
    commaPosition = data.indexOf(',');
    if (commaPosition != -1) {
      info[i] = data.substring(0, commaPosition);
      data = data.substring(commaPosition + 1);
    } else {
      if (data.length() > 0) {
        info[i] = data;
      }
    }
  }
  
  // 解析二氧化碳值(第四和第五位)
  int co2High = info[3].toInt(); // 使用16进制解析
  int co2Low = info[4].toInt();  // 使用16进制解析
  return co2High * 256 + co2Low; // 假设二氧化碳值以整数形式返回
}

void setup() {
  tempSerial.begin(9600);
  Serial.begin(9600);
}

void loop() {
  delay(500);  // 放慢输出频率
  
  // 发送测温湿度命令
  for (int i = 0; i < 8; i++) {
    tempSerial.write(tempHumidityItem[i]);
  }
  
  delay(100);  // 等待数据返回
  
  tempHumidityData = "";
  while (tempSerial.available()) { // 读取数据
    unsigned char in = (unsigned char)tempSerial.read();
    Serial.print(in, HEX);
    Serial.print(',');
    tempHumidityData += in;
    tempHumidityData += ',';
  }
  
  if (tempHumidityData.length() > 0) {
    Serial.println();
    Serial.println(tempHumidityData);
    
    SensorData sensorData = parseSensorData(tempHumidityData);
    Serial.print("Temperature: ");
    Serial.print(sensorData.temperature);
    Serial.println(" °C");
    Serial.print("Humidity: ");
    Serial.print(sensorData.humidity);
    Serial.println(" %");
  }
  
  // 发送测CO2命令
  for (int i = 0; i < 8; i++) {
    tempSerial.write(co2Item[i]);
  }
  
  delay(100);  // 等待数据返回
  
  co2Data = "";
  while (tempSerial.available()) { // 读取数据
    unsigned char in = (unsigned char)tempSerial.read();
    Serial.print(in, HEX);
    Serial.print(',');
    co2Data += in;
    co2Data += ',';
  }
  
  if (co2Data.length() > 0) {
    Serial.println();
    Serial.println(co2Data);
    
    float co2 = parseCO2Data(co2Data);
    Serial.print("CO2: ");
    Serial.print(co2);
    Serial.println(" ppm");
  }
}
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐