Simulink模型和Maxon EPOS4驱动器在倍福TwinCAT中接口文件的编写

Simulink模型和Maxon EPOS4驱动器在倍福TwinCAT中接口文件的编写

概要

笔者水平有限,以下说明中若有错误欢迎指正!

​ 笔者近期需要配置EPOS4驱动器和倍福TwinCAT的接口映射,本文主要介绍Simulink模型如何导入TwinCAT中作为PLC任务、Simulink模型输入输出与驱动器的接口文件如何编写以及接口文件代码编写所需的基础知识(CANopen总线、DSP402协议),如需浏览代码可直接跳转至最后,代码中有足够的注释,若有不懂的地方可再浏览前面的基础知识和参考链接。笔者有12个驱动器需要做映射,Simulink模型中的输入量为电机转速和电机转角,输出为电机力矩。


写接口前的准备

​ 前提:已正确配置TE1400模块,可以顺利导出Simulink模型到TwinCAT中,如何配置及导出模型参考上篇文章1,若希望Simulink模型作为一个控制器模型被PLC条件调用,即只有触发了输入条件才可以执行Simulink模型,回到Simulink模型,在Configuration中找到CallBy,设置为Module:

image-20240719093322570

​ 按照之前的文章设置System target file为TwinCAT.tlc,设置求解器为固定步长,设置好步长,之后对这个模型进行重新编译生成模型:

image-20240719093508826

​ 点击reload重新上载模型,把新的模型添加到TcCOM:

image-20240719093626131

​ 在解决方案管理器中在PLC处点击右键添加新项:

image-20240719102922922

​ 选择Standard PLC Project,命名并选择保存位置:

image-20240719103121030

​ 在新建的PLC下的project处右键,选择Import PLCopenXML:

image-20240719140114451

​ 找到刚才Simulink编译导出的C++文件夹中的PlcOpenPOUs.xml文件,点击打开:

image-20240719140212319

​ 直接点击OK即可:

image-20240719140340968

编程基础

​ 以下部分参考资料链接在最后,如果哪里有不懂建议阅读原书/原文档,推荐阅读《EtherCAT:工业以太网应用技术》2,CANopen轻松入门笔记3,DSP402驱动协议4
​ 若想进一步了解可参考EPOS4 Application Notes5,EPOS4 Communication Guide6,EPOS4 Firmware Specification7,EPOS4 Firmware Version «Readme»8,【Maxon驱动器与TwinCAT接口基础】EtherCAT通讯简介9

设备控制状态机

​ 伺服驱动器需要依据CiA 402描述的设备子协议进行控制,主站控制器通过修改6040h控制字(Control Word)来操作伺服驱动器的运行状态,同时通过读6041h状态字(Status Word)来获取驱动器的当前状态。
​ 状态机描述了控制器的状态以及主机的控制方式,是CiA 402伺服驱动器应用协议运行的基础,如下图所示:

在这里插入图片描述

​ 状态机的各状态说明见下表:

状态名称说明
未准备好接通电源
(Not Ready to Switch On)
控制器上电后,伺服驱动器进行初始化过程,在初始化未完成前,一直处于本状态
不可接通电源
(Switch On Disabled)
伺服驱动器初始化完成
准备好接通电源
(Ready to Switch On)
控制电已上,动力电使能开关关闭,电机无力矩
已开始供电
(Switched on)
动力电已上,电机无力矩,伺服驱动器已做好按配置功能控制电机的准备
可操作
(Operation Enable)
伺服驱动器按配置功能控制电机,电机有力矩输出
急停状态
(Quick Stop Activ)
伺服驱动器按照设定停机
出错反应
(Fault Reaction Activ)
驱动器内部报警,并按设定的运行方式停机,电机有力矩输出
出错
(Fault)
报警状态,电机无力矩

​ 状态转换由驱动器中的内部事件主站通过控制字发出的命令引起:

