初出茅庐的小李第59篇博客之测试Modbus协议的继电器

1, Modbus RTU指令详解

发送: FF 05 00 00 FF 00 99 E4
字段 含义 注释
FF 设备地址 范围1-255,默认255
05 功能码 写单个线圈
00 00 继电器地址 0x0000–0x0007分别代表#1继电器–#8继电器
FF 00 开/关命令 0x0000为关,0xFF00为开
99 E4 CRC16 CRC-16/MODBUS校验码
原样返回:FF 05 00 00 FF 00 99 E4
字段 含义 注释
FF 设备地址 范围1-255,默认255
05 功能码 写单个线圈
00 00 继电器地址 0x0000–0x0007分别代表#1继电器–#8继电器
FF 00 开/关命令 0x0000为关,0xFF00为开
99 E4 CRC16 CRC-16/MODBUS校验码

在这里插入图片描述
校验的结果在Modbus报文里要低字节在前高字节在后

E4 99
是校验的结果
99 E4 才是报文的内容

2,关闭1号继电器(手动模式)

发送: FF 05 00 00 00 00 D8 14
字段 含义 注释
FF 设备地址 范围1-255,默认255
05 功能码 写单个线圈
00 00 继电器地址 0x0000–0x0007分别代表#1继电器–#8继电器
00 00 开/关命令 0x0000为关,0xFF00为开
D8 14 CRC16 CRC-16/MODBUS校验码
原样返回:FF 05 00 00 00 00 D8 14
字段 含义 注释
FF 设备地址 范围1-255,默认255
05 功能码 写单个线圈
00 00 继电器地址 0x0000–0x0007分别代表#1继电器–#8继电器
00 00 开/关命令 0x0000为关,0xFF00为开
D8 14 CRC16 CRC-16/MODBUS校验码

3,打开所有继电器

发送:FF 0F 00 00 00 08 01 FF 30 1D
字段 含义 注释
FF 设备地址 范围1-255,默认255
0F 功能码 写多个线圈
00 00 起始地址 #1继电器地址
00 08 继电器数量 要控制的继电器总数量
01 命令字节数 控制命令字长度
FF 控制命令 0x00为全关,0xFF为全开
30 1D CRC16 CRC-16/MODBUS校验码
返回:FF 0F 00 00 00 08 41 D3
字段 含义 注释
FF 设备地址 范围1-255,默认255
0F 功能码 写多个线圈
00 00 起始地址 #1继电器地址
00 08 继电器数量 要控制的继电器总数量
41 D3 CRC16 CRC-16/MODBUS校验码

4,关闭所有继电器

发送:FF 0F 00 00 00 08 01 00 70 5D
字段 含义 注释
FF 设备地址 范围1-255,默认255
0F 功能码 写多个线圈
00 00 起始地址 #1继电器地址
00 08 继电器数量 要控制的继电器总数量
01 命令字节数 控制命令字长度
00 控制命令 0x00为全关,0xFF为全开
70 5D CRC16 CRC-16/MODBUS校验码
返回:FF 0F 00 00 00 08 41 D3
字段 含义 注释
FF 设备地址 范围1-255,默认255
0F 功能码 写多个线圈
00 00 起始地址 #1继电器地址
00 08 继电器数量 要控制的继电器总数量
41 D3 CRC16 CRC-16/MODBUS校验码

5,设置设备地址为255

发送: 00 10 00 00 00 01 02 00 FF EB 80
字段 含义 注释
00 固定值
10 功能码 写多个寄存器
00 00 起始地址
00 01 写寄存器个数
02 写寄存器字节数 写寄存器数据长度
00 FF 寄存器数据 写入设备地址0x00FF,范围:0x0001-0x00FF
EB 80 CRC16 CRC-16/MODBUS校验码
原样返回:00 10 00 00 00 01 02 00 FF EB 80
字段 含义 注释
00 固定值
10 功能码 写多个寄存器
00 00 起始地址
00 01 写寄存器个数
02 写寄存器字节数 写寄存器数据长度
00 FF 寄存器数据 即:写入设备地址0x00FF,范围:0x0001-0x00FF
EB 80 CRC16 CRC-16/MODBUS校验码

6,读取设备地址255

