本实验以Wemos D1 mini作为MODBUS主站(Master),温湿度变送器作为MODBUS从站(Slave),两者经RS485模块通过软串口进行通信。
器件
Wemos D1 mini 一块
温湿度变送器 一个
RS485转串口UART电平互转模块 一个
电源:充电宝 一个
USB线 一条
杜邦线若干
接线
先将温湿度变送器经RS485模块接到电脑的USB,用串口调试助手调通。
然后再接到D1 mini上,RS485的RX接mini的D1(GPIO5)、TX接mini的D2(GPIO4)、VCC接mini的3V3、GND接mini的G,RS485的A与温湿度变送器的A连接、RS485的B与温湿度变送器的B连接、大地悬空,温湿度变送器接外接电源5-30V均可。
注意:RS485模块的VCC和GND一定要用D1 mini板子的输出电压和地。
实物图
代码
读取设备地址 0x01的温湿度值(只有一个从设备地址设为0x01)
问询帧
地址码 | 功能码 | 起始地址 | 数据长度 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x04 | 0x00 0X01 | 0x00 0X02 | 0x20 | 0x0B |
应答帧(例如读到温度为30.5℃,湿度为54.6%)
地址码 | 功能码 | 有效数字 | 温度值 | 湿度值 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|---|
0X01 | 0X04 | 0X04 | 0X01 0X31 | 0X02 0X22 | 0X2A | 0XCE |
温度值=0x131,转换成十进制305,实际温度值 = 305 / 10 = 30.5℃
湿度值=0x222,转换成十进制546,实际湿度值=546 / 10 = 54.6%;
注:温度是有符号16进制数,若温度值=0xFF33,转换成十进制 -205,实际温度= -20.5℃
代码如下:
#include <SoftwareSerial.h>
unsigned char ith[8] = {0x01, 0x04, 0x00, 0x01, 0x00, 0x02, 0x20, 0x0B}; //16进制测温湿度命令帧
String data = ""; // 接收到的16进制字符串(温湿度返回帧)
SoftwareSerial thSerial(5, 4); // RX, TX
void getTH(String th); // 函数声明
float th_date[2];
float *P_th=th_date;
void setup()
{
thSerial.begin(9600);
Serial.begin(9600);
}
void loop()
{
delay(500); // 放慢输出频率
for (int i = 0 ; i < 8; i++) { // 发送测温湿度命令帧
thSerial.write(ith[i]); // write输出
}
delay(200); // 等待测温湿数据返回
data = "";
while (thSerial.available()) {//从串口中读取温湿度返回码
unsigned char in = (unsigned char)thSerial.read(); // read读取
data += in;
data += ',';
}
if (data.length() > 0) {
getTH(data);//调用函数计算温湿度值
Serial.print("温度值:");
Serial.print(*P_th);//输出温度值
Serial.println("℃");
Serial.print("湿度值:");
Serial.print(*(P_th+1));//输出湿度值
Serial.println("%");
}
delay(5000);
}
//计算温湿度值的函数
void getTH(String th) {
int commaPosition = -1;
String info[9]; // 用字符串数组存储温湿度返回码
for (int i = 0; i < 9; i++) {
commaPosition = th.indexOf(',');
if (commaPosition != -1)
{
info[i] = th.substring(0, commaPosition);
th = th.substring(commaPosition + 1, th.length());
}
else {
if (th.length() > 0) { // 最后一个会执行这个
info[i] = th.substring(0, commaPosition);
}
}
}
P_th[0] = (info[3].toInt() * 256 + info[4].toInt()) / 10.0;
P_th[1] = (info[5].toInt() * 256 + info[6].toInt()) / 10.0;
}