|
|
@@ -1,24 +1,16 @@ |
|
|
/** |
|
|
/** |
|
|
* @file plsr_run_control.c |
|
|
* @file plsr_run_control.c |
|
|
* @brief 完成方式 / 后续方式 运行控制(加减速形状由 accel_mode 决定) |
|
|
|
|
|
|
|
|
* @brief 运行控制:等待策略 + 开段端点 + 执行驱动 |
|
|
* |
|
|
* |
|
|
* 分层: |
|
|
|
|
|
* 1) 调用/等待策略:只决定调用顺序,以及传给段处理的 |
|
|
|
|
|
* 起始频率 f_from、终止频率 f_end、加速/减速时间(斜率基准) |
|
|
|
|
|
* 2) 段内处理:不感知 wait_type;只按 (f_from,f_tgt,f_end,accel,decel) |
|
|
|
|
|
* 做加速→匀速→减速(脉冲不够则三角) |
|
|
|
|
|
* 3) 曲线估加/减速脉冲;匀速=总数−加速−减速。 |
|
|
|
|
|
* 规划反向算 t_decel_start_ms;运行时 TIM3 1ms 按段内时间轴取频(直线为纯代数)。 |
|
|
|
|
|
* 起止≠0:首拍起速、末拍止速;起止=0:首末跟曲线,段末停表。 |
|
|
|
|
|
* |
|
|
|
|
|
* 典型策略映射: |
|
|
|
|
|
* - 完成方式:每段 f_end=止速;WAIT 只做段后等待与下一段 f_from(清链→起速) |
|
|
|
|
|
* - 后续方式末段:f_end=止速;非末段无缝:f_end=下一段目标 |
|
|
|
|
|
* - ACT:先按完成/后续规划加速/匀速/减速时间,再和 act_ms 比较: |
|
|
|
|
|
* 加速 > ACT → 加速中途打断;加速+匀速 > ACT → 不进减速; |
|
|
|
|
|
* 加速+匀速 < ACT < 三段总时间 → 减速中途打断; |
|
|
|
|
|
* ACT ≥ 加速+匀速+减速 → 三阶段(含减速)走完,脉冲照常计数,停表等到 ACT 再下一段(※4)。 |
|
|
|
|
|
* - 梯形/三角仅由 f_from/f_tgt/f_end/斜率/mode/脉冲数决定,不读 wait_type |
|
|
|
|
|
|
|
|
* 分层(阶段1薄拆分): |
|
|
|
|
|
* 1) 曲线(accel_curve):只吃 (f_from,f_tgt,f_end,斜率,N,mode) → 梯形/三角; |
|
|
|
|
|
* 不读 wait_type。端点须为真实频率(>=1);配置起/止=0 由运行层 |
|
|
|
|
|
* ResolveStart/EndHz 算起跳/落地后再传入。 |
|
|
|
|
|
* 2) 等待策略:只决定何时打断/段后等待;统一 handoff: |
|
|
|
|
|
* - 仍在输出且 freq>=1 → 链式传给下一段 |
|
|
|
|
|
* - 已停表/输出为 0 → 下一段从配置起速(0 则起跳频率)开跑 |
|
|
|
|
|
* 3) 发送模式只影响本段 f_end(完成=止速;后续且不停表=下一段目标) |
|
|
|
|
|
* 4) PlanSeg / ChangeFreq 共用规划入口,便于后期动态改频 |
|
|
* |
|
|
* |
|
|
* 【运行节拍】TIM3 1ms:RefreshProfile 改频;脉冲 UPDATE ISR 只计 s_done。 |
|
|
* 【运行节拍】TIM3 1ms:RefreshProfile 改频;脉冲 UPDATE ISR 只计 s_done。 |
|
|
*/ |
|
|
*/ |
|
|
@@ -79,7 +71,6 @@ static uint8_t s_pwm_on; |
|
|
/* 本段由策略层解析后的加减速时间(段内只用这两份,不再读 wait) */ |
|
|
/* 本段由策略层解析后的加减速时间(段内只用这两份,不再读 wait) */ |
|
|
static uint16_t s_run_accel_ms; |
|
|
static uint16_t s_run_accel_ms; |
|
|
static uint16_t s_run_decel_ms; |
|
|
static uint16_t s_run_decel_ms; |
|
|
static uint8_t s_orig_end_zero; /* 原始止速为 0(起跳频率已替代 plan.f_end) */ |
|
|
|
|
|
|
|
|
|
|
|
/** 策略层交给段处理的接口参数 */ |
|
|
/** 策略层交给段处理的接口参数 */ |
|
|
typedef struct { |
|
|
typedef struct { |
|
|
@@ -138,10 +129,15 @@ static void PlsrRunControlArmActExtOnPulseStart(void) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** EXT 中途切段:停表后立即按 jump 跳转 */ |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* EXT 触发切段(脉冲可能还在跑)。 |
|
|
|
|
|
* 同向且 PWM 在跑:不停表,下一段 f_from = 当前频率(衔接加速)。 |
|
|
|
|
|
* 反向或已停表:停表,下一段从起速爬。 |
|
|
|
|
|
*/ |
|
|
static void PlsrRunControlCutSegToNext(void) |
|
|
static void PlsrRunControlCutSegToNext(void) |
|
|
{ |
|
|
{ |
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
|
|
|
|
|
|
int16_t next0; |
|
|
|
|
|
uint8_t keep; |
|
|
|
|
|
|
|
|
s_state = RC_IDLE; |
|
|
s_state = RC_IDLE; |
|
|
s_act_armed = 0U; |
|
|
s_act_armed = 0U; |
|
|
@@ -149,26 +145,40 @@ static void PlsrRunControlCutSegToNext(void) |
|
|
s_act_cut_pending = 0U; |
|
|
s_act_cut_pending = 0U; |
|
|
s_act_handoff_keep = 0U; |
|
|
s_act_handoff_keep = 0U; |
|
|
s_wait_expire_req = 0U; |
|
|
s_wait_expire_req = 0U; |
|
|
PlsrPulseDriverStop(); |
|
|
|
|
|
s_follow_cont = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
|
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
next0 = PlsrPathPlanResolveAfterSeg(s_cur_seg); |
|
|
|
|
|
keep = 0U; |
|
|
|
|
|
if ((next0 >= 0) && (s_pwm_on != 0U) && (s_cur_freq >= 1U) && |
|
|
|
|
|
(PlsrPathPlanIsForward((uint16_t)next0, s_acc_pulse) == s_forward)) |
|
|
{ |
|
|
{ |
|
|
s_chain_freq = s_cur_freq; |
|
|
|
|
|
|
|
|
keep = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (keep != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
|
|
|
s_follow_cont = 1U; |
|
|
s_chain_valid = 1U; |
|
|
s_chain_valid = 1U; |
|
|
|
|
|
s_chain_freq = s_cur_freq; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
|
|
|
PlsrPulseDriverStop(); |
|
|
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
|
|
|
s_follow_cont = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
|
|
|
s_chain_freq = 0U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* ACT 时间到(脉冲可能还没发完):从当前频率切下一段。 |
|
|
|
|
|
* 同向:不停表,下一段 f_from=当前频率(※2 加速相 / ※3 减速相)。 |
|
|
|
|
|
* 反向或无 PWM:停表,下一段从起速爬。 |
|
|
|
|
|
|
|
|
* ACT 时间到(脉冲可能还没发完):丢掉本段剩余脉冲/减速,从当前频率切下一段。 |
|
|
|
|
|
* 同向:下一段 f_from=当前频率(逐层跳,不进本段减速)。 |
|
|
|
|
|
* 反向或无频率:停表,下一段从起速爬。 |
|
|
*/ |
|
|
*/ |
|
|
static void PlsrRunControlActExpire(void) |
|
|
static void PlsrRunControlActExpire(void) |
|
|
{ |
|
|
{ |
|
|
@@ -220,7 +230,7 @@ static void PlsrRunControlEnterPostWaitOrNext(void) |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 调用顺序策略(与段内波形无关): |
|
|
* 调用顺序策略(与段内波形无关): |
|
|
* WAIT时间/信号 → 停表清链后等待,再 BeginSeg(下一段 f_from=起速) |
|
|
|
|
|
|
|
|
* WAIT时间/信号 → 停表清链后等待,再 BeginSeg(下一段从起速/起跳开跑) |
|
|
* 其它 → 立即跳转下一段 |
|
|
* 其它 → 立即跳转下一段 |
|
|
*/ |
|
|
*/ |
|
|
if (seg->wait_type == PLSR_WAIT_TIME) |
|
|
if (seg->wait_type == PLSR_WAIT_TIME) |
|
|
@@ -259,6 +269,31 @@ static void PlsrRunControlEnterPostWaitOrNext(void) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((seg->wait_type == PLSR_WAIT_EXT) || |
|
|
|
|
|
(seg->wait_type == PLSR_WAIT_EXT_OR_DONE)) |
|
|
|
|
|
{ |
|
|
|
|
|
/* |
|
|
|
|
|
* EXT 脉冲发完后等待:停表,输出已经是 0。 |
|
|
|
|
|
* 下一段从配置起速(0 则起跳)重新规划;不是接着本段 f_end 往下跑。 |
|
|
|
|
|
*/ |
|
|
|
|
|
PlsrPulseDriverStop(); |
|
|
|
|
|
s_follow_cont = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
|
|
|
s_chain_valid = 0U; |
|
|
|
|
|
s_chain_freq = 0U; |
|
|
|
|
|
s_cur_freq = 0U; |
|
|
|
|
|
/* 只清消抖中的假沿;已确认的 fell 保留,供下面 TakeExtFalling 消费 */ |
|
|
|
|
|
PlsrSignalIoClearPending(); |
|
|
|
|
|
if (PlsrSignalIoTakeExtFalling() != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
s_wait_is_signal = 1U; |
|
|
|
|
|
s_state = RC_WAIT_COND; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -326,8 +361,8 @@ static void PlsrRunControlAfterSegDone(void) |
|
|
|
|
|
|
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
{ |
|
|
{ |
|
|
/* 段正常结束:下一段起速 = 本段止速 f_end,不能用峰值 s_cur_freq */ |
|
|
|
|
|
s_chain_freq = (s_orig_end_zero != 0U) ? 0U : s_accel_plan.f_end; |
|
|
|
|
|
|
|
|
/* 段正常结束:下一段起速 = 本段实际止速 plan.f_end,不能用峰值 s_cur_freq */ |
|
|
|
|
|
s_chain_freq = s_accel_plan.f_end; |
|
|
s_chain_valid = 1U; |
|
|
s_chain_valid = 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -356,7 +391,13 @@ static uint8_t PlsrRunControlBlocksFollowKeep(uint16_t cur_seg) |
|
|
{ |
|
|
{ |
|
|
PlsrSeg_t *seg = PlsrParamGetSeg(cur_seg); |
|
|
PlsrSeg_t *seg = PlsrParamGetSeg(cur_seg); |
|
|
|
|
|
|
|
|
/* WAIT时间(含0→1ms)、WAIT信号、ACT/EXT:均禁止无缝衔接 */ |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* WAIT时间/信号/ACT:禁止后续无缝衔接(发完后停表等条件)。 |
|
|
|
|
|
* EXT/EXT_OR_DONE:脉冲发完之前 EXT 可能尚未触发,发完后进等待态, |
|
|
|
|
|
* 此时 PWM 必须停;所以也禁止无缝衔接。 |
|
|
|
|
|
* (EXT 触发时若脉冲还在跑,由 CutSegToNext 判断 keep, |
|
|
|
|
|
* 那条路不走 BlocksFollowKeep。) |
|
|
|
|
|
*/ |
|
|
if ((seg->wait_type == PLSR_WAIT_TIME) || |
|
|
if ((seg->wait_type == PLSR_WAIT_TIME) || |
|
|
(seg->wait_type == PLSR_WAIT_SIGNAL) || |
|
|
(seg->wait_type == PLSR_WAIT_SIGNAL) || |
|
|
(seg->wait_type == PLSR_WAIT_ACT) || |
|
|
(seg->wait_type == PLSR_WAIT_ACT) || |
|
|
@@ -385,38 +426,60 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
io->accel_ms = cfg->accel_ms; |
|
|
io->accel_ms = cfg->accel_ms; |
|
|
io->decel_ms = cfg->decel_ms; |
|
|
io->decel_ms = cfg->decel_ms; |
|
|
|
|
|
|
|
|
/* ---------- 起始频率:由衔接状态决定(WAIT 会清链 → 起速) ---------- */ |
|
|
|
|
|
if (s_follow_cont != 0U) |
|
|
|
|
|
|
|
|
/* ---------- 起始频率 ---------- |
|
|
|
|
|
* 中途切段(ACT/EXT)会置 follow_cont:用打断瞬间的频率衔接下一段。 |
|
|
|
|
|
* ACT 为了对齐脉冲边界可能先停表,此时 pwm_on=0,但仍要跟当前频率, |
|
|
|
|
|
* 不能当成「段后停表」去走起跳。 |
|
|
|
|
|
* 真正段后停表:follow_cont/chain 已清,从配置起速(0 则起跳)开跑。 |
|
|
|
|
|
*/ |
|
|
|
|
|
if ((s_follow_cont != 0U) && (s_cur_freq >= 1U)) |
|
|
{ |
|
|
{ |
|
|
io->f_from = s_cur_freq; |
|
|
io->f_from = s_cur_freq; |
|
|
} |
|
|
} |
|
|
else if ((cfg->send_mode == PLSR_SEND_COMPLETE) && (s_chain_valid != 0U)) |
|
|
|
|
|
|
|
|
else if ((s_pwm_on != 0U) && (s_cur_freq >= 1U)) |
|
|
|
|
|
{ |
|
|
|
|
|
io->f_from = s_cur_freq; |
|
|
|
|
|
} |
|
|
|
|
|
else if ((s_chain_valid != 0U) && (s_chain_freq >= 1U) && |
|
|
|
|
|
((s_pwm_on != 0U) || (s_follow_cont != 0U))) |
|
|
{ |
|
|
{ |
|
|
io->f_from = s_chain_freq; |
|
|
io->f_from = s_chain_freq; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
io->f_from = PlsrRunControlClampSpeed(cfg->start_speed); |
|
|
|
|
|
|
|
|
io->f_from = PlsrAccelCurveResolveStartHz(cfg->start_speed, |
|
|
|
|
|
f_tgt, |
|
|
|
|
|
cfg->default_speed, |
|
|
|
|
|
cfg->start_speed, |
|
|
|
|
|
cfg->end_speed, |
|
|
|
|
|
io->accel_ms, |
|
|
|
|
|
io->decel_ms); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* ---------- 终止频率:仅由发送模式 + 是否有下一段决定 ---------- |
|
|
|
|
|
* 完成方式 / 真末段:公共止速 |
|
|
|
|
|
* 后续方式非末段:下一段目标(无缝衔接) |
|
|
|
|
|
* ACT 只由运行控制层管理,不改变本段曲线的 f_end 或阶段规划。 |
|
|
|
|
|
|
|
|
* ---------- 终止频率 ---------- |
|
|
|
|
|
* 完成方式 / 真末段 / 发完后要停表等(WAIT时间/信号):本段规划到止速。 |
|
|
|
|
|
* ACT/EXT 中途打断时剩余减速本来就会丢弃,不影响「进不进减速」。 |
|
|
|
|
|
* 后续方式且无门禁:过渡到下一段目标。 |
|
|
*/ |
|
|
*/ |
|
|
(void)f_tgt; |
|
|
|
|
|
next0 = PlsrPathPlanNextSeg(seg_0); |
|
|
next0 = PlsrPathPlanNextSeg(seg_0); |
|
|
end_at_stop = (next0 < 0) ? 1U : 0U; |
|
|
end_at_stop = (next0 < 0) ? 1U : 0U; |
|
|
|
|
|
|
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
|
|
|
|
|
|
if ((cfg->send_mode == PLSR_SEND_COMPLETE) || |
|
|
|
|
|
(PlsrRunControlBlocksFollowKeep(seg_0) != 0U)) |
|
|
{ |
|
|
{ |
|
|
end_at_stop = 1U; |
|
|
end_at_stop = 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (end_at_stop != 0U) |
|
|
if (end_at_stop != 0U) |
|
|
{ |
|
|
{ |
|
|
io->f_end = PlsrRunControlClampSpeed(cfg->end_speed); |
|
|
|
|
|
|
|
|
io->f_end = PlsrAccelCurveResolveEndHz(cfg->end_speed, |
|
|
|
|
|
f_tgt, |
|
|
|
|
|
cfg->default_speed, |
|
|
|
|
|
cfg->start_speed, |
|
|
|
|
|
cfg->end_speed, |
|
|
|
|
|
io->accel_ms, |
|
|
|
|
|
io->decel_ms); |
|
|
return 1U; |
|
|
return 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -619,30 +682,23 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
* (拉长会在尾部堆 1Hz 空耗)。 |
|
|
* (拉长会在尾部堆 1Hz 空耗)。 |
|
|
*/ |
|
|
*/ |
|
|
if ((old_t_dec > 0U) && (old_dec_n > 0U) && |
|
|
if ((old_t_dec > 0U) && (old_dec_n > 0U) && |
|
|
((remain_pulses == old_dec_n) || (s_orig_end_zero != 0U))) |
|
|
|
|
|
|
|
|
(remain_pulses == old_dec_n)) |
|
|
{ |
|
|
{ |
|
|
s_accel_plan.t_dec_ms = old_t_dec; |
|
|
s_accel_plan.t_dec_ms = old_t_dec; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 参数斜率决定的理想减速时间(本段 accel_ms/decel_ms) */ |
|
|
|
|
|
|
|
|
/* 参数斜率:K = 默认速度 / 加减速时间(减 0) */ |
|
|
df = (from_hz > f_end) ? (from_hz - f_end) : (f_end - from_hz); |
|
|
df = (from_hz > f_end) ? (from_hz - f_end) : (f_end - from_hz); |
|
|
if (f_end > from_hz) |
|
|
if (f_end > from_hz) |
|
|
{ |
|
|
{ |
|
|
ref_ms = s_run_accel_ms; |
|
|
ref_ms = s_run_accel_ms; |
|
|
den = (cfg->default_speed > cfg->start_speed) ? |
|
|
|
|
|
(cfg->default_speed - cfg->start_speed) : |
|
|
|
|
|
((cfg->default_speed > cfg->end_speed) ? |
|
|
|
|
|
(cfg->default_speed - cfg->end_speed) : cfg->default_speed); |
|
|
|
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
ref_ms = s_run_decel_ms; |
|
|
ref_ms = s_run_decel_ms; |
|
|
den = (cfg->default_speed > cfg->end_speed) ? |
|
|
|
|
|
(cfg->default_speed - cfg->end_speed) : |
|
|
|
|
|
((cfg->default_speed > cfg->start_speed) ? |
|
|
|
|
|
(cfg->default_speed - cfg->start_speed) : cfg->default_speed); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
den = cfg->default_speed; |
|
|
if (den == 0U) |
|
|
if (den == 0U) |
|
|
{ |
|
|
{ |
|
|
den = df; |
|
|
den = df; |
|
|
@@ -656,15 +712,8 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (s_orig_end_zero != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
s_accel_plan.t_dec_ms = (t_slope > 0U) ? t_slope : |
|
|
|
|
|
((old_t_dec > 0U) ? old_t_dec : 1U); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 止速≠0:ISR 内禁止 FitRamp/EstimatePulses;用 O(1) 平均公式。 |
|
|
|
|
|
|
|
|
* ISR 内禁止 FitRamp/EstimatePulses;用 O(1) 平均公式。 |
|
|
* 脉冲被截断导致 remain 变化时才走这里。 |
|
|
* 脉冲被截断导致 remain 变化时才走这里。 |
|
|
*/ |
|
|
*/ |
|
|
sum_f = from_hz + f_end; |
|
|
sum_f = from_hz + f_end; |
|
|
@@ -706,25 +755,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms); |
|
|
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms); |
|
|
if (next < 1U) |
|
|
if (next < 1U) |
|
|
{ |
|
|
{ |
|
|
if ((s_orig_end_zero != 0U) && (s_seg_elapsed_ms > 0U)) |
|
|
|
|
|
{ |
|
|
|
|
|
/* |
|
|
|
|
|
* 原始止速为 0,时间轴走完。剩余脉冲仍要发出并计数(ACT※4: |
|
|
|
|
|
* 三阶段走完后等时间,不能把 s_target 截掉导致计数丢失)。 |
|
|
|
|
|
*/ |
|
|
|
|
|
if (s_done < s_target) |
|
|
|
|
|
{ |
|
|
|
|
|
next = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
next = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
next = 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((next != s_cur_freq) || (do_start != 0U) || (s_pwm_on == 0U)) |
|
|
if ((next != s_cur_freq) || (do_start != 0U) || (s_pwm_on == 0U)) |
|
|
@@ -738,17 +769,17 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
uint16_t accel_ms, uint16_t decel_ms) |
|
|
uint16_t accel_ms, uint16_t decel_ms) |
|
|
{ |
|
|
{ |
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
|
|
|
uint32_t f_start; |
|
|
uint32_t f_lo; |
|
|
uint32_t f_lo; |
|
|
uint32_t f_hi; |
|
|
uint32_t f_hi; |
|
|
|
|
|
|
|
|
/* 段内只吃传入端点与加减速时间,不感知 wait */ |
|
|
/* 段内只吃传入端点与加减速时间,不感知 wait */ |
|
|
s_run_accel_ms = accel_ms; |
|
|
s_run_accel_ms = accel_ms; |
|
|
s_run_decel_ms = decel_ms; |
|
|
s_run_decel_ms = decel_ms; |
|
|
s_orig_end_zero = (f_end == 0U) ? 1U : 0U; |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 曲线估 acc_n / dec_n,const_n = total − acc − dec。 |
|
|
* 曲线估 acc_n / dec_n,const_n = total − acc − dec。 |
|
|
* 起止≠0:运行时首拍=起速、末拍=止速;起止=0:首末跟曲线,段末停表。 |
|
|
|
|
|
|
|
|
* f_from/f_end 已由策略层解析为真实频率;配置起止=0 时已换成起跳/落地。 |
|
|
*/ |
|
|
*/ |
|
|
PlsrAccelCurvePlan(&s_accel_plan, |
|
|
PlsrAccelCurvePlan(&s_accel_plan, |
|
|
total, |
|
|
total, |
|
|
@@ -762,6 +793,9 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
decel_ms, |
|
|
decel_ms, |
|
|
cfg->accel_mode); |
|
|
cfg->accel_mode); |
|
|
|
|
|
|
|
|
|
|
|
/* 运行层使用规划后的实际起始频率。 */ |
|
|
|
|
|
f_start = s_accel_plan.f_cur; |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 1ms 改频模式:运行时按 TIM3 毫秒时间轴取频。 |
|
|
* 1ms 改频模式:运行时按 TIM3 毫秒时间轴取频。 |
|
|
* 禁止在这里用脉冲递推模型二次拟合 T(FitRamp),否则规划与运行模型不一致, |
|
|
* 禁止在这里用脉冲递推模型二次拟合 T(FitRamp),否则规划与运行模型不一致, |
|
|
@@ -771,15 +805,15 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
/* 本段频率范围锁 PSC,升降只改 ARR;跨度过大则 LockPscRange 自动不锁 */ |
|
|
/* 本段频率范围锁 PSC,升降只改 ARR;跨度过大则 LockPscRange 自动不锁 */ |
|
|
f_lo = s_accel_plan.f_tgt; |
|
|
f_lo = s_accel_plan.f_tgt; |
|
|
f_hi = s_accel_plan.f_tgt; |
|
|
f_hi = s_accel_plan.f_tgt; |
|
|
if (f_from > f_hi) |
|
|
|
|
|
|
|
|
if (f_start > f_hi) |
|
|
{ |
|
|
{ |
|
|
f_hi = f_from; |
|
|
|
|
|
|
|
|
f_hi = f_start; |
|
|
} |
|
|
} |
|
|
if (f_from >= 1U) |
|
|
|
|
|
|
|
|
if (f_start >= 1U) |
|
|
{ |
|
|
{ |
|
|
if (f_from < f_lo) |
|
|
|
|
|
|
|
|
if (f_start < f_lo) |
|
|
{ |
|
|
{ |
|
|
f_lo = f_from; |
|
|
|
|
|
|
|
|
f_lo = f_start; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
@@ -820,11 +854,11 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
PlsrPulseDriverLockPscRange(f_lo, f_hi); |
|
|
PlsrPulseDriverLockPscRange(f_lo, f_hi); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
s_approach_from = f_from; |
|
|
|
|
|
|
|
|
s_approach_from = f_start; |
|
|
s_decel_from = s_accel_plan.f_tgt; |
|
|
s_decel_from = s_accel_plan.f_tgt; |
|
|
if (s_pwm_on == 0U) |
|
|
if (s_pwm_on == 0U) |
|
|
{ |
|
|
{ |
|
|
s_cur_freq = f_from; |
|
|
|
|
|
|
|
|
s_cur_freq = f_start; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
@@ -839,17 +873,17 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
if ((s_accel_plan.dec_n >= total) && |
|
|
if ((s_accel_plan.dec_n >= total) && |
|
|
(total > 0U) && |
|
|
(total > 0U) && |
|
|
(s_accel_plan.f_end != s_accel_plan.f_tgt) && |
|
|
(s_accel_plan.f_end != s_accel_plan.f_tgt) && |
|
|
(f_from >= s_accel_plan.f_tgt)) |
|
|
|
|
|
|
|
|
(f_start >= s_accel_plan.f_tgt)) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterDecel(f_from, total); |
|
|
|
|
|
|
|
|
PlsrRunControlEnterDecel(f_start, total); |
|
|
} |
|
|
} |
|
|
else if (f_from == s_accel_plan.f_tgt) |
|
|
|
|
|
|
|
|
else if (f_start == s_accel_plan.f_tgt) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterPhase(PH_CONST, f_from); |
|
|
|
|
|
|
|
|
PlsrRunControlEnterPhase(PH_CONST, f_start); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterPhase(PH_APPROACH, f_from); |
|
|
|
|
|
|
|
|
PlsrRunControlEnterPhase(PH_APPROACH, f_start); |
|
|
} |
|
|
} |
|
|
s_seg_elapsed_ms = 0U; |
|
|
s_seg_elapsed_ms = 0U; |
|
|
} |
|
|
} |
|
|
@@ -990,7 +1024,6 @@ void PlsrRunControlInit(void) |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_run_accel_ms = 0U; |
|
|
s_run_accel_ms = 0U; |
|
|
s_run_decel_ms = 0U; |
|
|
s_run_decel_ms = 0U; |
|
|
s_orig_end_zero = 0U; |
|
|
|
|
|
s_phase = PH_CONST; |
|
|
s_phase = PH_CONST; |
|
|
s_seg_elapsed_ms = 0U; |
|
|
s_seg_elapsed_ms = 0U; |
|
|
s_approach_from = 0U; |
|
|
s_approach_from = 0U; |
|
|
@@ -1143,9 +1176,21 @@ void PlsrRunControlTickMs(void) |
|
|
{ |
|
|
{ |
|
|
if (s_wait_is_signal != 0U) |
|
|
if (s_wait_is_signal != 0U) |
|
|
{ |
|
|
{ |
|
|
if (PlsrSignalIoTakeWaitFalling() != 0U) |
|
|
|
|
|
|
|
|
seg = PlsrParamGetSeg(s_cur_seg); |
|
|
|
|
|
if ((seg->wait_type == PLSR_WAIT_EXT) || |
|
|
|
|
|
(seg->wait_type == PLSR_WAIT_EXT_OR_DONE)) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
|
|
|
|
|
|
if (PlsrSignalIoTakeExtFalling() != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
if (PlsrSignalIoTakeWaitFalling() != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
/* WAIT 时间 / ACT 剩余到期在 On1ms */ |
|
|
/* WAIT 时间 / ACT 剩余到期在 On1ms */ |
|
|
@@ -1197,21 +1242,6 @@ void PlsrRunControlOn1ms(void) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((s_orig_end_zero != 0U) && |
|
|
|
|
|
(s_accel_plan.mode != PLSR_ACCEL_LINEAR) && |
|
|
|
|
|
(s_accel_plan.t_dec_ms >= 1U) && |
|
|
|
|
|
(s_seg_elapsed_ms >= |
|
|
|
|
|
(s_accel_plan.t_decel_start_ms + s_accel_plan.t_dec_ms))) |
|
|
|
|
|
{ |
|
|
|
|
|
/* 非直线:时间轴走完减速后,剩余脉冲仍按最后频率发完并计数 */ |
|
|
|
|
|
if ((s_done >= s_target) && |
|
|
|
|
|
(PlsrRunControlWillFollowKeep(s_cur_seg) == 0U)) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrPulseDriverArmOnePulseStop(); |
|
|
|
|
|
} |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -1234,14 +1264,13 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* ACT 到期后的切段只在脉冲边界执行。当前 UPDATE 已完成本段 |
|
|
|
|
|
* 最后一个完整脉冲,立即停表,任务再用当前频率衔接下一段。 |
|
|
|
|
|
|
|
|
* ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。 |
|
|
|
|
|
* 同向衔接:不停表,任务里用当前频率规划下一段(丢掉本段剩余)。 |
|
|
|
|
|
* 停表会把 pwm_on 清掉,Resolve 若再要求 pwm_on 就会误走起跳。 |
|
|
*/ |
|
|
*/ |
|
|
if (s_act_cut_pending != 0U) |
|
|
if (s_act_cut_pending != 0U) |
|
|
{ |
|
|
{ |
|
|
s_act_cut_pending = 0U; |
|
|
s_act_cut_pending = 0U; |
|
|
PlsrPulseDriverStop(); |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
|
|
|
s_act_handoff_keep = 1U; |
|
|
s_act_handoff_keep = 1U; |
|
|
s_state = RC_IDLE; |
|
|
s_state = RC_IDLE; |
|
|
s_act_expire_req = 1U; |
|
|
s_act_expire_req = 1U; |
|
|
|