ModbusRTU控制SV660P说明

帖子目的

Modbus RTU是工业控制现场经典的控制协议,本贴结合市场一线实际工作经验,总结上位机通过ModbusRTU控制SV660P的注意事项,希望对大家有所帮助

1.Modbus协议说明

Modbus通信的底层为RS485信号,采用双绞线进行联接就可以了,因此传输距离较远,可达1000米,抗干扰性能比较好,且成本低,在工业控制设备的通信中被广泛使用,现在众多厂家的变频器、控制器都采用了该协议。
传送数据格式有HEX码数据和ASCII码两种,分别称为Modbus-RTU和Modbus-ASC 协议。
前者为数据直接传送,而后者需将数据变换为ASCII码后传送,因此Modbus-RTU协议的通信效率较高,处理简单,使用得更多。
Modbus为单主多从通信方式,采用的是主问从答方式,每次通信都是由主站首先发起,从站被动应答。因此,如变频器之类的被控设备,一般内置的是从站协议,而PLC之类的控制设备,则需具有主站协议、从站协议。

2.常用Modbus 功能码及数据编址

SV660P作为Modbus从站时,支持Modbus协议功能码0x03, 0x06, 0x10;
Modbus通信主机在访问(读取或改写) 伺服从机的内部变量时,必须遵循如下的通信命令帧定义,以及变量地址索引方法,才能进行正常的通信操作

功能码 0x03(03):读寄存器

 

功能码 0x10(16):写多个寄存器

 

 

3.错误响应帧

 

 

 

 

 

 

4.接线&SV660P参数设置

 

 

 

 

 

 注:如线束制作不便,可直接购买 USB-S6-L-T00-3.0 数据线使用

 

 

 

 

 

 

5.通讯例子

5.1 写动作H31-00

5.1.1 伺服使能,H31-00的bit0设置为1
Send->
01 10 31 00 00 01 02 00 01 47 53
Recv<-
01 10 31 00 00 01 0F 35

5.1.2 伺服断使能,H31-00的bit0设置为0
Send->
01 10 31 00 00 01 02 00 00 86 93

5.1.3 正点动,H31-00的bit1设置为1
Send->
01 10 31 00 00 01 02 00 03 C6 92

5.1.4 反点动,H31-00的bit2设置为1
Send->
01 10 31 00 00 01 02 00 05 46 90

5.1.5 绝对定位,H31-00的bit3设置为1
Send->
01 10 31 00 00 01 02 00 01 47 53 (先写0)
Send->
01 10 31 00 00 01 02 00 09 46 95 (再写1)

5.1.6 原点回归使能,H31-00的bit4设置为1
Send->
01 10 31 00 00 01 02 00 01 47 53(先写0)
Send->
01 10 31 00 00 01 02 00 11 46 9F(再写1)

5.1.7 VDI急停,H31-00的bit5设置为1
Send->
01 10 31 00 00 01 02 00 21 46 8B (先写1,触发急停,面板报Er.900)
Send->
01 10 31 00 00 01 02 00 01 47 53 (再写0,解除急停)

5.1.8 报警复位,H31-00的bit6设置为1
Send->
01 10 31 00 00 01 02 00 41 46 A3 (先写1,报警复位)
Send->
01 10 31 00 00 01 02 00 01 47 53 (再写0)

5.2 写参数

注意:参数掉电保持H0C-13=1,且参数设置好后,断电重启,然后必须关闭H0C-13=0,保护EEPROM。

5.2.1 写目标位置H11-0C=10000(假设写入ABCD数据,格式为CDAB)
Send->
01 10 11 0C 00 02 04 27 10 00 00 38 DB
Recv->
01 10 11 0C 00 02 84 F7

5.2.2 写点动速度H06-04=32rpm
Send->
01 10 06 04 00 01 02 00 20 C0 0C
Recv->
01 10 06 04 00 01 40 80

5.2.3 功能码急停,断使能,面板不报Er.900,H0D-05=1
Send->
01 10 0D 05 00 01 02 00 01 BB 05 (先写1,触发急停)
Send->
01 10 0D 05 00 01 02 00 00 7A C5(再写1,解除急停)
Recv->
01 10 0D 05 00 01 13 64

5.2.4 驱动重启H0D-00=1
Send->
01 10 31 00 00 01 02 00 00 86 93(伺服断使能,重启后自动恢复为0)
Send->
01 10 0D 00 00 01 02 00 01 BB 50(驱动重启)
Recv->
01 10 0D 00 00 01 03 65 (正确返回)
Recv->
01 90 04 4D C3 (从站设备故障,请先断使能)

5.3 读参数

5.3.1 读实际位置H0B-07(假设读取格式为CDAB,实际数据为ABCD)
Send->
01 03 0B 07 00 02 77 EE
Recv->
01 03 04 09 B2 00 00 59 88(当前位置为0x09B2=2482)

5.3.2 读故障代码H0B-34
Send->
01 03 0B 22 00 01 26 24
Recv->
01 03 02 07 40 BB 84 (Er.740编码器故障)
Recv->
01 03 02 E9 39 37 C6(Er.939动力线断线)

 

 5.3.3 读物理DO信号H0B-05
Send->
01 03 0B 05 00 01 96 2F
Recv->
01 03 02 00 1A 39 8F(上电默认,bit0-伺服准备好,bit2-零速信号)
Recv->
01 03 02 00 18 B8 4E(定位完成,bit1-定位完成,保持信号)
Recv->
01 03 02 00 08 B9 82(回原完成,bit4-原点回零完成,保持信号)

 

 

5.3.4 以当前位置为零点(位置=0)H05-30=6
Send->
01 10 05 1E 00 01 02 00 06 70 EC
Recv->
01 10 05 1E 00 01 61 03

6.CRC16计算方法

以C++为例,可参考以下代码:[i]

#include <cstdio>
#include <iostream>
using namespace std;

uint16_t CRC16(uint8_t* arr_buff, int len)
{
        uint16_t crc = 0xFFFF;
        uint16_t i, j, Data;
        for (j = 0; j<len; j++)
        {
                crc = crc ^*arr_buff++;
                for (i = 0; i<8; i++)
                {
                        if ((crc & 0x0001) >0)
                        {
                                crc = crc >> 1;
                                crc = crc ^ 0xa001;
                        }
                        else
                                crc = crc >> 1;
                }
        }
        return (crc);
}

void main()
{
        uint8_t dataIn[9] = { 0x01,0x10,0x31,0x00,0x00,0x01,0x02,0x00,0x01 };
        cout << "dataIn[" << sizeof(dataIn) << "]" << "= { ";
        for (int i = 0; i < sizeof(dataIn); i++)
        {
                printf("%02x ", dataIn[i]);
        }
        cout << "};" << endl;
        uint16_t Result = CRC16(dataIn, sizeof(dataIn));
        cout << "CRC16 Result : " << hex << Result%0x100 << " " << hex << Result/0x100 << endl;
        system("Pause");
}

[i]运行结果如下:

 

posted @ 2021-11-01 18:33  古道轻风  阅读(1859)  评论(0编辑  收藏  举报