状态转换序号From To驱动器内部事件/从主站接收控制字动作
0开始 ⇒ \Rightarrow 未准备好接通电源驱动器复位(Reset)驱动器自检/自初始化
1未准备好接通电源 ⇒ \Rightarrow 不可接通电源驱动器自检/自初始化成功激活通讯
2不可接通电源 ⇒ \Rightarrow 准备好接通电源“Shutdown”指令
3准备好接通电源 ⇒ \Rightarrow 已开始供电“Switch on”指令上动力电
4已开始供电 ⇒ \Rightarrow 可操作“Enable Operation”指令驱动操作使能
5可操作 ⇒ \Rightarrow 已开始供电“Disable Operation”指令驱动操作去使能
6已开始供电 ⇒ \Rightarrow 准备好接通电源“Shutdown”指令关动力电
7准备好接通电源 ⇒ \Rightarrow 不可接通电源“Quick Stop”“Disable Voltage”指令
8可操作 ⇒ \Rightarrow 准备好接通电源“Shutdown”指令立即关闭动力电,若无抱闸,电机可自由旋转
9可操作 ⇒ \Rightarrow 不可接通电源“Disable Voltage”指令同上
10已开始供电 ⇒ \Rightarrow 不可接通电源“Quick Stop”“Disable Voltage”指令同上
11可操作 ⇒ \Rightarrow 急停状态“Quick Stop”指令执行急停功能
12急停状态 ⇒ \Rightarrow 不可接通电源急停完成或“Disable Voltage”指令关动力电
13所有状态 ⇒ \Rightarrow 出错反应驱动器中发生错误执行故障反应功能
14出错反应 ⇒ \Rightarrow 出错出错反应完成驱动操作去使能
15出错 ⇒ \Rightarrow 未准备好接通电源“Fault Reset”指令离开故障状态后,控制字的“Fault Reset”位必须由主站清除
16急停状态 ⇒ \Rightarrow 可操作“Enable Operation”指令驱动操作使能

​ 只要有报警状态出现,状态机将自动进入“出错”状态。控制器上电后,伺服驱动器将进行初始化,当初始化完成后,状态机自动切换到“不可接通电源”状态。

6040h控制字(ControlWord)

​ 控制字为16位,其中位0~3和位7构成了状态机跳转的控制字指令,各种跳转条件见下表,x代表任意:

指令位7
故障复位
位3
使能运行
位2
快速停机
位1
使能电源
位0
接通电源
控制字
位7~位0
对应转换
Fault Reset1xxxx1xxxxxxx15
Shutdown0x1100xxxx1102,6,8
Switch on001110xxx01113
Enable Operation011110xxx11114,16
Disable Operation001110xxx01115
Quick Stop0x01x0xxxx01x7,10,11
Disable Voltage0xx0x0xxxxx0x7,9,10,12

6041h状态字(StatusWord)

​ 状态字为16位,其中位0~3和位5、6代表了伺服驱动器状态机所处的状态,定义见下表,x代表任意:

状态位6
(Switch On Disabled)
位5
(Quick Stop Activ)
位3
(Fault)
位2
(Operation Enable)
位1
(Switched on)
位0
(Ready to Switch On)
状态字
位6~位0
未准备好接通电源
(Not Ready to Switch On)
0x00000xx0000
不可接通电源
(Switch On Disabled)
1x00001xx0000
准备好接通电源
(Ready to Switch On)
01000101x0001
已开始供电
(Switched on)
01001101x0011
可操作
(Operation Enable)
01011101x0111
急停状态
(Quick Stop Activ)
00011100x0111
出错反应
(Fault Reaction Activ)
0x11110xx1111
出错
(Fault)
0x10000xx1000

数据类型

