#define _IN_MOTOS_C //------------------------------------------------------------------------------- #include "motos.h" #include "stm32motos.h" #include "inout.h" //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- const u16 g_axisIDList[AXIS_NUM] = { AXIS_ID1, AXIS_ID2, AXIS_ID3, AXIS_ID4, AXIS_ID5, AXIS_ID6, }; //------------------------------------------------------------------------------- // 初始化电机 void InitMotos(void) { InitSTM32Motos(); #if (STM32_MOTOS_NUM >= 1) InitStm32Moto1OutFunc(SetMoto1PulseOn, SetMoto1PulseOff, SetMoto1SignOn, SetMoto1SignOff); #endif #if (STM32_MOTOS_NUM >= 2) InitStm32Moto2OutFunc(SetMoto2PulseOn, SetMoto2PulseOff, SetMoto2SignOn, SetMoto2SignOff); #endif #if (STM32_MOTOS_NUM >= 3) InitStm32Moto3OutFunc(SetMoto3PulseOn, SetMoto3PulseOff, SetMoto3SignOn, SetMoto3SignOff); #endif #if (STM32_MOTOS_NUM >= 4) InitStm32Moto4OutFunc(SetMoto4PulseOn, SetMoto4PulseOff, SetMoto4SignOn, SetMoto4SignOff); #endif #if (STM32_MOTOS_NUM >= 5) InitStm32Moto5OutFunc(SetMoto5PulseOn, SetMoto5PulseOff, SetMoto5SignOn, SetMoto5SignOff); #endif #if (STM32_MOTOS_NUM >= 6) InitStm32Moto6OutFunc(SetMoto6PulseOn, SetMoto6PulseOff, SetMoto6SignOn, SetMoto6SignOff); #endif memset(&g_motosPara, 0, sizeof(MotosPara)); // 设置电机参数 } // 读取电机位置 int GetMotosCounter(s32 * position) { int i; if (position != NULL) { for (i = 0; i < AXIS_NUM; i++) { position[i] = GetAxisCounter(g_axisIDList[i]); } } return 0; } // 设置电机位置 void SetMotosCounter(s32 * position) { int i; for (i = 0; i < AXIS_NUM; i++) { if (position != NULL) { SetAxisCounter(g_axisIDList[i], position[i]); } else { SetAxisCounter(g_axisIDList[i], 0); } } } // 刷新坐标 void RefreshMotosPos(s32 * poslist) { // 全部刷新 int i; for (i = 0; i < AXIS_NUM; i++) { g_motosPara.motosPos[i] = poslist[i]; } g_motosPara.enFlag = DATA_VALID; } //------------------------------------------------------------------------------- s32 GetMotoCounter(int axisIdx) { assert_param(axisIdx < AXIS_NUM); return GetAxisCounter(g_axisIDList[axisIdx]); } void SetMotoCounter(int axisIdx, s32 pos) { assert_param(axisIdx < AXIS_NUM); SetAxisCounter(g_axisIDList[axisIdx], pos); } //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- void MotoServoCtrl(int axisIdx, int onoff) { assert_param(onoff == SERVO_ON || onoff == SERVO_OFF); if (axisIdx < AXIS_NUM) { SetAxisConfig(g_axisIDList[axisIdx], onoff); } } // 设置电机配置 void SetMotosConfig(MotosConfig * pConfig) { int i; u16 axisID; if (pConfig == NULL) { return; } if (pConfig->newConfig == 0) { return; } // 停止运行 StopVAxisRun(VAXIS_ID_ALL); for (i = 0; i < AXIS_NUM; i++) { axisID = g_axisIDList[i]; if ((pConfig->axisConfig[i].axisConfig & CONFIG_EN) != 0) // 配置允许 { if ((pConfig->axisConfig[i].axisConfig & POA_EN) != 0) // A允许输出 { SetAxisConfig(axisID, POUTA_EN); } else { SetAxisConfig(axisID, POUTA_DIS); } if ((pConfig->axisConfig[i].axisConfig & POB_EN) != 0) // B允许输出 { SetAxisConfig(axisID, POUTB_EN); } else { SetAxisConfig(axisID, POUTB_DIS); } if ((pConfig->axisConfig[i].axisConfig & SON_EN) != 0) // 伺服ON允许 { SetAxisConfig(axisID, SERVO_ON); } else { SetAxisConfig(axisID, SERVO_OFF); } if ((pConfig->axisConfig[i].axisConfig & ALM_LEVH) != 0) // 报警电平为高 { SetAxisAlarmConfig(axisID, ALM_LEV_HIGH); } else { SetAxisAlarmConfig(axisID, ALM_LEV_LOW); } if ((pConfig->axisConfig[i].axisConfig & ALM_EN) != 0) // 报警停车允许 { SetAxisAlarmConfig(axisID, ALM_STOP_EN); } else { SetAxisAlarmConfig(axisID, ALM_STOP_DIS); } if ((pConfig->axisConfig[i].axisConfig & POUT_EN) != 0) // 输出允许 { SetAxisConfig(axisID, pConfig->axisConfig[i].poutType); // 脉冲输出模式 脉冲方式输出 SetAxisConfig(axisID, pConfig->axisConfig[i].spdSource); // 实轴速度控制模式(虚轴1,虚轴2,虚轴3,编码器) SetAxisConfig(axisID, pConfig->axisConfig[i].datSource); // 实轴数据获取模式(硬件插补,编码器随动,编码器映射) } else { SetAxisConfig(axisID, POUT_DISABLE); // 禁止脉冲输出 } } } SetVAxisConfig(VCTR_AXIS_ALM_INT); // 清除报警状态 } //------------------------------------------------------------------------------- // 计算加减速需要的位移 // 参数: pps1 速度1 // pps2 速度2 // calcTime 速度变化时间,单位为1/72us // 返回: // 位移值 // 条件,速度变化量固定为1ppg u32 CalcDisplacement(u32 pps1, u32 pps2, u32 calcTime) { // 速度变化量固定为1ppg // 公式: d=(v2+v1)*(v2-v1)/(2a) // v1 = pps1 // v2 = pps2 // a = 1ppg/(calcTime/FPGA_CLK) // 最终 d=(v2+v1)*(v2-v1)*calcTime/(2*FPGA_CLK) double temp; if (pps1 < pps2) { temp = (pps2-pps1); } else { temp = (pps1-pps2); } temp *= (pps1+pps2); temp *= calcTime; temp /= (2*FPGA_CLK); return (u32)(temp+0.5); } // 功能:计算某位移下速度变化需要的时间间隔参数(单位为1/72us) // 参数: // disp 位移 // pps1 速度1 // pps2 速度2 // // 返回: // 位移值 // 条件,速度变化量固定为1ppg u32 CalcGapTime(u32 disp, u32 pps1, u32 pps2) { double temp; // 速度变化量固定为1ppg // 公式: a=(v2+v1)*(v2-v1)/(2*d) // v1 = pps1 // v2 = pps2 // d = disp // a = 1ppg/(calcTime/FPGA_CLK) // 最终 calcTime= (2*FPGA_CLK)*d/((v2+v1)*(v2-v1)) if (disp == 0 || pps1 == pps2) { return 0; } if (pps1 < pps2) { temp = (pps2-pps1); } else { temp = (pps1-pps2); } temp *= (pps1+pps2); temp = (2.0*FPGA_CLK)/temp; temp *= disp; return (u32)(temp+0.5); } // 计算某位移和某加速度下,最终的速度值 // 参数: // disp 位移 // pps1 速度1 // addgap 时间间隔 // // 返回: // 位移值 // 条件,速度变化量固定为1ppg u32 CalcEndSpd(u32 disp, u32 pps1, s32 addgap) { double temp; // 速度变化量固定为1ppg // 公式: a=(v2+v1)*(v2-v1)/(2*d) // v1 = pps1 // d = disp // a = 1ppg/(addgap/FPGA_CLK) // 最终 pps2 = sqrt(2*FPGA_CLK*disp/addgap + pps1*pps1) temp = 2.0*FPGA_CLK*disp/addgap; temp += 1.0*pps1*pps1; if (temp > 0) { temp = sqrt(temp); } else { temp = 0; } return (u32)(temp+0.5); } //-------------------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:多轴直线插补运动控制(硬件实现),最多支持6轴直线插补,支持虚轴1或虚轴2控制 // 参数:插补控制结构指针 // 结果: 0,运动执行完成。 // -1,输入参数错误 // -2,执行过程中填充数据不及时错误退出 // -3 fpga 读写错误 // -4 FPGA 版本错误 // =1, 驱动器报警停车 // =2, 紧急停止条件触发停车 // =3, 快速停止条件触发停车 // =4, 普通停车条件触发停车 #if (1) int InterpolationMotion(InterMoveCtrl * pCtrl) { int i, rslt; u32 totalnum, circlenum, circlesize, lastsize; // 运动总量,循环总次数,切换表个数,一般表的长度,最后一个表的长度 u32 runcircle, execcircle, runrepeat, exerepeat; // 运动段数,执行段数,运动重复次数,执行重复次数 u32 runcount; u32 pulsePerSegment; u16 vAxisId; u16 vAxisCleanOv1, vAxisCleanOv2; u16 vAxisBuf1Finish, vAxisBuf2Finish; u16 vAxisBuf1Running, vAxisBuf2Running; // u16 vAxisBuf1En, vAxisBuf2En; u16 vAxisDisBuf1, vAxisDisBuf2; u32 movement[AXIS_NUM], count[AXIS_NUM]; s32 val32, position[AXIS_NUM]; int dir[AXIS_NUM]; // 各个轴的运动方向 int runsta, bufsta, bufsel; int slowSta; int brksta, inbrk; // 刹车状态,正在刹车标志 int nstpsta, innstp; // 刹车状态,正在刹车标志 int stopfill; // 停止填充数据标志 u16 tmp16, vrsta, err; double calc, len; u16 outNum; u32 startpps, runpps, slowpps, stoppps; // 速度 u32 addppsg, decppsg, brkppsg, tslppsg; // 加速度 u32 num, addnum, decnum, jumpnum; // 加减速需要的脉冲个数 u32 curtab1num, curtab2num; VAxisCmdStr vAxisCmd; InterData idata; num = 0; // ------------------------------------------------------------------------ // 参数合法性判断 if (pCtrl == NULL) { printf("para error in MotosRun\r\n"); rslt = -1; // 输入参数错误 return rslt; } if (pCtrl->vAxisId != VAXIS_ID1) { printf("para vAxisId error in MotosRun\r\n"); rslt = -1; // 输入参数错误 return rslt; } for (i = 0; i < AXIS_NUM; i++) // 统一实轴速度来源 { pCtrl->motosConfig.axisConfig[i].spdSource = MAKE_POUT_CMD(pCtrl->vAxisId); } // 选择参与电机 SetMotosConfig(&(pCtrl->motosConfig)); // 等待驱动器执行 if (pCtrl->Delay != NULL && pCtrl->motosConfig.newConfig != 0) { pCtrl->Delay(100); } // ------------------------------------------------------------------------ if (pCtrl->GetEmergencyStop != NULL) // 紧急停止条件函数 { err = pCtrl->GetEmergencyStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; printf("emergency stop 1 in InterpolationMotion, err=0x%x\r\n", err); rslt = 2; // 紧急停止条件触发停车,立刻停止脉冲发送 return rslt; } } if (pCtrl->GetQuickStop != NULL) // 出错停止条件函数 { err = pCtrl->GetQuickStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; printf("quick stop 1 in InterpolationMotion, err=0x%x\r\n", err); rslt = 3; // 快速停止条件触发停车 return rslt; } } if (pCtrl->GetNormalStop != NULL) // 一般停止 { err = pCtrl->GetNormalStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; printf("normal stop 1 in InterpolationMotion, err=0x%x\r\n", err); rslt = 4; // 普通停车条件触发停车 return rslt; } } // 速度控制参数 startpps = pCtrl->spdPara.startPPS; runpps = pCtrl->spdPara.runPPS; slowpps = pCtrl->spdPara.slowPPS; stoppps = pCtrl->spdPara.stopPPS; addppsg = pCtrl->spdPara.addPPSG; decppsg = pCtrl->spdPara.decPPSG; brkppsg = pCtrl->spdPara.brkPPSG; tslppsg = pCtrl->spdPara.brkPPSG*TOSLOWMUTI; if (startpps == 0 || runpps == 0 || slowpps == 0 || stoppps == 0 || addppsg == 0 || decppsg == 0 || brkppsg == 0 || tslppsg == 0) { printf("one of speed para is zero \r\n"); printf("startpps = %d, runpps = %d, slowpps = %d, stoppps = %d, addppsg = %d, decppsg = %d, brkppsg = %d\r\n", startpps, runpps, slowpps, stoppps, addppsg, decppsg, brkppsg); rslt = -1; return rslt; } vAxisId = pCtrl->vAxisId; if (vAxisId == VAXIS_ID1) { vAxisCleanOv1 = VCTR_VAXIS1_CLEAN_OV1; vAxisCleanOv2 = VCTR_VAXIS1_CLEAN_OV2; vAxisBuf1Finish = VAXIS1_BUF1_FINISH; vAxisBuf2Finish = VAXIS1_BUF2_FINISH; vAxisBuf1Running = VAXIS1_BUF1_RUNNING; vAxisBuf2Running = VAXIS1_BUF2_RUNNING; // vAxisBuf1En = VAXIS1_BUF1_ENABLE; // vAxisBuf2En = VAXIS1_BUF2_ENABLE; vAxisDisBuf1 = VCTR_VAXIS1_DIS_BUF1; vAxisDisBuf2 = VCTR_VAXIS1_DIS_BUF2; } else { printf("not support vaxis\r\n"); } // 计算最大位移 totalnum = 0; // 脉冲个数 circlenum = 0; // 周期数 circlesize = 0; // 每个循环周期的数量 lastsize = 0; // 最后一个周期的数量 runrepeat = pCtrl->mvmtPara.extraRepeat; exerepeat = pCtrl->mvmtPara.extraRepeat; // 得到实轴最大位移,作为最长轴 for (i = 0; i < AXIS_NUM; i++) { if (pCtrl->mvmtPara.movement[i] >= 0) { movement[i] = (u32)(pCtrl->mvmtPara.movement[i]); dir[i] = 1; } else { movement[i] = (u32)(-(pCtrl->mvmtPara.movement[i])); dir[i] = -1; } // printf("axis %d movement = %d.\r\n", i+1, movement[i]); if (totalnum < movement[i]) { totalnum = movement[i]; } /* if (pCtrl->interLongSel == LAS_COMPOSITE) // 几个轴的合成长度 { calc = movement[i]; calc *= calc; len += calc; } else { } */ count[i] = 0; } totalnum = pCtrl->mvmtPara.interLong; pulsePerSegment = pCtrl->mvmtPara.pulsePerSegment; /* if (pCtrl->interLong == LAS_COMPOSITE) // 几个轴的合成长度 { len = sqrt(len); totalnum = (u32)(len+0.5); } */ if (totalnum == 0) { printf("move count = 0. run over\r\n"); return -1; } else if (totalnum < 2) { circlenum = 1; circlesize = totalnum; lastsize = totalnum; } else if (totalnum < pulsePerSegment*2) // 小于2个最大位图周期, 将其分为均匀的两个部分 { circlenum = 2; circlesize = (totalnum)/2; lastsize = totalnum-circlesize; } else { circlenum = (totalnum + pulsePerSegment-1)/pulsePerSegment; circlesize = pulsePerSegment; lastsize = totalnum-circlesize*(circlenum-1); } #if (0) if (pCtrl->stopMode == STOP_MODE_TAB) // 整点停止模式下,长轴数据大于一个表时,必须为整表 { if (lastsize != circlesize && totalnum > ) { printf("totalnum is not equal to circle nun\r\n"); return 0; } } #endif // printf("calc para. circlenum=%d, circlesize=%d, lastsize=%d\r\n", circlenum, circlesize, lastsize); if (circlenum == 0 || circlesize == 0 || lastsize == 0) { printf("calc error. circlenum=%d, circlesize=%d, lastsize=%d\r\n", circlenum, circlesize, lastsize); return -1; } // 速度控制参数 addnum = CalcDisplacement(startpps, runpps, addppsg); // 加速脉冲数 decnum = CalcDisplacement(stoppps, runpps, decppsg); // 减速脉冲数 // printf("before run, start=%d, stop=%d, runing=%d, \r\n\taddppsg=%d, addnum=%d, decppsg=%d, decnum=%d\r\n",startpps, stoppps, runpps, addppsg, addnum, decppsg, decnum); if ((totalnum < addnum + decnum) || ((totalnum < (addnum + decnum + pulsePerSegment)) && (addnum%pulsePerSegment) != 0) || 0 ) { // 重新计算 加速脉冲个数,最高速度,和减速脉冲个数 calc = addnum; calc /= (addnum + decnum); calc *= totalnum; // 按照比例,加速脉冲的个数 calc /= pulsePerSegment; // 加速圈数 addnum = (u32)calc; if (addnum != 0) { addnum *= pulsePerSegment; // 取整的脉冲数 } else { addnum = totalnum / 2; } len = addnum*2; len *= FPGA_CLK; len /= addppsg; len -= startpps; calc = startpps; calc *= startpps; len += calc; calc = sqrt(len); // 加速脉冲数 runpps = (u32)(calc+0.5); decnum = CalcDisplacement(stoppps, runpps, decppsg); // 重新计算减速脉冲数 // printf("recalc addnum=%d, runpps=%d, decnum=%d\r\n", addnum, runpps, decnum); } // 控制循环 runsta = 0; bufsel = 0; bufsta = 0; slowSta = 0; brksta = 0; inbrk = 0; nstpsta = 0; innstp = 0; stopfill = 0; // 停止填充数据标志 runcircle = circlenum; // 计算计数 execcircle = circlenum; // 执行计数 runcount = 0; jumpnum = 0; pCtrl->errInfo = 0; curtab1num = 0; curtab2num = 0; rslt = 0; if (pCtrl->WorkBeforeRun != NULL) { pCtrl->WorkBeforeRun(pCtrl->workPara1, pCtrl->workPara2); } SetVAxisConfig(VCTR_AXIS_ALM_INT); // 清除报警状态 memset(&idata, 0, sizeof(InterData)); while(execcircle > 0 || exerepeat > 0) // 执行未完成 { if ( stopfill == 0 && // 允许填充数据 (bufsta & 0x03) != 0x03 && // 有buff空闲 (runcircle != 0 || runrepeat != 0) && // 数据未完成 1 ) { if (runcircle == 1) // 最后一圈计算 { num = lastsize; if (runrepeat == 0) { runsta = 1; // 最后一圈减速 } } else { num = circlesize; if (runrepeat == 0 && (runsta == 0 && decnum > lastsize)) // 如果减速需要脉冲个数大于最后一圈的位移 { if ((runcircle-1) <= (decnum-lastsize+circlesize-1)/circlesize) { runsta = 1; // 减速标志 } } } runcount += num; if (runsta == 1) // 计算减速点 { if (decnum > lastsize) { jumpnum = num - (decnum - lastsize) % num; } else { jumpnum = lastsize - decnum; } if (jumpnum >= num) { jumpnum = 0; } if (decnum != 0) { decnum = decnum - (num - jumpnum); } // printf("jumpnum=%d, decnum=%d\r\n", jumpnum, decnum); } for (i = 0; i < AXIS_NUM; i++) // 写各个轴的插补数据 { if (movement[i] != 0) { if (bufsel == 0) { idata.bufSel = BUF_SEL1; } else { idata.bufSel = BUF_SEL2; } // 计算该段插补需要的实轴数据 //-------------------------- idata.vaxisId = vAxisId; // 使用虚轴1 if (dir[i] >= 0) // 方向 { idata.dirAttr = DIR_POSPOS; // 正向 } else { idata.dirAttr = DIR_NEGNEG; // 反向 } idata.datBufLen = 1+1; // 有效段个数: 1 idata.axisId = g_axisIDList[i]; idata.startEscNum = 0; idata.partVxNum = num; calc = movement[i]; calc *= runcount; calc /= totalnum; calc -= count[i]; outNum = (u16)(calc+0.5); count[i] += outNum; idata.datBuff[0] = outNum; // 第一段数据 idata.datBuff[1] = 0; // 结束段写0 idata.sineOut = 0; //printf("%d.datBuff[0]=%d\r\n", i+1, idata.datBuff[0]); rslt = WriteInterData(&idata); if (rslt < 0) { return rslt; } // printf("axis %d wt, c=%d, ac=%d\r\n", i+1, outNum, count[i]); if (runcount >= totalnum) { count[i] = 0; } } else { if (bufsel == 0) { CleanAxisBuff(g_axisIDList[i], BUF_SEL1); } else { CleanAxisBuff(g_axisIDList[i], BUF_SEL2); } } } if (runcount >= totalnum) { runcount = 0; } // 启动运动, 虚轴命令 vAxisCmd.vaxisId = vAxisId; // 使用虚轴 if (bufsel == 0) { bufsta |= 0x01; vAxisCmd.bufSel = BUF_SEL1; curtab1num = num; // printf("write buff1\r\n"); } else { bufsta |= 0x02; vAxisCmd.bufSel = BUF_SEL2; curtab2num = num; // printf("write buff2\r\n"); } if (runsta == 0) { // printf("write add vtable\r\n"); vAxisCmd.startPPS = startpps; // 启动速度 vAxisCmd.runPPS = runpps; // 运行速度 vAxisCmd.jumpNum = 0; // 跳过脉冲数 vAxisCmd.calcGap = addppsg; // 计算时间 } else { // printf("write dec vtable, jump=%d\r\n", jumpnum); vAxisCmd.startPPS = stoppps; // 启动速度 vAxisCmd.runPPS = stoppps; // 运行速度 vAxisCmd.jumpNum = jumpnum; // 跳过脉冲数 vAxisCmd.calcGap = decppsg; // 计算时间 } vAxisCmd.outNum = num; // 表的脉冲个数 StartVAxisRun(&vAxisCmd); // 写运行命令 // 得到虚轴运行状态 // printf("At%d, StartVAxisRun, vrsta=0x%x, vrsta1=0x%x\r\n", Get100UsSoftTimer(), GetRunStatus(), GetRunStatus1()); runcircle--; // 计算计数减小 if (runcircle == 0) { if (runrepeat != 0) { runrepeat--; runcircle = circlenum; } } bufsel = ~bufsel; // 切换buf } // 等待运动结束 rslt = 0; do { err = 0; //---------- if (slowSta != 0 && slowpps != pCtrl->spdPara.slowPPS) { printf("reset slowsta when speed change\r\n"); slowSta = 0; } slowpps = pCtrl->spdPara.slowPPS; // 更新降速速度 //---------- { int count = 100; do { // 得到虚轴运行状态 tmp16 = GetRunStatus(); vrsta = GetRunStatus(); // printf("1. run sta =0x%x\r\n", vrsta); while(tmp16 != vrsta) // 稳定的值 { // printf("1. run sta not same, old=0x%x, new=0x%x\r\n", tmp16, vrsta); tmp16 = vrsta; vrsta = GetRunStatus(); } if ( (vrsta & (vAxisBuf1Finish|vAxisBuf1Running)) != (vAxisBuf1Finish|vAxisBuf1Running) && (vrsta & (vAxisBuf2Finish|vAxisBuf2Running)) != (vAxisBuf2Finish|vAxisBuf2Running) ) // 完成标志和运行标志不可能同时有效,这时有可能是读取错误 { break; } printf("1. rd sta err, sta=0x%x, count=%d\r\n", vrsta, 100-count); }while(count--); if (count == 0) { printf("rd fpga data timout\r\n"); StopVAxisRun(vAxisId); rslt = -3; // fpga 读写错误 break; } if ((vrsta & vAxisBuf1Finish) != 0) // 虚轴缓冲区1数据执行完成标志 { SetVAxisConfig(vAxisCleanOv1); // 清除表1完成标志 bufsta &= 0xFE; // 释放buf1 execcircle--; if (execcircle == 0) { if (exerepeat != 0) { exerepeat--; execcircle = circlenum; } } curtab1num = 0; // printf("At%d, table 1 ok, vrsta=0x%x, vsta=0x%x, vrsta1=0x%x\r\n", GetUsSoftTimer(), vrsta, GetRunStatus(), GetRunStatus1()); } if ((vrsta & vAxisBuf2Finish) != 0) // 虚轴缓冲区2数据执行完成标志 { SetVAxisConfig(vAxisCleanOv2); // 清除表2完成标志 bufsta &= 0xFD; // 释放buf2 execcircle--; if (execcircle == 0) { if (exerepeat != 0) { exerepeat--; execcircle = circlenum; } } curtab2num = 0; // printf("At%d, table 2 ok, vrsta=0x%x, vsta=0x%x, vrsta1=0x%x\r\n", GetUsSoftTimer(), vrsta, GetRunStatus(), GetRunStatus1()); } if ((vrsta & AXIS_ALARM_FLAG) != 0) // 实轴报警标志 { err = GetAlarmValue(); // 得到轴报警信息 SetVAxisConfig(VCTR_AXIS_ALM_INT); // 清除状态 StopVAxisRun(vAxisId); if (err != 0) { printf("1. axis alarm value=0x%x\r\n", err); } rslt = 1; // 驱动器报警停车 break; } else if ((vrsta & (vAxisBuf1Running | vAxisBuf2Running)) == 0) // 两个缓冲区的数据都执行完成,没有有效数据 { #if (0) temp16 = GetRunStatus1(); if ((temp16 & (vAxisBuf1En|vAxisBuf2En)) == 0) #endif { // printf("At%d, no more data in two buff in InterpolationMotion\r\n", GetUsSoftTimer()); StopVAxisRun(vAxisId); if (pCtrl->stopMode == STOP_MODE_TAB) { // printf("stop at tab end\r\n"); if (brksta == 1) { rslt = 3; // 快速停止条件触发停车,执行完一个缓冲区数据 } else // if (nstpsta == 1) { rslt = 4; // 普通停车条件触发停车,执行完一个缓冲区数据 } } else { // printf("stop when spd low, execcircle=%d,exerepeat=%d\r\n", execcircle, exerepeat); if (execcircle == 0 && exerepeat == 0) { /* * 20221124 * 数据执行完成的优先级高 * 如果停止条件触发,但降速完成后数据恰好执行完成,则认为是正常停车,而非停止条件停车 */ rslt = 0; } else { rslt = -2; // 无有效数据,退出 } } break; } } } // 停止条件判断 if (pCtrl->GetEmergencyStop != NULL) // 急停条件函数 { err = pCtrl->GetEmergencyStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; StopVAxisRun(vAxisId); printf("1. emergency stop 3, err=0x%x\r\n", err); rslt = 2; // 紧急停止条件触发停车,立刻停止脉冲发送 break; } } if (inbrk != 0 || (brksta != 1 && pCtrl->GetQuickStop != NULL)) // 快停条件函数 { if (inbrk == 0) { err = pCtrl->GetQuickStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; // printf("quick stop in InterpolationMotion, err=0x%x\r\n", err); } } if (err != 0 || inbrk != 0) { // 计算从当前速度降速到停止需要的位移 if (pCtrl->stopMode == STOP_MODE_TAB) { u32 curpps, curmvmt, decCount, resdcount; curpps = GetVAxisPPS(vAxisId); // 当前速度 decCount = CalcDisplacement(curpps, stoppps, brkppsg); // 计算以当前运行速度减速到停止速度需要的位移 curmvmt = GetVAxisCounter(vAxisId); // 当前表运行进度 // 运行状态 tmp16 = GetRunStatus(); vrsta = GetRunStatus(); while(tmp16 != vrsta) { // printf("3. run sta not same, old=0x%x, new=0x%x\r\n", tmp16, vrsta); tmp16 = vrsta; vrsta = GetRunStatus(); } // printf("cur vaxis counter=%d, vrsta=0x%x\r\n", curmvmt, vrsta); resdcount = 0; if (decCount > (curtab1num+curtab2num-curmvmt)) // 减速需要脉冲数大于已填充数据 { inbrk = 1; // 设置进入降速状态,但需要继续填充数据和计算减速点 } else { // 判断当前运行的表是那个表 if ((vrsta & vAxisBuf1Running) != 0) // 表1正在执行 { if (decCount < (curtab1num-curmvmt)) { resdcount = (curtab1num-curmvmt); SetVAxisConfig(vAxisDisBuf2); // 取消掉表2的已填充数据 } } else if ((vrsta & vAxisBuf2Running) != 0) // 表2正在执行 { if (decCount < (curtab2num-curmvmt)) { resdcount = (curtab2num-curmvmt); SetVAxisConfig(vAxisDisBuf1); // 取消掉表1的已填充数据 } } if (resdcount == 0) { resdcount = (curtab1num+curtab2num-curmvmt); } brkppsg = CalcGapTime(decCount*num, curpps, stoppps); // 按照新位移,重新计算刹车加速度 inbrk = 0; // 不再进入 stopfill = 1; // 不再填充数据 } } // 立即降速 brksta = 1; // 设置刹车车状态 vAxisCmd.vaxisId = vAxisId; vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = brkppsg; vAxisCmd.runPPS = stoppps; vAxisCmd.startPPS = stoppps; // 进入快速降速,停止过程 StartVAxisRun(&vAxisCmd); } } if (innstp != 0 || nstpsta != 1) // 一般停止条件函数 { if (innstp == 0 && nstpsta != 1) { if (pCtrl->GetNormalStop != NULL) { err = pCtrl->GetNormalStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->errInfo = err; // printf("normal stop 2 in InterpolationMotion, err=0x%x\r\n", err); } } } if (err != 0 || innstp != 0) { // 计算从当前速度降速到停止需要的位移 if (pCtrl->stopMode == STOP_MODE_TAB) { u32 curpps, curmvmt, decCount, resdcount; curpps = GetVAxisPPS(vAxisId); // 当前速度 decCount = CalcDisplacement(curpps, stoppps, decppsg); // 计算以当前运行速度减速到停止速度需要的位移 curmvmt = GetVAxisCounter(vAxisId); // 当前表运行进度 // 运行状态 tmp16 = GetRunStatus(); vrsta = GetRunStatus(); while(tmp16 != vrsta) { // printf("4. run sta not same, old=0x%x, new=0x%x\r\n", tmp16, vrsta); tmp16 = vrsta; vrsta = GetRunStatus(); } // printf("cur vaxis counter=%d, vrsta=0x%x\r\n", curmvmt, vrsta); resdcount = 0; if (decCount > (curtab1num+curtab2num-curmvmt)) // 减速需要脉冲数大于已填充数据 { innstp = 1; // 设置进入降速状态,但需要继续填充数据和计算减速点 } else { // 判断当前运行的表是那个表 if ((vrsta & vAxisBuf1Running) != 0) // 表1正在执行 { if (decCount < (curtab1num-curmvmt)) { resdcount = (curtab1num-curmvmt); SetVAxisConfig(vAxisDisBuf2); // 取消掉表2的已填充数据 } } else if ((vrsta & vAxisBuf2Running) != 0) // 表2正在执行 { if (decCount < (curtab2num-curmvmt)) { resdcount = (curtab2num-curmvmt); SetVAxisConfig(vAxisDisBuf1); // 取消掉表1的已填充数据 } } if (resdcount == 0) { resdcount = (curtab1num+curtab2num-curmvmt); } decppsg = CalcGapTime(decCount*num, curpps, stoppps); // 按照新位移,重新计算刹车加速度 innstp = 0; // 不再进入 stopfill = 1; // 不再填充数据 } } // 立即降速 nstpsta = 1; // 设置停车状态 vAxisCmd.vaxisId = vAxisId; vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = decppsg; vAxisCmd.runPPS = stoppps; vAxisCmd.startPPS = stoppps; // 进入快速降速,停止过程 StartVAxisRun(&vAxisCmd); } } if (pCtrl->GetSlowDown != NULL) // 降速 { tmp16 = pCtrl->GetSlowDown(pCtrl->condPara1, pCtrl->condPara2); if (tmp16 != 0) { if (slowSta == 0) // 非降速状态 { slowSta = 1; // 设置为降速状态 // printf("in slow down sta, slowpps=%d, tslppsg=%d\r\n", slowpps, tslppsg); vAxisCmd.vaxisId = vAxisId; //使用虚轴 vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = tslppsg; vAxisCmd.runPPS = slowpps; vAxisCmd.startPPS = slowpps; StartVAxisRun(&vAxisCmd); // 处理降速 } } else { if (slowSta == 1) // 在降速状态 { slowSta = 0; // printf("out slow down sta\r\n"); StopSpdCtrl(vAxisId); // 恢复正常速度 } } } // 刹车 if ((brksta == 1 || nstpsta == 1) && pCtrl->stopMode == STOP_MODE_SPD) // 停止刹车状态,且是速度低于停止频率立刻停车模式 { val32 = GetVAxisPPS(vAxisId); // 读取当前虚轴的运行频率 if (val32 <= stoppps) // 频率小于停止频率,立刻停止 { if (brksta == 1) { rslt = 3; // 快速停止条件触发停车,速度低于停车速度 } else // if (nstpsta == 1) { rslt = 4; // 普通停车条件触发停车,速度低于停车速度 } break; } else { // printf(">stoppps\r\n"); } } // 更新坐标 if (GetMotosCounter(position) == 0) { RefreshMotosPos(position); // 更新各个轴的位置 if (pCtrl->RefreshPosition != NULL) { pCtrl->RefreshPosition(pCtrl->refPosPara, position); } } else { rslt = 5; } }while(0); // exerepeat == 0 && execcircle == 1); if (rslt != 0) { break; } } StopVAxisRun(vAxisId); if (pCtrl->WorkAfterRun != NULL) { pCtrl->WorkAfterRun(pCtrl->workPara1, pCtrl->workPara2); } if (pCtrl->Delay != NULL) { // pCtrl->Delay(100); } // 更新坐标 if (GetMotosCounter(position) == 0) { RefreshMotosPos(position); // 更新各个轴的位置 if (pCtrl->RefreshPosition != NULL) { pCtrl->RefreshPosition(pCtrl->refPosPara, position); } } else { rslt = 5; } if (rslt == 0) { pCtrl->errInfo = 0; } return rslt; } #endif //------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------ // 功能:多轴连续直线插补运动控制,最多支持6轴的运动。 支持虚轴1或虚轴2控制 // 参数:连续插补控制结构指针 // 结果: 0,运动执行完成。 // -1,输入参数错误 // -2,执行过程中填充数据不及时错误退出 // -3 FPGA 读写错误 // -4 FPGA 版本错误 // =1, 驱动器报警停车 // =2, 紧急停止条件触发停车 // =3, 快速停止条件触发停车 // =4, 普通停车条件触发停车 // =5,电机坐标获取错误 #if (1) int ContinuousInterpolation(ContinuousInterMoveCtrl * pCtrl) { int i, j, rslt, err; int bufsta, bufsel; // 缓冲区状态,缓冲区选择 u16 vrsta, tmp16; // 虚轴运行状态 u16 vAxisId; u32 decPPSG, decCount; u16 vAxisCleanOv1, vAxisCleanOv2; u16 vAxisBuf1Finish, vAxisBuf2Finish; // 虚轴缓冲区1完成标志,虚轴缓冲区2完成标志 u16 vAxisBuf1Running, vAxisBuf2Running; // 虚轴缓冲区1正在执行标志,虚轴缓冲区2正在执行标志 // u16 vAxisDisBuf1, vAxisDisBuf2; s32 position[AXIS_NUM]; VAxisCmdStr vAxisCmd; InterData idata; // ------------------------------------------------------------------------ // 参数合法性判断 if (pCtrl == NULL) { printf("para error in ContinuousInterpolation\r\n"); rslt = -1; // 输入参数错误 return rslt; } if (pCtrl->vAxisId != VAXIS_ID1) { printf("para vAxisId error in ContinuousInterpolation\r\n"); rslt = -1; // 输入参数错误 return rslt; } for (i = 0; i < AXIS_NUM; i++) // 统一实轴速度来源 { pCtrl->motosConfig.axisConfig[i].spdSource = MAKE_POUT_CMD(pCtrl->vAxisId); } // ------------------------------------------------------------------------ if (pCtrl->GetEmergencyStop != NULL) // 紧急停止条件函数 { err = pCtrl->GetEmergencyStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->mvData.errInfo = err; printf("emergency stop 1 in ContinuousInterpolation, err=0x%x\r\n", err); rslt = 2; // 紧急停止条件触发停车,立刻停止脉冲发送 return rslt; } } if (pCtrl->GetQuickStop != NULL) // 出错停止条件函数 { err = pCtrl->GetQuickStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->mvData.errInfo = err; printf("quick stop 1 in ContinuousInterpolation, err=0x%x\r\n", err); rslt = 3; // 快速停止条件触发停车 return rslt; } } if (pCtrl->GetNormalStop != NULL) // 一般停止 { err = pCtrl->GetNormalStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->mvData.errInfo = err; printf("normal stop 1 in ContinuousInterpolation, err=0x%x\r\n", err); rslt = 4; // 普通停车条件触发停车 return rslt; } } // 选择参与电机 SetMotosConfig(&(pCtrl->motosConfig)); // 等待驱动器执行 if (pCtrl->Delay != NULL && pCtrl->motosConfig.newConfig != 0) { pCtrl->Delay(100); } bufsta = 0; bufsel = 0; decCount = 0; pCtrl->mvData.fillLimit = 0; decPPSG = MIN_GAP; pCtrl->mvData.errInfo = 0; vAxisId = pCtrl->vAxisId; if (vAxisId == VAXIS_ID1) { vAxisCleanOv1 = VCTR_VAXIS1_CLEAN_OV1; vAxisCleanOv2 = VCTR_VAXIS1_CLEAN_OV2; vAxisBuf1Finish = VAXIS1_BUF1_FINISH; vAxisBuf2Finish = VAXIS1_BUF2_FINISH; vAxisBuf1Running = VAXIS1_BUF1_RUNNING; vAxisBuf2Running = VAXIS1_BUF2_RUNNING; // vAxisDisBuf1 = VCTR_VAXIS1_DIS_BUF1; // vAxisDisBuf2 = VCTR_VAXIS1_DIS_BUF2; } else { printf("not support vaxis\r\n"); } if (pCtrl->WorkBeforeRun != NULL) { pCtrl->WorkBeforeRun(pCtrl->workPara1, pCtrl->workPara2); } SetVAxisConfig(VCTR_AXIS_ALM_INT); // 清除报警状态 memset(&idata, 0, sizeof(InterData)); do { pCtrl->mvData.bufsta = bufsta; // 刷新数据 if (pCtrl->RefreshData != NULL) { rslt = pCtrl->RefreshData(pCtrl->refDatPara, (u32)(&(pCtrl->mvData))); } // 更新坐标 if (GetMotosCounter(position) == 0) { RefreshMotosPos(position); // 更新各个轴的位置 if (pCtrl->RefreshPosition != NULL) { pCtrl->RefreshPosition(pCtrl->refPosPara, position); } } else { rslt = 5; break; } // 填充数据 if ((bufsta & 0x03) != 0x03 && pCtrl->mvData.mvmtStatus != 0) // 当Buff有空闲,并且还有数据时 { if (pCtrl->mvData.runstat != CRST_BREAK || pCtrl->mvData.fillLimit > 0) // 非刹车过程 或 在刹车过程中且允许填充数据 { if (pCtrl->mvData.fillLimit > 0) { pCtrl->mvData.fillLimit--; } // 写各个轴的插补数据 for (i = 0; i < AXIS_NUM; i++) { if (pCtrl->mvData.mvmtdat.segmnetNum[i] != 0) // 有效段数 { idata.datBufLen = pCtrl->mvData.mvmtdat.segmnetNum[i]; // 有效段个数 // 计算该段插补需要的实轴数据 //-------------------------- idata.axisId = g_axisIDList[i]; // 实轴选择 idata.vaxisId = vAxisId; // 使用虚轴 if (bufsel == 0) // 缓冲区选择 { idata.bufSel = BUF_SEL1; // 缓冲区1 } else { idata.bufSel = BUF_SEL2; // 缓冲区2 } idata.startEscNum = pCtrl->mvData.mvmtdat.startEsc[i]; // 起始跳过脉冲数 idata.partVxNum = pCtrl->mvData.mvmtdat.vppSegment[i]; // 每段对应的虚轴脉冲数 //---------------- 20220531 修改每段脉冲数限制 if ((idata.partVxNum * SUPPORT_SEGMENT) < pCtrl->mvData.mvmtdat.interLong) { idata.partVxNum = (pCtrl->mvData.mvmtdat.interLong+SUPPORT_SEGMENT-1) / SUPPORT_SEGMENT; } //----------------- 20220531 修改每段脉冲数限制 idata.dirAttr = AXIS_DIR_USEBUF; // 使用段内方向 // 填充多段数据 for (j = 0; j < pCtrl->mvData.mvmtdat.segmnetNum[i]; j++) { idata.datBuff[j] = pCtrl->mvData.mvmtdat.movement[i][j]; // 数据段 } idata.datBuff[j] = 0; idata.datBufLen += 1; idata.sineOut = pCtrl->mvData.mvmtdat.sineOut[i]; // 正弦输出模式 //printf("HEX:%d.datBuff[0]=0x%x\r\n", i+1, idata.datBuff[0]); //printf("DEC:%d.datBuff[0]=%d\r\n", i+1, idata.datBuff[0]); rslt = WriteInterData(&idata); if (rslt < 0) { return rslt; } //printf("axis %d wt, c=%d\r\n", i+1, idata.datBuff[0]); } else { if (bufsel == 0) { CleanAxisBuff(g_axisIDList[i], BUF_SEL1); } else { CleanAxisBuff(g_axisIDList[i], BUF_SEL2); } } } // 启动运动, 虚轴命令 vAxisCmd.vaxisId = vAxisId; // 使用虚轴 if (bufsel == 0) { bufsta |= 0x01; vAxisCmd.bufSel = BUF_SEL1; // curtab1num = pCtrl->mvData.interLong; // printf("write buff1\r\n"); } else { bufsta |= 0x02; vAxisCmd.bufSel = BUF_SEL2; // curtab2num = pCtrl->mvData.interLong; // printf("write buff2\r\n"); } // printf("write add vtable\r\n"); vAxisCmd.startPPS = pCtrl->mvData.lowPPS; // 启动速度 vAxisCmd.runPPS = pCtrl->mvData.runPPS; // 运行速度 vAxisCmd.jumpNum = 0; // 跳过脉冲数 vAxisCmd.calcGap = pCtrl->mvData.calcGap; // 计算时间 vAxisCmd.outNum = pCtrl->mvData.mvmtdat.interLong; // 插补轴的脉冲个数 rslt = StartVAxisRun(&vAxisCmd); // 写运行命令 if (rslt < 0) { break; } bufsel = ~bufsel; // 切换buf pCtrl->mvData.fillCount++; // 填充数据计数增加 // pCtrl->mvData.runIdx++; // 运行计数器 pCtrl->mvData.mvmtStatus = 0; // 设置数据执行标志 } } // 等待运动结束 rslt = 0; err = 0; { // 得到虚轴运行状态 // 为了得到一个正确的运行状态 tmp16 = GetRunStatus(); vrsta = GetRunStatus(); while(tmp16 != vrsta) { // printf("5. run sta not same, old=0x%x, new=0x%x\r\n", tmp16, vrsta); tmp16 = vrsta; vrsta = GetRunStatus(); } tmp16 = GetRunStatus(); vrsta = GetRunStatus(); while(tmp16 != vrsta) { // printf("6. run sta not same, old=0x%x, new=0x%x\r\n", tmp16, vrsta); tmp16 = vrsta; vrsta = GetRunStatus(); } if ((vrsta & (vAxisBuf1Finish|vAxisBuf2Finish)) != 0) // 虚轴缓冲区1或2完成 { if (pCtrl->mvData.runstat != CRST_NORMAL) // 处于进入停止状态或刹车状态时,执行完一个表后,重新计算加速度 { s32 inmvmt; // 调整减速速度 u32 curpps = GetVAxisPPS(vAxisId); // 当前速度 inmvmt = decCount; // inmvmt -= 1; if (inmvmt > 0) { inmvmt *= pCtrl->mvData.mvmtdat.interLong; // 重新计算加速度 decPPSG = CalcGapTime(inmvmt, curpps, pCtrl->mvData.lowPPS); // printf("pCtrl->mvData.runstat=%d, curpps=%d, mvmt=%d, lopps=%d, recalc decPPSG=%d\r\n", pCtrl->mvData.runstat, curpps, inmvmt, pCtrl->mvData.lowPPS, decPPSG); vAxisCmd.vaxisId = vAxisId; // 使用虚轴 vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = decPPSG; vAxisCmd.runPPS = pCtrl->mvData.lowPPS; vAxisCmd.startPPS = pCtrl->mvData.lowPPS; rslt = StartVAxisRun(&vAxisCmd); // 减速 if (rslt < 0) { break; } } } if ((vrsta & vAxisBuf1Finish) != 0) // 虚轴缓冲区1完成标志 { SetVAxisConfig(vAxisCleanOv1); // 清除表1完成标志 bufsta &= 0xFE; // 释放buf1 pCtrl->mvData.execCount++; // 已执行数据增加 pCtrl->mvData.lastEndPPS = GetLastVAxisFrequency(vAxisId); pCtrl->mvData.exeingIdx = pCtrl->dataBegIndex+pCtrl->mvData.emptyCount+pCtrl->mvData.execCount; // 正在执行数据的索引(另外一个表的数据) = 数据起始+跳过数据+已经执行数据 // printf("table 1 ok, datidx=%d, endpps=%d\r\n", iddx, pCtrl->mvData.lastEndPPS); // printf("table 1 ok, exeingidx=%d, endpps=%d\r\n", pCtrl->mvData.exeingIdx, pCtrl->mvData.lastEndPPS); if (pCtrl->mvData.runstat == CRST_BREAK) // 进入减速后,第一次切换表开始减速 { if (decCount != 0) { decCount--; // 减速执行圈数减少 } // printf("in break, table 1 ok, exeingIdx=%d, decCount=%d, endpps=%d\r\n", pCtrl->mvData.exeingIdx, decCount, pCtrl->mvData.lastEndPPS); } } if ((vrsta & vAxisBuf2Finish) != 0) // 虚轴缓冲区2完成标志 { SetVAxisConfig(vAxisCleanOv2); // 清除表2完成标志 bufsta &= 0xFD; // 释放buf2 pCtrl->mvData.execCount++; // 已执行数据增加 pCtrl->mvData.lastEndPPS = GetLastVAxisFrequency(vAxisId); pCtrl->mvData.exeingIdx = pCtrl->dataBegIndex+pCtrl->mvData.emptyCount+pCtrl->mvData.execCount; // 正在执行数据的索引(另外一个表的数据) = 数据起始+跳过数据+已经执行数据 // printf("table 2 ok, datidx=%d, endpps=%d\r\n", iddx, pCtrl->mvData.lastEndPPS); // printf("table 2 ok, exeingidx=%d, endpps=%d\r\n", pCtrl->mvData.exeingIdx, pCtrl->mvData.lastEndPPS); if (pCtrl->mvData.runstat == CRST_BREAK) // 进入减速后,第一次切换表开始减速 { if (decCount != 0) { decCount--; // 减速执行圈数减少 } // printf("in break, table 2 ok, exeingIdx=%d, decCount=%d, endpps=%d\r\n", pCtrl->mvData.exeingIdx, decCount, pCtrl->mvData.lastEndPPS); } } } if ((vrsta & AXIS_ALARM_FLAG) != 0) // 实轴报警标志 { err = GetAlarmValue(); // 得到轴报警信息 SetVAxisConfig(VCTR_AXIS_ALM_INT); // 清除状态 if (err != 0) { printf("2. axis alarm value=0x%x\r\n", err); } rslt = 1; // 驱动器报警停车 break; } else if ((vrsta & (vAxisBuf1Running | vAxisBuf2Running)) == 0) // 两个缓冲区的数据都执行完成,没有有效数据 { if (pCtrl->mvData.waitNoData == 0) { rslt = 0; // 无有效数据,结束 // printf("no more data in two buff in ContinuousInterpolation, err=0x%x\r\n", pCtrl->mvData.errInfo); break; } else { // printf("wait when no data\r\n"); } } } if (pCtrl->GetEmergencyStop != NULL) // 急停条件函数 { err = pCtrl->GetEmergencyStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { pCtrl->mvData.errInfo = err; printf("2. emergency stop 3, err=0x%x\r\n", err); rslt = 2; // 紧急停止条件触发停车,立刻停止脉冲发送 break; } } if (pCtrl->mvData.runstat == CRST_NORMAL && pCtrl->GetQuickStop != NULL) // 快速停止条件函数 { err = pCtrl->GetQuickStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { // printf("quick stop, enter break status, rslt=0x%x\r\n", err); pCtrl->mvData.errInfo = err; // 设置当前速度为运行速度,保持速度不变 decPPSG = pCtrl->qstopPPSG; vAxisCmd.vaxisId = vAxisId; // 使用虚轴 vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = decPPSG; vAxisCmd.runPPS = GetVAxisPPS(vAxisId); vAxisCmd.startPPS = pCtrl->mvData.lowPPS; rslt = StartVAxisRun(&vAxisCmd); if (rslt < 0) { break; } // 计算以当前运行速度减速到停止速度需要的位移 decCount = CalcDisplacement(vAxisCmd.runPPS, vAxisCmd.startPPS, decPPSG); if (pCtrl->mvData.mvmtdat.interLong != 0) { decCount += pCtrl->mvData.mvmtdat.interLong-1; decCount /= pCtrl->mvData.mvmtdat.interLong; // 计算得到减速需要的整圈数 } else { printf("1. Err: interLong==0\r\n"); } //printf("1. runpps=%d, lowPPS=%d, calcGap=%d, decCount=%d\r\n", vAxisCmd.runPPS, vAxisCmd.startPPS, vAxisCmd.calcGap, decCount); pCtrl->mvData.fillLimit = decCount+pCtrl->mvData.execCount-pCtrl->mvData.fillCount; // 需要继续填充的数据计数 /* 20220406 ljs 填充限制+1 * 降速所需圈数decCount,求出的这个值是正确的 * pCtrl->mvData.execCount是执行完成计数值 * pCtrl->mvData.fillCount是填充计数值 * 代码执行到此处时,一定有一个表正在执行,且另外一个表已经被填充 * 正在执行的表是不能降速的,只有未执行的表是可以降速的 * 故上述填充限制计算得出的值会少填充一针数据 * 例如,此时正在执行第113针,已经填充了第114针,那么第113针不考虑降速,从第114针开始降速 * 若填充计数值为65,此时执行完成计数值为63(因为第113针尚未执行完成,故差值为2) * 若求出需要4圈降速,那么第114,115,116,117针需要降速,且可以降速到目标速度 * 根据上述计算方式求出的填充限制值为2,则可继续填充执行第115,116针,则第117针虽然可以填充, * 但因为此时填充限制值为0,故虽然填充了,但不执行 * 所以实际只有3针用于降速 * 这就是为什么降速不到目标速度的原因 */ pCtrl->mvData.fillLimit += 1; //printf("1. fill limit=%d, decCount=%d,fillCount=%d,exeCount=%d\r\n", pCtrl->mvData.fillLimit, decCount,pCtrl->mvData.fillCount,pCtrl->mvData.execCount); if (pCtrl->mvData.fillLimit < 0) { // printf("1. no need to fill data\r\n"); pCtrl->mvData.fillLimit = 0; } pCtrl->mvData.runstat = CRST_QSTOP; // 设置停车状态 } } if (pCtrl->mvData.runstat == CRST_NORMAL && pCtrl->GetNormalStop != NULL) // 一般停止 { err = pCtrl->GetNormalStop(pCtrl->condPara1, pCtrl->condPara2); if (err != 0) { // printf("normal stop, enter break status, rslt=0x%x\r\n", err); pCtrl->mvData.errInfo = err; // 设置当前速度为运行速度,保持速度不变 decPPSG = pCtrl->nstopPPSG; vAxisCmd.vaxisId = vAxisId; // 使用虚轴 vAxisCmd.bufSel = BUF_SEL3; vAxisCmd.calcGap = decPPSG; vAxisCmd.runPPS = GetVAxisPPS(vAxisId); vAxisCmd.startPPS = pCtrl->mvData.lowPPS; rslt = StartVAxisRun(&vAxisCmd); if (rslt < 0) { break; } // 计算以当前运行速度减速到停止速度需要的位移 decCount = CalcDisplacement(vAxisCmd.runPPS, vAxisCmd.startPPS, decPPSG); if (pCtrl->mvData.mvmtdat.interLong != 0) { decCount += pCtrl->mvData.mvmtdat.interLong-1; decCount /= pCtrl->mvData.mvmtdat.interLong; // 计算得到减速需要的整圈数 } else { printf("2. Err: interLong==0\r\n"); } //printf("2. runpps=%d, lowPPS=%d, calcGap=%d, decCount=%d\r\n", vAxisCmd.runPPS, vAxisCmd.startPPS, vAxisCmd.calcGap, decCount); pCtrl->mvData.fillLimit = decCount+pCtrl->mvData.execCount-pCtrl->mvData.fillCount; // 需要继续填充的数据计数 // 20220406 ljs 填充限制+1 pCtrl->mvData.fillLimit += 1; //printf("2. fill limit=%d, decCount=%d,fillCount=%d,exeCount=%d\r\n", pCtrl->mvData.fillLimit, decCount,pCtrl->mvData.fillCount,pCtrl->mvData.execCount); if (pCtrl->mvData.fillLimit < 0) { // printf("1. no need to fill data\r\n"); pCtrl->mvData.fillLimit = 0; } pCtrl->mvData.runstat = CRST_NSTOP; // 设置停车状态 } } }while(1); StopVAxisRun(vAxisId); if (pCtrl->WorkAfterRun != NULL) { pCtrl->WorkAfterRun(pCtrl->workPara1, pCtrl->workPara2); } // 更新坐标 if (GetMotosCounter(position) == 0) { RefreshMotosPos(position); // 更新各个轴的位置 if (pCtrl->RefreshPosition != NULL) { pCtrl->RefreshPosition(pCtrl->refPosPara, position); } } else { rslt = 5; } return rslt; } #endif