optical/NxFuncs/closedriver/drivermotion.c
2025-09-04 09:45:08 +08:00

487 lines
11 KiB
C

#include "drivermotion.h"
#if (DEV_MOTIONS_NUM > 0)
//----------------------------------------------------------------
// 积分计算的运动控制的计算
#ifndef CALC_TIMES_PER_SEC
#define CALC_TIMES_PER_SEC (10000) // 每秒钟计算次数
#endif
#ifndef USE_FLOAT_CALC
#define USE_FLOAT_CALC 1 // 0, 整数运算, 1, 浮点数运算
#endif
#if (USE_FLOAT_CALC == 1)
#define CALC_TYPE float
#define CALC_MUTI 1.0f
#else
#define CALC_TYPE s32
#define CALC_MUTI 10000
#endif
//----------------------------------------------------------------
typedef struct
{
// 输入参数
CALC_TYPE startSpd; // 启动停止速度
CALC_TYPE runSpd; // 运动速度
CALC_TYPE runAdd; // 启停加速度
CALC_TYPE brkAdd; // 刹车加速度
u32 funTestTime; // 运行过程中外部函数检测间隔时间 0:不检测外部函数 (单位:0.1ms)
// 函数指针
int (*GetNormalStop)(u32,u32); // 一般停止条件函数,当为空时,不检测停止条件; 不为空时,条件满足,降速到停止(按启停加速度降速)
int (*GetQuickStop)(u32,u32); // 快速停止条件函数,当为空时,不检测停止条件; 不为空时,条件满足,降速到停止(按刹车加速度降速)
u32 condPara1, condPara2; // 条件函数参数
int blockRunflag; // 阻塞运行标志, =1阻塞运行,同步运动 =0,非阻塞,异步运动
void (*ExecWhenRun)(void); // 电机运行过程中执行的函数
void (*ExecWhenStart)(void); // 电机启动时执行的函数
void (*ExecWhenStop)(void); // 电机停止时执行的函数
void (*DelayWhenBlock)(u32); // 阻塞时的Delay函数
//---------------------
// 状态参数
int runState; // 运行状态
s32 realpos; // 绝对坐标
int startrunflag; // 启动运行标志
int stopflag; // 停止标志
//---------------------
// 计算控制变量
int rundir; // 运行方向
u32 totalNums; // 运动总脉冲数
u32 pulseCount; // 当前脉冲计数
u32 decPos; // 减速点位置
u32 funTestCount; // 运行过程中外部函数检测间隔时间计数器
CALC_TYPE currentSpd; // 当前速度
CALC_TYPE currentAcc; // 当前加速度
CALC_TYPE currentPos; // 当前位置
//---------------------
} DriverMotionCtrl;
DriverMotionCtrl g_drvMotionsCtrlList[DEV_MOTIONS_NUM];
//----------------------------------------------------------------
// 积分计算过程
void IntegrationMotionCalc(DriverMotionCtrl * pCtrl)
{
if (pCtrl == NULL ||
0 )
{
return;
}
if (pCtrl->runState <= DRV_MOTION_STOP ||
pCtrl->startrunflag <= 0) // 停止状态
{
return; // 不执行
}
if (pCtrl->stopflag != 0)
{
if (pCtrl->stopflag == 1)
{
pCtrl->currentAcc = pCtrl->runAdd; // 当前加速度
pCtrl->runState = DRV_MOTION_NSTOP;
}
else
{
pCtrl->currentAcc = pCtrl->brkAdd; // 当前加速度
pCtrl->runState = DRV_MOTION_ESTOP;
}
}
if (pCtrl->funTestTime > 0) // 条件检测
{
pCtrl->funTestCount++; // 计数增加
if ((pCtrl->funTestCount >= pCtrl->funTestTime) && // 到了测试时间
1 )
{
pCtrl->funTestCount = 0;
if (pCtrl->GetNormalStop != NULL) // 一般停止条件
{
if ((pCtrl->runState == DRV_MOTION_ADD) || // 加速
(pCtrl->runState == DRV_MOTION_RUN) || // 匀速
(pCtrl->runState == DRV_MOTION_DEC) || // 计数降速
0 )
{
if (pCtrl->GetNormalStop(pCtrl->condPara1, pCtrl->condPara2) != 0)
{
pCtrl->currentAcc = pCtrl->runAdd; // 当前加速度
pCtrl->runState = DRV_MOTION_NSTOP; // 普通条件停车
}
}
}
if (pCtrl->GetQuickStop != NULL) // 快速停止条件
{
if ((pCtrl->runState == DRV_MOTION_ADD) || // 加速
(pCtrl->runState == DRV_MOTION_RUN) || // 匀速
(pCtrl->runState == DRV_MOTION_DEC) || // 计数降速
(pCtrl->runState == DRV_MOTION_ESTOP) || // 条件停车
0 )
{
if (pCtrl->GetQuickStop(pCtrl->condPara1, pCtrl->condPara2) != 0)
{
pCtrl->currentAcc = pCtrl->brkAdd; // 当前加速度
pCtrl->runState = DRV_MOTION_ESTOP; // 急停条件停车
}
}
}
if (pCtrl->ExecWhenRun != NULL) // 电机运行过程中执行的函数
{
pCtrl->ExecWhenRun();
}
}
}
// 加速中
if (pCtrl->runState == DRV_MOTION_ADD)
{
pCtrl->currentSpd += pCtrl->currentAcc; // 改变当前速度
if (pCtrl->currentSpd >= pCtrl->runSpd) // 当前速度大于运行速度,进入匀速状态
{
pCtrl->runState = DRV_MOTION_RUN;
pCtrl->currentSpd = pCtrl->runSpd;
pCtrl->decPos = (pCtrl->totalNums - pCtrl->pulseCount); // 减速点位移
}
}
// 减速中
if (pCtrl->runState == DRV_MOTION_DEC) // 计数降速
{
pCtrl->currentSpd -= pCtrl->currentAcc; // 当前速度
if (pCtrl->currentSpd <= pCtrl->startSpd)
{
pCtrl->currentSpd = pCtrl->startSpd;
}
}
// 条件停车中
if ((pCtrl->runState == DRV_MOTION_NSTOP) || // 条件停车
(pCtrl->runState == DRV_MOTION_ESTOP) || // 条件刹车
0 )
{
pCtrl->currentSpd -= pCtrl->currentAcc; // 当前速度
if (pCtrl->currentSpd <= pCtrl->startSpd) // 当前速度小于启动速度,进入停止状态
{
pCtrl->currentSpd = pCtrl->startSpd;
pCtrl->runState = DRV_MOTION_STOPING;
}
}
// 位置计算
{
pCtrl->currentPos += pCtrl->currentSpd * pCtrl->rundir; // 速度积分
if (pCtrl->currentPos > CALC_MUTI || pCtrl->currentPos < -CALC_MUTI) // 位置移出
{
int ofst = (int)(pCtrl->currentPos/CALC_MUTI); // 计算位置偏差
pCtrl->currentPos -= ofst*CALC_MUTI;
pCtrl->realpos += ofst; // 位置改变
pCtrl->pulseCount += abs(ofst); // 计数值增加
}
}
// 停止处理
{
if ((pCtrl->pulseCount >= pCtrl->totalNums) || // 发送脉冲完成
(pCtrl->runState <= DRV_MOTION_STOP) || // 停止信号
(pCtrl->runState == DRV_MOTION_STOPING) || // 停止中
0 )
{
if (pCtrl->runState > DRV_MOTION_STOP) // 运行状态
{
pCtrl->runState = DRV_MOTION_STOP; // 设置为关闭状态
pCtrl->startrunflag = 0; // 关闭运行标志
if (pCtrl->ExecWhenStop != NULL) // 执行关闭时的函数
{
pCtrl->ExecWhenStop();
}
}
}
else
{
if ( (pCtrl->runState == DRV_MOTION_ADD) && // 加速状态中
(pCtrl->pulseCount >= (pCtrl->totalNums>>1)) && // 大于位移的一半
1 )
{
pCtrl->runState = DRV_MOTION_RUN;
pCtrl->currentAcc = pCtrl->runAdd; // 当前加速度
pCtrl->decPos = pCtrl->pulseCount;
#if (0)
#if (USE_FLOAT_CALC == 0)
printf("enter dec, spd=%d\r\n", pCtrl->currentSpd);
#else
#endif
#endif
}
if ( (pCtrl->runState == DRV_MOTION_RUN) && // 匀速中
(pCtrl->pulseCount >= pCtrl->decPos) && // 大于降速点
1 )
{
pCtrl->runState = DRV_MOTION_DEC;
pCtrl->currentAcc = pCtrl->runAdd; // 当前加速度
}
}
}
}
CALC_TYPE pps_to_ppg(s32 pps)
{
return pps*CALC_MUTI / CALC_TIMES_PER_SEC;
}
//----------------------------------------------------------------
// 启动运动控制(停止状态时可用)
int DrvMotionStart(int driverIdx, DrvMotionPara * pPara)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
printf("DrvMotionStart fail, driverIdx error\r\n");
return -1;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
if (pPara == NULL)
{
printf("DrvMotionStart fail, pPara is NULL\r\n");
return -1;
}
if (pCtrl->runState <= DRV_MOTION_STOP) // 停车/报警状态允许启动电机
{
pCtrl->startrunflag = 0; // 关闭运行标志
if (pPara->movement == 0) // 电机运行完毕
{
pCtrl->runState = DRV_MOTION_STOP;
printf("driverIdx=%d, movement=0\r\n", driverIdx);
pCtrl->rundir = 0;
return 0;
}
if (pPara->startPPS < 10)
{
pPara->startPPS = 10;
}
if (pPara->runPPS < 10)
{
pPara->runPPS = 10;
}
if (pPara->startPPS > pPara->runPPS)
{
pPara->startPPS = pPara->runPPS;
}
if (pPara->addPPSS < 1)
{
pPara->addPPSS = 1;
}
// 输入速度参数计算
pCtrl->startSpd = pps_to_ppg(pPara->startPPS); // 启动停止速度
pCtrl->runSpd = pps_to_ppg(pPara->runPPS); // 运动速度
pCtrl->runAdd = pps_to_ppg(pPara->addPPSS); // 启停加速度
pCtrl->brkAdd = pps_to_ppg(pPara->brkPPSS); // 刹车加速度
pCtrl->currentSpd = pCtrl->startSpd; // 当前速度
pCtrl->currentAcc = pCtrl-> runAdd; // 当前加速度
pCtrl->currentPos = 1; // 当前位置, 先输出一个脉冲
pCtrl->runState = DRV_MOTION_ADD; // 运行状态, 加速中
pCtrl->funTestTime = pPara->funTestTime;
pCtrl->funTestCount = 0; // 运行过程中外部函数检测间隔时间计数器
// 函数指针
pCtrl->GetNormalStop = pPara->GetNormalStop; // 一般停止条件函数
pCtrl->GetQuickStop = pPara->GetQuickStop; // 快速停止条件函数
pCtrl->condPara1 = pPara->condPara1; // 条件函数参数
pCtrl->condPara2 = pPara->condPara2; // 条件函数参数
pCtrl->blockRunflag = pPara->blockRunflag; // 阻塞运行标志
pCtrl->ExecWhenStart = pPara->ExecWhenStart; // 启动时执行的函数
pCtrl->ExecWhenRun = pPara->ExecWhenRun; // 运行过程中执行的函数
pCtrl->ExecWhenStop = pPara->ExecWhenStop; // 停止时执行的函数
pCtrl->DelayWhenBlock = pPara->DelayWhenBlock; // 阻塞时执行的函数
if (pCtrl->ExecWhenStart != NULL) // 启动前执行
{
pCtrl->ExecWhenStart();
}
//---------------------
// 位移配置
pCtrl->rundir = (pPara->movement > 0) ? 1:-1; // 方向
pCtrl->totalNums = abs(pPara->movement); // 总位移
pCtrl->pulseCount = 0; // 脉冲计数
pCtrl->decPos = pCtrl->totalNums; // 减速位置
// 输出配置
pCtrl->stopflag = 0;
pCtrl->startrunflag = 1; // 设置启动运行标志
return DrvMotionRun(driverIdx);
}
else
{
printf("DrvMotionStart failed, drv%d is running\r\n", driverIdx);
return -2; // 电机正在运行
}
}
// 停止运动控制(非阻塞运动时用到)
void DrvMotionStop(int driverIdx)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
pCtrl->stopflag = 1;
}
// 停止运动控制(非阻塞运动时用到)
void DrvMotionBreak(int driverIdx)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
pCtrl->stopflag = 2;
}
int DrvMotionRun(int driverIdx)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return -1;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
// 运行循环
do
{
if (pCtrl->runState <= DRV_MOTION_STOP)
{
break;
}
if (pCtrl->blockRunflag == 0) // 阻塞运行标志
{
break;
}
if (pCtrl->DelayWhenBlock != NULL)
{
pCtrl->DelayWhenBlock(0);
}
}while(1);
return pCtrl->runState;
}
// 得到运动状态(非阻塞运动时用到)
int GetDrvMotionState(int driverIdx)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return 0;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
return pCtrl->runState;
}
// 得到当前运动位置(非阻塞运动时用到)
s32 GetDrvMotionRealPos(int driverIdx)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return 0;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
return pCtrl->realpos;
}
// 设置当前运动位置(停止状态时可用)
// 禁止应用层使用此代码,若需重置电机坐标,需使用ResetDriverPos
void SetDrvMotionRealPos(int driverIdx, s32 pos)
{
DriverMotionCtrl * pCtrl;
if (driverIdx < 0 || driverIdx >= DEV_MOTIONS_NUM)
{
return ;
}
pCtrl = &(g_drvMotionsCtrlList[driverIdx]);
pCtrl->realpos = pos;
// printf("set drv%d realpos to %d\r\n", driverIdx+1, pos);
}
//----------------------------------------------------------------
// 初始化
void InitDrvMotions(void)
{
memset(&g_drvMotionsCtrlList, 0, sizeof(DriverMotionCtrl)*DEV_MOTIONS_NUM);
// 测试命令
}
// 计算过程
void DrvMotionCalcProc(void)
{
DriverMotionCtrl * pCtrl;
int i;
for (i = 0; i < DEV_MOTIONS_NUM; i++)
{
pCtrl = &(g_drvMotionsCtrlList[i]);
IntegrationMotionCalc(pCtrl);
}
}
//----------------------------------------------------------------
#endif