CANopen 某志驱动器, 撞击掉使能恢复正常状态
- 前言
- 数据手册介绍
- 控制状态机 0x6040
- 轮廓位置模式
- 调试过程的怀点
- 绝对位置模式下执行到指定位置
- 相对位置模式下执行到指定位置
- 撞击后自动复位处理函数
- 电机清故障码
- 清警告码
- 个人分析
- AI协助分析
- 为什么第二次必失败
- 快速验证方法
- 修改之后代码
- “完美解决-无论多少次撞击掉使能都恢复正常状态”
- 总结
- 一、整体流程(4 大步骤)
- 二、逐步骤指令明细(你代码真实执行顺序)
前言
在自动化设备调试中,我们经常会遇到这样的场景:设备发生撞机保护后,第一次复位一切正常;但第二次撞机后,电机就再也使能不上了。
最近在某志CANopen 驱动器的摆臂轴调试中就遇到了这个问题。撞击掉使能后,上位机下发恢复指令,下位机执行回原流程,但摆臂电机始终无法进入Operation Enabled状态。抓包发现状态字死死卡在0x0008。
本文将完整复盘这次排查过程,重点解析CiA402 标准状态机与厂商自定义寄存器(0x200B/0x2006)混用带来的致命陷阱,并给出经过验证的非阻塞式清故障+使能代码模板。
数据手册介绍
控制状态机 0x6040
轮廓位置模式
调试过程的怀点
以下为绝对位置模式和归零模式的代码,当时怀疑过有问题,但是第一次能够正常运行,为什么第二次不能正常的执行了呢?
绝对位置模式下执行到指定位置
/* 绝对位置模式下执行到指定位置*/voidAxis_Run_inABPositionMode(Axis_Var*Axis,uint32_tProfileVelocity,int32_tTargetPosition){switch(Axis->RunState){case0://增加这个步骤是为了Axis->RunState++;break;case1:Axis->i32TargetPosition=TargetPosition;Axis->u32ProfileVelocity=ProfileVelocity;Axis->RunState++;break;case2:Axis->i8Mode=0x01;Axis->u16ControlWord=0x1F;Axis->RunState++;break;case3:Axis->u16ControlWord=0x0F;Axis->RunState++;break;case4:/* 给电机一个状态变化的时间*/if(++Axis->RunTimes>=50){Axis->RunTimes=0;Axis->RunState++;}break;case5:if(((Axis->u16DSPStatus&(1<<3))>>3)&&(abs(Axis->i32ActualPosition-Axis->i32TargetPosition)<1000));/* 到位*/elseif((Axis->u16DSPStatus&(1<<9))>>9);/* 堵转*/elsereturn;Axis->RunState++;break;case6:Axis->RunState=RUN_FINISH;break;default:break;}}相对位置模式下执行到指定位置
/* 相对位置模式下执行到指定位置*/voidAxis_Run_inRLPositionMode(Axis_Var*Axis,uint32_tProfileVelocity,int32_tTargetPosition){switch(Axis->RunState){case0:Axis->i32TargetPosition=TargetPosition;Axis->u32ProfileVelocity=ProfileVelocity;Axis->RunState++;break;case1:Axis->i8Mode=0x01;Axis->u16ControlWord=0x5F;Axis->RunState++;break;case2:Axis->u16ControlWord=0x4F;Axis->RunState++;break;case3:/* 1S间隔*/if(++Axis->RunTimes>=100){Axis->RunTimes=0;Axis->RunState++;}break;case4:/* 到位判断*/if((Axis->u16DSPStatus&(1<<3))>>3);elsereturn;Axis->RunState++;break;case5:Axis->RunState=RUN_FINISH;break;default:break;}}撞击后自动复位处理函数
voidSystem_rehome(void){staticuint8_trehome_state=0;static_Axis_ AxisID=_Axis_Y;staticuint16_ttimes=0,errtimes=0,cnt=0,rehometimes=0;//计数器if(++cnt<20)return;cnt=0;switch(rehome_state){case0:if(1==Axis_ClearFault(AxisID)){rehome_state++;}break;case1:if(1==Axis_ClearWarnig(AxisID)