发送: 00 03 00 00 00 01 85 DB
字段 含义 注释
00 固定值
03 功能码 读保持寄存器
00 00 起始地址
00 01 寄存器数量 读寄存器数量
85 DB CRC16 CRC-16/MODBUS校验码
返回: 00 03 02 00 FF C5 C4
字段 含义 注释
00 固定值
03 功能码 读保持寄存器
02 数据字节数 从寄存器读取到的数据长度
00 FF 寄存器数据 读取到设备地址为0x00FF
C5 C4 CRC16 CRC-16/MODBUS校验码

7,读取继电器状态

发送: FF 01 00 00 00 08 28 12
字段 含义 注释
FF 设备地址 范围1-255,默认255
01 功能码 读线圈状态
00 00 起始地址 #1继电器地址
00 08 继电器数量 要读取的继电器总数量为0x0008
28 12 CRC16 CRC-16/MODBUS校验码
返回: FF 01 01 01 A1 A0
字段 含义 注释
FF 设备地址 范围1-255,默认255
01 功能码 读线圈状态
01 数据字节数 读取到的数据长度
01 数据 读取到的数据,Bit0-Bit7分别代表#1继电器–#8继电器状态,0为关,1为开
A1 A0 CRC16 CRC-16/MODBUS校验码

8,读取光耦输入状态

发送: FF 02 00 00 00 08 6C 12
字段 含义 注释
FF 设备地址 范围1-255,默认255
02 功能码 读离散输入状态
00 00 起始地址 #1光耦地址
00 08 光耦数量 要读取的光耦总数量为0x0008
6C 12 CRC16 CRC-16/MODBUS校验码
返回: FF 02 01 01 51 A0
字段 含义 注释
FF 设备地址 范围1-255,默认255
02 功能码 读离散输入状态
01 数据字节数 读取到的数据长度
01 数据 读取到的数据,Bit0-Bit7分别代表#1光耦–#8光耦输入状态,0为高电平,1为低电平
51 A0 CRC16 CRC-16/MODBUS校验码

9,设置波特率为9600

发送: FF 10 03 E9 00 01 02 00 03 8B CC
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
03 E9 起始地址
00 01 写寄存器个数
02 写寄存器字节数 写寄存器数据长度
00 03 寄存器数据 波特率写入值,范围:0x0002–0x0004,其中0x0002, 0x0003, 0x0004分别代表波特率4800, 9600, 19200
8B CC CRC16 CRC-16/MODBUS校验码
返回: FF 10 03 E9 00 01 C5 A7
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
03 E9 起始地址
00 01 写寄存器个数
C5 A7 CRC16 CRC-16/MODBUS校验码

10,读取波特率 返回19200

发送: FF 03 03 E8 00 01 11 A4
字段 含义 注释
FF 设备地址 范围1-255,默认255
03 功能码 读保持寄存器
03 E8 起始地址
00 01 寄存器数量 读寄存器数量
11 A4 CRC16 CRC-16/MODBUS校验码
返回: FF 03 02 00 04 90 53
字段 含义 注释
FF 设备地址 范围1-255,默认255
03 功能码 读保持寄存器
02 数据字节数 从寄存器读取到的数据长度
00 04 寄存器数据 波特率读取值,范围:0x0002–0x0004,其中0x0002, 0x0003, 0x0004分别代表波特率4800, 9600, 19200
90 53 CRC16 CRC-16/MODBUS校验码

11,打开1号继电器(闪闭模式2S)

发送: FF 10 00 03 00 02 04 00 04 00 14 C5 9F
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
00 03 继电器地址 #1继电器–#8继电器地址分别为:0x0003,0x0008,0x000D,0x0012,0x0017,0x001C,0x0021,0x0026
00 02 写寄存器个数
04 写寄存器字节数 写寄存器数据长度
00 04 寄存器1数据 闪闭/闪断值,0x0004代表闪闭,0x0002代表闪断
00 14 寄存器2数据 延时设置值,范围:0x0001–0xFFFF。延时基数为0.1S,故延时
时间为0x0014
0.1=200.1S=2S,#1继电器闭合2S后自动断开
C5 9F CRC16 CRC-16/MODBUS校验码
返回: FF 10 00 03 00 02 A4 16
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
00 03 继电器地址 #1继电器–#8继电器地址分别为:0x0003,0x0008,0x000D,0x0012,0x0017,0x001C, 0x0021,0x0026
00 02 写寄存器个数
A4 16 CRC16 CRC-16/MODBUS校验码

12,关闭1号继电器(闪断模式3S)

