CANopen对于运动控制来说是一款优秀的通讯协议,采用了面向对象的一些设计思路,比如对象字典,过程数据对象(PDO),服务数据对象(SDO)等等。CANopen定义了完整的同步控制机制,使其成为主流的运动控制协议,除了在CAN总线上运行外,还被搬到了以太网上(CANopen over Ethernet),形成了著名的PowerLink,EtherCat工业以太网协议(CoE)。
一般支持ethercat的驱动器用的都是CoE协议,在配置好PDO后,ethercat的domain中包含了映射的Object Dictionary数据,通过读写domain即可读写对象字典中的对应数据,其中最主要的两个参数( 控制字 和 状态字) 的简单使用如下:
控制字用于控制驱动器的各种状态切换(其中过程 0 和 过程 1 是还有 Error Occurs 都是自动切换的,其他状态切换一般需要通过写驱动器的控制字来完成):
各个状态的解释如下:
以下是各个状态切换的条件,其中 Bit0、Bit1 等所指的是控制字的对应位:
控制字各bit表示的含义:
状态字各bit表示的含义:
这是一段关于状态迁移的简易代码(读状态字并且写控制字):
switch(cmd)
{
case ServoCommandOFF: // init value: If in Switch_On_Disabled state, change to Ready_To_Switch On
{
output.control_word_ = 0x06; // operation: Shut down
break;
}
case ServoCommandON:
{
if( (input.status_word_ & 0x0040) == 0x0040 )
{
output.control_word_ = 0x06; // operation: Shut down
}
else if ( (input.status_word_&0x007f) == 0x0031 ) // FSA State: Ready to Switch On
{
output.control_word_ = 0x07; // operation: Switch On
}
break;
}
case ServoCommandEnable: // 上使能
{
if ( (input.status_word_&0x007b) == 0x0033 ) // FSA State: Switch On
{
output.control_word_ = 0x0f; // Enable Operation
}
else
{
output.control_word_ = 0x0b; // 急停, Quick Stop
}
break;
}
case ServoCommandDisable: // 下使能
{
output.control_word_ = 0x07; // Disable operation
break;
}
case ServoCommandEmeStop: // 急停
{
output.control_word_ = 0x0b; // 急停, Quick Stop
break;
}
case ServoCommandFaultReset: // 错误恢复, 错误恢复后需要重新使能
{
if( (input.error_code_!= 0) || (input.status_word_&0x0008) )
{
output.control_word_ = output.control_word_ | 0x0080;
}
else
{
output.control_word_ = output.control_word_ & 0xff7f;
}
break;
}
case ServoCommandHalt: // 暂停 Halt On; Warning!!! 在暂停驱动器之前确保控制器已经停止发送位置指令
{
output.control_word_ = output.control_word_ | 0x0100;
break;
}
case ServoCommandHaltReset: // 取消暂停 Halt Off, Warning!!!
{
output.control_word_ = output.control_word_ & 0xfeff;
// if ( (input.status_word_& 0x007f) == 0x0037) // FSA State: Operation enabled (正常工作状态) = Switch On + Enable Operation + Quick Stop Off + No warning + Voltage On
// {
// output.target_cmd_ = data_->out.pos;
// }
break;
}
default:
output.control_word_ = 0x0b; // 急停, Quick Stop
break;
}
当然,除了用一堆if…else也可以用有限状态机来实现,ref link: http://blog.csdn.net/gw569453350game/article/details/50427937