条件:驱动器是汇川的SV660P,电机是MS1H4-40B30CB;
需求:需要用Modbus-RTU通讯控制电机,实现以下动作:
1.启动/关闭电机使能。
2.设置电机正向运行速度;
3.设置电机反向运行速度;
4.设置电机的加、减速度;
5.设置电机正向运行的步数;
6.设置电机反向运行的步数;
7.用外接对射光电开关,触发判断停止或运行;
8.让电机回到原点;(在驱动器DI1和DI2安装了正向和反向超程开关,以正向超程开关为触发回原点)
9.读取编码器的值;
10.读取接收超程报警信息;
11.读取驱动器报错、报警等信息;
以上设置和动作需要在PC的串口助手中,用指令来实现设置和控制。
楼主最近还看过
// 初始化Modbus RTU主站(需配置硬件接口)
"MB_MASTER_DB"(REQ := TRUE,
MB_ADDR := 1, // 驱动器站号
MB_BAUD := 9600, // 波特率
MB_PARITY := 0, // 无校验(8N1)
MB_DB := "Modbus_DB");
FUNCTION_BLOCK "FB_SV660P_Control"
VAR_INPUT
// 控制命令
Enable : BOOL; // 电机使能
Set_Speed_Pos : REAL; // 正向速度(rpm)
Set_Speed_Neg : REAL; // 反向速度(rpm)
Set_Accel : REAL; // 加速度(rpm/s²)
Set_Decel : REAL; // 减速度(rpm/s²)
Move_Pos_Steps : DINT; // 正向步数
Move_Neg_Steps : DINT; // 反向步数
Go_Home : BOOL; // 回原点命令
END_VAR
VAR_OUTPUT
Encoder_Value : DINT; // 编码器反馈
DI_Status : WORD; // DI状态(Bit0:DI1, Bit1:DI2, Bit2:光电)
Alarm_Code : INT; // 报警代码
Status : STRING[20]; // 状态信息
END_VAR
VAR
// Modbus通信临时变量
MB_Data : ARRAY[0..15] OF WORD;
MB_Error : WORD;
END_VAR
// 写入0x2000寄存器
IF Enable THEN
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#06, // 功能码06(写单寄存器)
ADDR := 16#2000, // 地址
COUNT := 1,
DATA_PTR := ADR(MB_Data));
MB_Data[0] := 1; // 1=使能
ELSE
MB_Data[0] := 0; // 0=关闭
END_IF;
// 正向速度(0x2001, 32位)
MB_Data[0] := WORD_TO_INT(REAL_TO_WORD(Set_Speed_Pos * 100)); // 转换为0.01rpm单位
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#10, // 功能码16(写多寄存器)
ADDR := 16#2001,
COUNT := 2,
DATA_PTR := ADR(MB_Data));
// 正向步数(0x2008)
MB_Data[0] := DINT_TO_WORD(Move_Pos_Steps);
MB_Data[1] := DINT_TO_WORD(Move_Pos_Steps SHR 16); // 高16位
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#10,
ADDR := 16#2008,
COUNT := 2,
DATA_PTR := ADR(MB_Data));
IF Go_Home THEN
// 1. 启动回零(0x200A=1)
MB_Data[0] := 1;
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#06,
ADDR := 16#200A,
COUNT := 1,
DATA_PTR := ADR(MB_Data));
// 2. 监控DI1(超程开关)
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#03,
ADDR := 16#3002, // DI状态地址
COUNT := 1,
DATA_PTR := ADR(DI_Status));
// 3. 停止条件
IF (DI_Status AND 16#01) <> 0 THEN // Bit0=DI1触发
Status := 'Home Done';
END_IF;
END_IF;
// 读取DI状态(0x3002)
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#03,
ADDR := 16#3002,
COUNT := 1,
DATA_PTR := ADR(DI_Status));
// 光电触发(Bit2)时急停
IF (DI_Status AND 16#04) <> 0 THEN
MB_Data[0] := 0; // 速度=0
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#06,
ADDR := 16#2001,
COUNT := 1,
DATA_PTR := ADR(MB_Data));
Status := 'Photo Stop';
END_IF;
// 读取报警代码(0x5000)
"MB_MASTER_DB"(REQ := TRUE,
FUNC := 16#03,
ADDR := 16#5000,
COUNT := 1,
DATA_PTR := ADR(Alarm_Code));
// 错误处理
IF Alarm_Code <> 0 THEN
Status := CONCAT('Error: ', INT_TO_STRING(Alarm_Code));
END_IF;
// 实例化功能块
"SV660P_CTRL"(
Enable := TRUE,
Set_Speed_Pos := 300.0, // 300rpm
Set_Accel := 100.0, // 100rpm/s²
Move_Pos_Steps := 10000, // 10000脉冲
Go_Home := TRUE); // 启动回零
// 获取输出
Encoder_Value := "SV660P_CTRL".Encoder_Value;
Alarm_Code := "SV660P_CTRL".Alarm_Code;
IF "MB_MASTER_DB".DONE THEN
// 处理成功
ELSIF "MB_MASTER_DB".ERROR THEN
Status := 'Comm Error';
END_IF;
IF Set_Speed_Pos > 3000.0 THEN
Set_Speed_Pos := 3000.0; // 限制最大速度
END_IF;
回复本条