发送: FF 10 00 03 00 02 04 00 02 00 1E A5 99
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
00 03 继电器地址 #1继电器–#8继电器地址分别为:0x0003,0x0008,0x000D,0x0012,0x0017,0x001C,0x0021,0x0026
00 02 写寄存器个数
04 写寄存器字节数 写寄存器数据长度
00 02 寄存器1数据 闪闭/闪断值,0x0004代表闪闭,0x0002代表闪断
00 1E 寄存器2数据 延时设置值,范围:0x0001–0xFFFF。延时基数为0.1S,故延时时间为0x001E0.1=300.1S=3S,#1继电器断开3S后自动闭合
A5 99 CRC16 CRC-16/MODBUS校验码
返回: FF 10 00 03 00 02 A4 16
字段 含义 注释
FF 设备地址 范围1-255,默认255
10 功能码 写多个寄存器
00 03 继电器地址 #1继电器–#8继电器地址分别为:0x0003,0x0008,0x000D,0x0012,0x0017,0x001C, 0x0021,0x0026
00 02 写寄存器个数
A4 16 CRC16 CRC-16/MODBUS校验码

**这里面用到了很多功能码01 02 03 05 10 0F 等每种功能码都有其约定的含义具体含义是啥可以不用关心,既然是协议先遵循就好,接下里看如何组包用单片机发送这些命令 **

我现在不关心返回值所以先用简单的方式实现,真正的通信是应该判断通信之后返回的报文的我这里还没有做
安全起见先用调试助手测试

在这里插入图片描述

这些报文经过测试跟手册说的一样证明这个模块还是比较可靠的

下面就用程序来实现发送

Arduino 控制继电器

const byte RS485_ON1[8]={0xFF,0x05,0x00,0x00,0xFF,0x00,0x99,0xE4};//FF 05 00 00 FF 00 99 E4 
const byte RS485_OFF1[8]={0xFF,0x05,0x00,0x00,0x00,0x00,0xD8,0x14};//FF 05 00 00 00 00 D8 14
const byte RS485_ON2[8]={0xFF,0x05,0x00,0x01,0xFF,0x00,0xC8,0x24};//FF 05 00 01 FF 00 C8 24
const byte RS485_OFF2[8]={0xFF,0x05,0x00,0x01,0x00,0x00,0x89,0xD4};//FF 05 00 01 00 00 89 D4
const byte RS485_ON3[8]={0xFF,0x05,0x00,0x02,0xFF,0x00,0x38,0x24};//FF 05 00 02 FF 00 38 24
const byte RS485_OFF3[8]={0xFF,0x05,0x00,0x02,0x00,0x00,0x79,0xD4};//FF 05 00 02 00 00 79 D4
const byte RS485_ON4[8]={0xFF,0x05,0x00,0x03,0xFF,0x00,0x69,0xE4};//FF 05 00 03 FF 00 69 E4
const byte RS485_OFF4[8]={0xFF,0x05,0x00,0x03,0x00,0x00,0x28,0x14};//FF 05 00 03 00 00 28 14
const byte RS485_ONALL[10]={0xFF,0x0F,0x00,0x00,0x00,0x08,0x01,0xFF,0x30,0x1D};//FF 0F 00 00 00 08 01 FF 30 1D
const byte RS485_OFFALL[10]={0xFF,0x0F,0x00,0x00,0x00,0x08,0x01,0x00,0x70,0x5D};//FF 0F 00 00 00 08 01 00 70 5D

arduino中数据类型跟我们经常在C语言中还是有点不同
这里有两篇博文写的很清楚可以作为参考学习推荐收藏
链接

链接
在这里插入图片描述
在这里插入图片描述

红外控制的代码

/*
 * 红外控制函数
 * 函数说明:
 * 传入红外键值
 * 执行对应动作
 */
