本实验以Wemos D1 mini作为MODBUS主站(Master),2个温湿度变送器作为MODBUS从站(Slave),两者经RS485模块通过软串口进行半双工通信,实现对设备的轮询。
器件
Wemos D1 mini 一块
温湿度变送器 两个
TTL转RS485 模块 MAX485 一个
电源:充电宝 一个
USB线 一条
杜邦线若干
接线
先将温湿度变送器经RS485模块接到电脑的USB,用串口调试助手调通,并设定两个设备地址分别为0X01、0X02。
修改从机地址命令帧
地址码 | 功能码 | 起始地址 | 数据长度 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0X01 | 0x00 0X08 | 0xD8 | 0x30 |
应答帧(与发送帧相同)
地址码 | 功能码 | 起始地址 | 数据长度 | 校验码低位 | 校验码高位 |
---|---|---|---|---|---|
0x01 | 0x06 | 0x00 0X01 | 0x00 0X08 | 0xD8 | 0x30 |
然后再接到D1 mini上,MAX485的R0接mini的D1(GPIO5)、DI接mini的D2(GPIO4)、VCC接mini的3V3、GND接mini的G、RE和DE都接到mini的D4(GPIO2),MAX485的A与两个温湿度变送器的A连接、RS485的B与两个温湿度变送器的B连接、大地悬空,温湿度变送器接外接电源5-30V均可。
注意:MAX485的VCC和GND一定要用D1 mini板子的输出电压和地。
实物图
代码
代码如下(示例):
#include <SoftwareSerial.h>
SoftwareSerial Master(D2, D1); //定义软串口RX、TX
unsigned char Qu_Frame[2][8] = {{0x01, 0x04, 0x00, 0x01, 0x00, 0x02, 0x20, 0x0B},
{0x02, 0x04, 0x00, 0x01, 0x00, 0x02, 0x20, 0x38}};//主机请求帧列表
String Re_Frame=""; //定义一个字符串,用来将从机返回帧
int DE_RE=D4; //使能端,高电平发送请求,低电平接收数据
void getTH(String th); // 函数声明
float th_date[2];
float *P_th=th_date;
void setup() {
Serial.begin(9600);
Serial.println("Master is ready!");
Master.begin(9600);
pinMode(DE_RE,OUTPUT);
digitalWrite(DE_RE,LOW);
}
void loop()
{
for(int i = 0 ; i < 2; i++) //用来对每个从机进行一次大轮询
{
digitalWrite(DE_RE,HIGH); //将主机设为发送状态
for(int j = 0 ; j < 8; j++) //给从机发送请求码
Master.write(Qu_Frame[i][j]);
digitalWrite(DE_RE,LOW); //然后立马换成接收状态
delay(500); //等一下从机反应,否则Maste.available还没反应过来,就过去了,加个
Re_Frame=""; //准备接收从机数据
int k=0;
while(Master.available()) //当从机有数据发过来
{
unsigned char in = (unsigned char)Master.read(); // read读取
Re_Frame += in;
Re_Frame += ','; //读数据信息到数组Re_Frame
k++;
}
delay(1000);
if (Re_Frame.length() > 0) {
getTH(Re_Frame);//调用函数计算温湿度值
Serial.print(i+1);
Serial.print("号设备");
Serial.print("温度值:");
Serial.print(*P_th);//输出温度值
Serial.print("℃");
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;
}