数据类型数据描述数值区间占据位数
BOOL布尔值{0,1}(FALSE/TRUE)8(理论1位,实际1字节9
SINT有符号短整数-128~1278
INT有符号整数-32768~3276716
DINT有符号整数 − 2 32 − 1 -2^{32}-1 2321~ 2 32 − 1 2^{32}-1 232132
UINT无符号整数0~6553516
REAL32位浮点数 − 3.4 × 1 0 38 -3.4\times 10^{38} 3.4×1038~ 3.4 × 1 0 38 3.4\times 10^{38} 3.4×103832
LREAL64位浮点数 − 1.8 × 1 0 308 -1.8\times 10^{308} 1.8×10308~ 1.8 ∗ 1 0 308 1.8*10^{308} 1.81030864

编写接口程序

​ 由于CSDN不支持Structured Text语言高亮,想看代码高亮可自行下载VSCode-ST语言插件。首先声明程序中用到的常量,常量在系统初始化完成后,只能进行读操作,不能赋值:

PROGRAM MAIN
VAR CONSTANT	//定义常量
	PI : REAL:=3.141592653;
END_VAR

​ 在TcCOM中加载的模型上双击查看模型的Object ID:

image-20240719100614425

​ 对于模型接口功能块进行变量声明,在oid中输入TcCOM中模型的object ID:

VAR
	fb_test	:	FB_testSimulinkModel(oid:=16#01010010);
END_VAR

image-20240719100638707

​ 随后在程序中就可以调用相应的method进行模型调用,并且也可以直接访问到输入输出等参数进行赋值。

image-20240719100804593

​ 最后分配模型的Task为PlcTask(必须和所调用的PLC的Task一致):

image-20240719100850948

最终接口程序

PROGRAM MAIN
//程序说明
//将12个电机分为4组,每组3个电机;从根部到底部为1~4组,第1组为ECi52,28Nm;第2~4组为ECi40,18Nm;
//修改System_Enable的数值可以指令使能第几组电机
//修改EnableJointFlag的数值可以指令使能第几个电机
//SystemReadyCount变量统计每一组中电机使能成功的数量
//修改modechange的值调整电机的控制方式,0:速度环;1:电流环
//速度环时,修改Label的值可直接通过手柄操控各电机运动,1~4对应第1~4组电机,按键映射见下
VAR CONSTANT	
	PI : REAL:=3.141592653;									 //声明常量数值
END_VAR

VAR
	fb_test	:	FB_testSimulinkModel(oid:=16#01010010);
	input:BOOL:=TRUE;						                 //条件调用PLC,input为真,使能模型
	(****** Enable command ******)
	System_Enable   : ARRAY [1..4] OF BOOL:=[1,1,1,1];       //12个电机分为4组,每一组的使能标志
    EnableJointFlag : ARRAY [1..4, 1..3] OF BOOL := [        //输入标志,指示是否尝试使能电机
        [1, 1, 1], 
        [1, 1, 1], 
        [1, 1, 1], 
        [1, 1, 1]
    ];
    Enable_Succeed   : ARRAY [1..4, 1..3] OF BOOL;	         //输出标志,指示电机是否成功进入操作使能状态
	StatusWord      : ARRAY [1..4, 1..3] OF UINT;            //12个驱动器的状态字组合成二维数组
    ControlWord     : ARRAY [1..4, 1..3] OF UINT;            //12个驱动器的控制字组合成二维数组
	SystemReadyCount1 : INT:=0;								 //统计第1组电机使能成功数量
	SystemReadyCount2 : INT:=0;								 //统计第2组电机使能成功数量
	SystemReadyCount3 : INT:=0;								 //统计第3组电机使能成功数量
	SystemReadyCount4 : INT:=0;								 //统计第4组电机使能成功数量

	ActualVelocity	: ARRAY[1..4, 1..3] OF LREAL;			 //12个电机输出端编码器反馈角速度(rad/s)
	ActualPosition	: ARRAY[1..4, 1..3] OF LREAL;			 //12个电机输出端编码器反馈角度(rad)
	TargetVelocity	: ARRAY[1..3]		OF DINT;			 //D速度环单独调整每组电机输出端期望角速度(pulses/s)

	//	从根部到端部分为第1~4组,第1组为ECi52,28Nm;第2~4组为ECi40,18Nm
	Label   :   INT:=0;                                       //控制单独动哪一组关节
    group   :   INT;                                          //计数变量,第group组电机,每组3个
	i       :   INT;                                          //计数变量,每组第i个电机
	MotorReductionRatio		:	INT:=	100;				  //电机齿轮箱减速比
	modechange				:	INT:=	  0;				  //modechange切换电机控制方式,0:速度环;1:电流环

	//	绝对编码器初始位置
	Position_Initial1 : ARRAY[1..6] OF DINT:=[0,0,0,0,0,0]; 
	Position_Initial2 : ARRAY[1..6] OF DINT:=[0,0,0,0,0,0]; 
	Position_Initial3 : ARRAY[1..6] OF DINT:=[0,0,0,0,0,0];
	Position_Initial4 : ARRAY[1..6] OF DINT:=[0,0,0,0,0,0];
	
	//	手柄各键的变量映射
	Key1	:DINT;						//	Y		键
	Key2	:DINT;						//	B		键
	Key3	:DINT;						//	A		键
	Key4	:DINT;						//	X		键
	Key5	:DINT;						//	LB		键
	Key6	:DINT;						//	RB		键
	L1		:DINT;						//	LT		键
	L2		:DINT;						//	BACK	键
	R1		:DINT;						//	T		键
	R2		:DINT;						//	START	键
	
END_VAR

VAR_INPUT
	 接收驱动器的输入 
	Statusword_1			AT %I*: ARRAY[1..3] OF UINT;
	StatusWord_2			AT %I*: ARRAY[1..3] OF UINT;
	StatusWord_3			AT %I*: ARRAY[1..3] OF UINT;
	StatusWord_4			AT %I*: ARRAY[1..3] OF UINT;
	ActualVelocity1		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc/s 每秒脉冲数
	ActualVelocity2		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc/s 每秒脉冲数
	ActualVelocity3		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc/s 每秒脉冲数
	ActualVelocity4		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc/s 每秒脉冲数
	ActualPosition1		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc	脉冲数
	ActualPosition2		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc	脉冲数
	ActualPosition3		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc	脉冲数
	ActualPosition4		    AT %I*: ARRAY[1..3] OF DINT; // unit: Inc	脉冲数
	TorqueActualValue1	    AT %I*: ARRAY[1..3] OF INT;	 // unit: 28/1000 N*m
	TorqueActualValue2	    AT %I*: ARRAY[1..3] OF INT;	 // unit: 16/1000 N*m
	TorqueActualValue3	    AT %I*: ARRAY[1..3] OF INT;	 // unit: 16/1000 N*m
	TorqueActualValue4	    AT %I*: ARRAY[1..3] OF INT;	 // unit: 16/1000 N*m
	
END_VAR

VAR_OUTPUT
	 向驱动器输出目标值 
	ControlWord_1			AT %Q*: ARRAY[1..3] OF UINT;
	ControlWord_2			AT %Q*: ARRAY[1..3] OF UINT;
	ControlWord_3			AT %Q*: ARRAY[1..3] OF UINT;
	ControlWord_4			AT %Q*: ARRAY[1..3] OF UINT;
	TargetVelocity1		    AT %Q*: ARRAY[1..3] OF DINT; // unit: 1000rpm
	TargetVelocity2		    AT %Q*: ARRAY[1..3] OF DINT; // unit: 1000rpm
	TargetVelocity3		    AT %Q*: ARRAY[1..3] OF DINT; // unit: 1000rpm
	TargetVelocity4		    AT %Q*: ARRAY[1..3] OF DINT; // unit: 1000rpm
	ModeOfOperation1		AT %Q*: ARRAY[1..3] OF SINT; // 9:速度环,10:力矩环
	ModeOfOperation2		AT %Q*: ARRAY[1..3] OF SINT; 
	ModeOfOperation3		AT %Q*: ARRAY[1..3] OF SINT; 
	ModeOfOperation4		AT %Q*: ARRAY[1..3] OF SINT; 
	TargetTorque1		    AT %Q*: ARRAY[1..3] OF INT:=[0,0,0,0,0,0]; // unit: 28/1000 N*m
	TargetTorque2		    AT %Q*: ARRAY[1..3] OF INT:=[0,0,0,0,0,0]; // unit: 16/1000 N*m
	TargetTorque3		    AT %Q*: ARRAY[1..3] OF INT:=[0,0,0,0,0,0]; // unit: 16/1000 N*m
	TargetTorque4		    AT %Q*: ARRAY[1..3] OF INT:=[0,0,0,0,0,0]; // unit: 16/1000 N*m
END_VAR

//变量声明结束

//逻辑计算开始

IF input THEN
	fb_test.Execute();                                                      //input为真,则调用之前定义的功能块实例(Simulink模型)
END_IF

(******分成4组,每组3个电机******)

FOR i:=1 TO 3 BY 1 DO
	StatusWord[1, i] := StatusWord_1[i];                                    //将驱动器输入的状态字写入StatusWord二维数组中
	StatusWord[2, i] := StatusWord_2[i];
	StatusWord[3, i] := StatusWord_3[i];
	StatusWord[4, i] := StatusWord_4[i];
END_FOR

//读状态字,根据状态字发控制字,使能电机
FOR group   :=  1   TO  4   BY  1   DO                                      //遍历四组电机
    FOR i   :=  1	TO	3	BY	1	DO								        //每一组从1到3遍历
	    IF	System_Enable[group] = 1	    THEN							//检验第一组作为整个系统是否使能
		    IF  (EnableJointFlag[group,i])	THEN						    //检验第一组中每个电机是否使能

                //状态字和2#1001111按位与操作,校验状态字的位7、位3、位2、位1、位0,根据当前状态和状态转换条件发送控制字
                //检验状态字是否为Fault状态(2#0xx1000)
			    IF  (StatusWord[group, i] AND (2#1001111))=2#0001000	THEN	
				    ControlWord[group, i]:=2#10000000;					    //若为Fault状态,则Reset Fault,控制字2#1xxxxxx
			    END_IF

                //检验状态字是否为Switch On Disabled状态(2#1xx0000)
			    IF  (StatusWord[group, i] AND (2#1001111))=2#1000000	THEN	
				    Controlword[group, i]:=2#00000110;                      //若为Switch On Disabled状态,则Shutdown,控制字2#0xxxx110
                    Enable_Succeed[group, i]:=FALSE;                        //使能标志为FALSE
			    END_IF

                //状态字和2#1101111按位与操作,校验状态字的位7、位6、位3、位2、位1、位0,根据当前状态和状态转换条件发送控制字
                //检验状态字是否为Ready to Switch On状态(2#01x0001)
                IF  (StatusWord[group, i] AND (2#1101111))=2#0100001    THEN    
                    ControlWord[group, i]:=2#00000111;                      //若为Ready to Switch On状态,则Switch On,控制字(2#0xxx0111)
                END_IF

                //检验状态字是否为Switched On状态(2#01x0011)
                IF  (StatusWord[group, i] AND (2#1101111))=2#0100011    THEN    
                    ControlWord[group, i]:=2#00001111;                      //若为Switched On状态,则Enable Operation,控制字(2#0xxx1111)
                END_IF
                
                //检验状态字是否为Operation Enable状态(2#01x0111)
                IF  (StatusWord[group, i] AND (2#1101111))=2#0100111    THEN    
                    Enable_Succeed[group, i]:=TRUE;                         //使能成功,标志为TRUE
                END_IF  
            ELSE
                    ControlWord[group, i]:=2#00000110;                      //电机使能标志为0,即EnableJointFlag_1[i1]=0,则Shutdown,控制字2#0xxxx110
		    END_IF
        END_IF
    END_FOR
END_FOR

FOR i:=1 TO 3 BY 1 DO
	ControlWord_1[i] := ControlWord[1, i];                                  //将ControlWord二维数组按对应关系写入各组控制字中输出
	ControlWord_2[i] := ControlWord[2, i];
	ControlWord_3[i] := ControlWord[3, i];
	ControlWord_4[i] := ControlWord[4, i];
END_FOR

//统计每组电机中使能成功的电机数量
FOR i:=1 TO 3 BY 1 DO
	IF Enable_Succeed[1, i]=TRUE THEN
		SystemReadyCount1 := SystemReadyCount1+1;
	END_IF
	IF Enable_Succeed[2, i]=TRUE THEN
		SystemReadyCount2 := SystemReadyCount2+1;
	END_IF
	IF Enable_Succeed[3, i]=TRUE THEN
		SystemReadyCount3 := SystemReadyCount3+1;
	END_IF
	IF Enable_Succeed[4, i]=TRUE THEN
		SystemReadyCount4 := SystemReadyCount4+1;
	END_IF
END_FOR

//	以下为手柄控制接口,调节单组电机,Key1对应Y键,Key2对应B键,Key3对应A键
IF (R2=1) THEN								//对应手柄Start键按下,各电机正向转动
	IF (Key1=1) THEN						//Y键按下,电机1正转
		TargetVelocity[1]:=200000;
	ELSE
		TargetVelocity[1]:=0;
	END_IF
	IF (Key2=1) THEN						//B键按下,电机2正转
		TargetVelocity[2]:=200000;
	ELSE
		TargetVelocity[2]:=0;
	END_IF
	IF (Key3=1) THEN						//A键按下,电机3正转
		TargetVelocity[3]:=200000;
	ELSE
		TargetVelocity[3]:=0;
	END_IF
ELSE										//对应手柄Start键未按下,各电机反向转动
	IF (Key1=1) THEN						//Y键按下,电机1反转
		TargetVelocity[1]:=-200000;
	ELSE
		TargetVelocity[1]:=0;
	END_IF
	IF (Key2=1) THEN						//B键按下,电机2反转
		TargetVelocity[2]:=-200000;
	ELSE
		TargetVelocity[2]:=0;
	END_IF
	IF (Key3=1) THEN						//A键按下,电机3反转
		TargetVelocity[3]:=-200000;
	ELSE
		TargetVelocity[3]:=0;
	END_IF
END_IF

// 通过修改Label值,调节第Label组电机
IF (Label = 1) OR (Label = 2) OR (Label = 3) OR (Label = 4) THEN
    CASE Label OF
        1: // 设置TargetVelocity1
            TargetVelocity1 := TargetVelocity;
        2: // 设置TargetVelocity2
            TargetVelocity2 := TargetVelocity;
        3: // 设置TargetVelocity3
            TargetVelocity3 := TargetVelocity;
        4: // 设置TargetVelocity4
            TargetVelocity4 := TargetVelocity;
    END_CASE;
END_IF;

// 1为电流环,0位速度环
IF modechange=1 THEN
	FOR i:=1 TO 3 BY 1 DO
		ModeOfOperation1[i]:=10;
		ModeOfOperation2[i]:=10;
		ModeOfOperation3[i]:=10;
		ModeOfOperation4[i]:=10;
	END_FOR
ELSE
	FOR i:=1 TO 3 BY 1 DO
		ModeOfOperation1[i]:=9;
		ModeOfOperation2[i]:=9;
		ModeOfOperation3[i]:=9;
		ModeOfOperation4[i]:=9;
	END_FOR
END_IF

//	速度单位转换:每秒脉冲数 --> rad/s,单圈19位编码器,每转2^19=524288个脉冲,转数乘2*PI转换为rad,除以减速比得到输出端速度
//	角度单位转换:脉冲数	--> rad,单圈19位编码器,每转2^19=524288个脉冲,转数乘2*PI转换为rad,减速比只影响角速度,角度无须除以减速比
FOR i:=1 TO 3 DO			//遍历每组的三个电机

	ActualVelocity[1, i]	:=	DINT_TO_LREAL(ActualVelocity1[i])/524288*2*PI/MotorReductionRatio;
	ActualVelocity[2, i]	:=	DINT_TO_LREAL(ActualVelocity2[i])/524288*2*PI/MotorReductionRatio;
	ActualVelocity[3, i]	:=	DINT_TO_LREAL(ActualVelocity3[i])/524288*2*PI/MotorReductionRatio;
	ActualVelocity[4, i]	:=	DINT_TO_LREAL(ActualVelocity4[i])/524288*2*PI/MotorReductionRatio;

	ActualPosition[1, i]	:=	DINT_TO_LREAL(ActualPosition1[i]-Position_Initial1[i])/524288*2*PI;
	ActualPosition[2, i]	:=	DINT_TO_LREAL(ActualPosition2[i]-Position_Initial2[i])/524288*2*PI;
	ActualPosition[3, i]	:=	DINT_TO_LREAL(ActualPosition3[i]-Position_Initial3[i])/524288*2*PI;
	ActualPosition[4, i]	:=	DINT_TO_LREAL(ActualPosition4[i]-Position_Initial4[i])/524288*2*PI;

END_FOR

//	角速度(rad/s)赋值给Simulink模型的输入,在TwinCAT3中手动设置映射
fb_test.stInput.velocity1_1	:=	ActualVelocity[1, 1];
fb_test.stInput.velocity1_2	:=	ActualVelocity[1, 2];
fb_test.stInput.velocity1_3	:=	ActualVelocity[1, 3];

fb_test.stInput.velocity2_1	:=	ActualVelocity[2, 1];
fb_test.stInput.velocity2_2	:=	ActualVelocity[2, 2];
fb_test.stInput.velocity2_3	:=	ActualVelocity[2, 3];

fb_test.stInput.velocity3_1	:=	ActualVelocity[3, 1];
fb_test.stInput.velocity3_2	:=	ActualVelocity[3, 2];
fb_test.stInput.velocity3_3	:=	ActualVelocity[3, 3];

fb_test.stInput.velocity4_1	:=	ActualVelocity[4, 1];
fb_test.stInput.velocity4_2	:=	ActualVelocity[4, 2];
fb_test.stInput.velocity4_3	:=	ActualVelocity[4, 3];


//	角度(rad)赋值给Simulink模型的输入,在TwinCAT3中手动设置映射
fb_test.stInput.position1_1	:=	ActualPosition[1, 1];
fb_test.stInput.position1_2	:=	ActualPosition[1, 2];
fb_test.stInput.position1_3	:=	ActualPosition[1, 3];

fb_test.stInput.position2_1	:=	ActualPosition[2, 1];
fb_test.stInput.position2_2	:=	ActualPosition[2, 2];
fb_test.stInput.position2_3	:=	ActualPosition[2, 3];

fb_test.stInput.position3_1	:=	ActualPosition[3, 1];
fb_test.stInput.position3_2	:=	ActualPosition[3, 2];
fb_test.stInput.position3_3	:=	ActualPosition[3, 3];

fb_test.stInput.position4_1	:=	ActualPosition[4, 1];
fb_test.stInput.position4_2	:=	ActualPosition[4, 2];
fb_test.stInput.position4_3	:=	ActualPosition[4, 3];

//转矩单位转换,将Simulink模型中输出的转矩(N*m)转换为电机转矩(千分之一额定转矩)
//	ECi40-36V 输出端额定转矩16N*m,ECi52-36V 额定转矩28N*m
TargetTorque1[1]:=LREAL_TO_INT(fb_test.stOutput.torque1_1/28*1000);
TargetTorque1[2]:=LREAL_TO_INT(fb_test.stOutput.torque1_2/28*1000);
TargetTorque1[3]:=LREAL_TO_INT(fb_test.stOutput.torque1_3/28*1000);

TargetTorque2[1]:=LREAL_TO_INT(fb_test.stOutput.torque2_1/16*1000);
TargetTorque2[2]:=LREAL_TO_INT(fb_test.stOutput.torque2_2/16*1000);
TargetTorque2[3]:=LREAL_TO_INT(fb_test.stOutput.torque2_3/16*1000);

TargetTorque3[1]:=LREAL_TO_INT(fb_test.stOutput.torque3_1/16*1000);
TargetTorque3[2]:=LREAL_TO_INT(fb_test.stOutput.torque3_2/16*1000);
TargetTorque3[3]:=LREAL_TO_INT(fb_test.stOutput.torque3_3/16*1000);

TargetTorque4[1]:=LREAL_TO_INT(fb_test.stOutput.torque4_1/16*1000);
TargetTorque4[2]:=LREAL_TO_INT(fb_test.stOutput.torque4_2/16*1000);
TargetTorque4[3]:=LREAL_TO_INT(fb_test.stOutput.torque4_3/16*1000);




  1. 倍福TE1400组件安装指南:https://blog.csdn.net/weixin_43807835/article/details/140323746 ↩︎

  2. 《EtherCAT 工业以太网控制技术》(豆瓣):https://book.douban.com/subject/35077018/ ↩︎

  3. 《CANopen轻松入门笔记》:https://pan.quark.cn/s/eaf6869011b6 ↩︎

  4. dsp402协议(英文原版):https://pan.quark.cn/s/a3db4d87ac0f ↩︎

  5. EPOS4 Application Notes:https://pan.quark.cn/s/a257526dcecc ↩︎

  6. EPOS4 Communication Guide:https://pan.quark.cn/s/5951eaf2047a ↩︎

  7. EPOS4 Firmware Spacification:https://pan.quark.cn/s/8c44e6abb4d0 ↩︎

  8. EPOS4 Firmware Version 《Readme》:https://pan.quark.cn/s/8c44e6abb4d0 ↩︎

  9. 为什么C语言中bool型变量占用一个字节:https://blog.csdn.net/LANGQING12345/article/details/40623241 ↩︎ ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值