void IR_Contrl(unsigned int key_val)
{
//  unsigned char data;
//  data = 0x00;
//  /*不能直接写0x00在函数里,否则会报错*/
  switch(key_val)
  {
    case 0xFFA25D:
      {
          Serial.println("CH-");
          mySerial.write(RS485_OFFALL,sizeof(RS485_OFFALL));
//          mySerial.write(0xFF);
//          mySerial.write(0x05);
//          mySerial.write(data);
//          mySerial.write(data);
//          mySerial.write(0xFF);
//          mySerial.write(data);
//          mySerial.write(0x99);
//          mySerial.write(0xE4);
      }
      break;
    case 0xFF629D:
      Serial.println("CH");
      break;
    case 0xFFE21D:
      {
        Serial.println("CH+");
        mySerial.write(RS485_ONALL,sizeof(RS485_ONALL));
//        mySerial.write(0xFF);
//        mySerial.write(0x05);
//        mySerial.write(data);
//        mySerial.write(data);
//        mySerial.write(data);
//        mySerial.write(data);
//        mySerial.write(0xD8);
//        mySerial.write(0x14);
      }
      break;
    case 0xFF22DD:
      {
        Serial.println("PREV");
      }
      break;
    case 0xFF02FD:
      Serial.println("NEXT");
      break;
    case 0xFFC23D:
      Serial.println("PLAY/PAUSE");
      break;
    case 0xFFE01F:
      Serial.println("-");
      break;
    case 0xFFA857:
      Serial.println("+");
      break;
       case 0xFF906F:
      Serial.println("EQ");
      break;
    case 0xFF6897:
      Serial.println("0");
      break;
    case 0xFF30CF:
      {
        Serial.println("1");
        mySerial.write(RS485_ON1,sizeof(RS485_ON1));
      }
      break;
    case 0xFF18E7:
      {
        Serial.println("2");
        mySerial.write(RS485_ON2,sizeof(RS485_ON2));
      }
      break;
    case 0xFF7A85:
      {
        Serial.println("3");
        mySerial.write(RS485_ON3,sizeof(RS485_ON3));
      }
      break;
    case 0xFF10EF:
      {
        Serial.println("4");
        mySerial.write(RS485_ON4,sizeof(RS485_ON4));
      }
      break;
    case 0xFF38C7:
      {
        Serial.println("5");
        mySerial.write(RS485_OFF1,sizeof(RS485_OFF1));
      }
      break;
    case 0xFF5AA5:
      {
        Serial.println("6");
        mySerial.write(RS485_OFF2,sizeof(RS485_OFF2));
      }
      break;
    case 0xFF42BD:
      {
        Serial.println("7");
        mySerial.write(RS485_OFF3,sizeof(RS485_OFF3));
      }
      break;
    case 0xFF4AB5:
      {
        Serial.println("8");
        mySerial.write(RS485_OFF4,sizeof(RS485_OFF4));
      }
      break;
    case 0xFF52AD:
      Serial.println("9");
      break;
    case 0xFF9867:
      Serial.println("100+");
      break;
    case 0xFFB04F:
      Serial.println("200+");
      break;
  }
}                        

最后测试的效果

在这里插入图片描述

https://www.bilibili.com/video/BV1X5411E7Zj小破站测试结果

接下里可以玩玩这个风扇,据说四线风扇可以PWM调速,那我们或许可以试试编码器调速,或者温度调速,把这个风扇玩起来

这个风扇是我在租房子的时候房东管理员哪里两瓶饮料换来的(其实是他送我的,我也不好意白嫖啊!!!!)

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Arduino可以通过连接WiFi模块来控制继电器。首先,需要选择一个适用于Arduino的WiFi模块,常见的有ESP8266和ESP32等。接下来,将WiFi模块与Arduino进行连接,可以通过串行通信或使用适当的库来实现。通过连接到无线网络,Arduino就能够与其他设备或互联网进行通信。 一旦Arduino成功连接到WiFi,就可以开始使用继电器控制其他设备。先将继电器Arduino进行连接,通常使用数字引脚来控制继电器的开关。确保正确连接继电器的电源和控制引脚。 在Arduino编程环境中,可以使用相应的库来控制继电器。一般而言,通过设置引脚状态为高电平或低电平来控制继电器的开关。具体的代码可以参考相应的库和文档。 接下来,编写代码来实现WiFi模块与继电器控制。首先,需要初始化WiFi模块并连接到无线网络。在成功连接后,使用合适的指令或函数来控制继电器。这可以通过向继电器控制引脚发送高或低电平来实现。 测试代码时,可以尝试使用一个简单的命令或按钮来触发继电器的开关。例如,当用户通过手机应用或网页发送一个指令给Arduino时,Arduino接收到该指令后就会执行相应的动作,控制继电器的开关。 通过连接WiFi模块控制继电器Arduino可以实现远程控制其他设备或实现自动化控制。但需要注意安全性和合法性,避免对他人或设备造成损害。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值