瀏覽代碼

修复100kHz时提前进入减速导致最后1Hz拖尾

master
hanyongwei 1 月之前
父節點
當前提交
cbed24c4f0
共有 5 個文件被更改,包括 1779 次插入1684 次删除
  1. +21
    -9
      drivers/Source/stm32f4xx_it.c
  2. +1653
    -1654
      iar/plsr.dep
  3. +18
    -14
      plsr/accel_curve/plsr_accel_curve.c
  4. +1
    -1
      plsr/accel_curve/plsr_accel_curve.h
  5. +86
    -6
      plsr/run_control/plsr_run_control.c

+ 21
- 9
drivers/Source/stm32f4xx_it.c 查看文件

@@ -24,6 +24,7 @@
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include "ucos_ii.h" #include "ucos_ii.h"
#include "os_cpu.h" #include "os_cpu.h"
#include "plsr.h"
#include "plsr_signal_io.h" #include "plsr_signal_io.h"
/* USER CODE END Includes */ /* USER CODE END Includes */


@@ -259,9 +260,16 @@ void EXTI15_10_IRQHandler(void)
*/ */
void TIM1_UP_TIM10_IRQHandler(void) void TIM1_UP_TIM10_IRQHandler(void)
{ {
OSIntEnter();
HAL_TIM_IRQHandler(&htim10);
OSIntExit();
/*
* PLSR runs this vector at up to 100 kHz. The handler only owns the
* pulse-domain counter and must not pay the HAL/uC-OS dispatch cost on
* every pulse. No OS object is accessed by PlsrOnPulseIsr().
*/
if ((TIM10->SR & TIM_SR_UIF) != 0U)
{
TIM10->SR = (uint32_t)~TIM_SR_UIF;
PlsrOnPulseIsr();
}
} }


/** /**
@@ -269,9 +277,11 @@ void TIM1_UP_TIM10_IRQHandler(void)
*/ */
void TIM1_TRG_COM_TIM11_IRQHandler(void) void TIM1_TRG_COM_TIM11_IRQHandler(void)
{ {
OSIntEnter();
HAL_TIM_IRQHandler(&htim11);
OSIntExit();
if ((TIM11->SR & TIM_SR_UIF) != 0U)
{
TIM11->SR = (uint32_t)~TIM_SR_UIF;
PlsrOnPulseIsr();
}
} }


/** /**
@@ -279,9 +289,11 @@ void TIM1_TRG_COM_TIM11_IRQHandler(void)
*/ */
void TIM8_UP_TIM13_IRQHandler(void) void TIM8_UP_TIM13_IRQHandler(void)
{ {
OSIntEnter();
HAL_TIM_IRQHandler(&htim13);
OSIntExit();
if ((TIM13->SR & TIM_SR_UIF) != 0U)
{
TIM13->SR = (uint32_t)~TIM_SR_UIF;
PlsrOnPulseIsr();
}
} }


/** /**


+ 1653
- 1654
iar/plsr.dep
文件差異過大導致無法顯示
查看文件


+ 18
- 14
plsr/accel_curve/plsr_accel_curve.c 查看文件

@@ -241,20 +241,24 @@ uint32_t PlsrAccelCurveResolveEndHz(uint32_t f_cfg,


f_cfg = PlsrAccelCurveClampFreq(f_cfg); f_cfg = PlsrAccelCurveClampFreq(f_cfg);
f_tgt = PlsrAccelCurveClampFreq(f_tgt); f_tgt = PlsrAccelCurveClampFreq(f_tgt);
if (f_cfg >= 1U)
{
return f_cfg;
}
if (f_tgt < 1U) if (f_tgt < 1U)
{ {
return 1U; return 1U;
} }


t_dec = PlsrAccelCurveRampTimeMs(f_tgt, 0U, default_spd,
start_spd_ref, end_spd_ref,
accel_ms, decel_ms);
return PlsrAccelCurveJumpFromZero(f_tgt, t_dec,
start_spd_ref, end_spd_ref);
/*
* 止速 0 或 1:都按落地频率估计。1Hz 当真止速会在段末拖超长尾巴。
*/
if (f_cfg <= 1U)
{
t_dec = PlsrAccelCurveRampTimeMs(f_tgt, 0U, default_spd,
start_spd_ref, end_spd_ref,
accel_ms, decel_ms);
return PlsrAccelCurveJumpFromZero(f_tgt, t_dec,
start_spd_ref, end_spd_ref);
}

return f_cfg;
} }


/** 直线:进度千分比 → 形状千分比 */ /** 直线:进度千分比 → 形状千分比 */
@@ -609,14 +613,14 @@ static uint32_t PlsrAccelCurveEstimatePulses(uint32_t f_from,
return n; return n;
} }


/** 匀速时间向下取整:宁可早进减速,保证斜坡走完再落到 f_end */
/** 匀速时间向上取整:晚一点进减速,把脉冲留在峰值,避免斜坡中途脉冲耗尽 */
static uint32_t PlsrAccelCurveConstTimeMs(uint32_t const_n, uint32_t f_hz) static uint32_t PlsrAccelCurveConstTimeMs(uint32_t const_n, uint32_t f_hz)
{ {
if ((const_n == 0U) || (f_hz < 1U)) if ((const_n == 0U) || (f_hz < 1U))
{ {
return 0U; return 0U;
} }
return (const_n * 1000UL) / f_hz;
return (const_n * 1000UL + f_hz - 1UL) / f_hz;
} }


/** /**
@@ -956,9 +960,9 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
plan->acc_n = acc_n; plan->acc_n = acc_n;
plan->dec_n = dec_n; plan->dec_n = dec_n;
/* /*
* 进入减速时刻:加速时间 + 匀速时间。
* 三角无匀速 → t_decel_start = t_acc,减速从峰值立刻开始
* 止速脉冲数 = dec_n,由 1ms 模型按 (f_peak→f_end, t_dec) 估出
* 进入减速时刻(时间域反向规划):
* t_decel_start = t_acc + t_const,与加速从 t=0 正向规划对称
* t_const 向上取整,避免过早进减速、高频把脉冲烧光
*/ */
plan->t_decel_start_ms = t_acc + PlsrAccelCurveConstTimeMs(plan->const_n, f_peak); plan->t_decel_start_ms = t_acc + PlsrAccelCurveConstTimeMs(plan->const_n, f_peak);
} }


+ 1
- 1
plsr/accel_curve/plsr_accel_curve.h 查看文件

@@ -58,7 +58,7 @@ uint32_t PlsrAccelCurveResolveStartHz(uint32_t f_cfg,


/** /**
* 配置止速 → 规划用真实终点频率。 * 配置止速 → 规划用真实终点频率。
* f_cfg>=1:原样(钳位);f_cfg==0:按斜率算落地频率(避免 1Hz 拖尾)。
* f_cfg>1:原样(钳位);f_cfg<=1:按斜率算落地频率(禁止真 1Hz 拖尾)。
* 段末是否停表由运行层决定,与本函数无关。 * 段末是否停表由运行层决定,与本函数无关。
*/ */
uint32_t PlsrAccelCurveResolveEndHz(uint32_t f_cfg, uint32_t PlsrAccelCurveResolveEndHz(uint32_t f_cfg,


+ 86
- 6
plsr/run_control/plsr_run_control.c 查看文件

@@ -12,7 +12,9 @@
* 3) 发送模式只影响本段 f_end(完成=止速;后续且不停表=下一段目标) * 3) 发送模式只影响本段 f_end(完成=止速;后续且不停表=下一段目标)
* 4) PlanSeg / ChangeFreq 共用规划入口,便于后期动态改频 * 4) PlanSeg / ChangeFreq 共用规划入口,便于后期动态改频
* *
* 【运行节拍】TIM3 1ms:RefreshProfile 改频;脉冲 UPDATE ISR 只计 s_done。
* 【运行节拍】TIM3 1ms:RefreshProfile 改频。
* 加速:t=0 起正向走 t_acc;减速:按 t_decel_start(反向规划)或 remain<=dec_n 进入。
* 脉冲 UPDATE ISR 只计 s_done。
*/ */
#include "plsr_run_control.h" #include "plsr_run_control.h"
#include "plsr_path_plan.h" #include "plsr_path_plan.h"
@@ -67,6 +69,8 @@ static uint8_t s_follow_cont;
static uint32_t s_chain_freq; static uint32_t s_chain_freq;
static uint8_t s_chain_valid; static uint8_t s_chain_valid;
static uint8_t s_pwm_on; static uint8_t s_pwm_on;
static uint8_t s_dec_armed; /* 1=已按剩余脉冲进入减速时间轴 */
static uint32_t s_dec_t0_ms; /* 进入减速时的段内时间 */


/* 本段由策略层解析后的加减速时间(段内只用这两份,不再读 wait) */ /* 本段由策略层解析后的加减速时间(段内只用这两份,不再读 wait) */
static uint16_t s_run_accel_ms; static uint16_t s_run_accel_ms;
@@ -662,6 +666,8 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses)


PlsrRunControlEnterPhase(PH_DECEL, from_hz); PlsrRunControlEnterPhase(PH_DECEL, from_hz);
f_end = s_accel_plan.f_end; f_end = s_accel_plan.f_end;
s_dec_armed = 1U;
s_dec_t0_ms = s_seg_elapsed_ms;


if (remain_pulses == 0U) if (remain_pulses == 0U)
{ {
@@ -749,12 +755,78 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses)
static void PlsrRunControlRefreshProfile(uint8_t do_start) static void PlsrRunControlRefreshProfile(uint8_t do_start)
{ {
uint32_t next; uint32_t next;
uint32_t remain;
uint32_t t_rel;
uint8_t has_dec;

remain = 0U;
if (s_target > s_done)
{
remain = (uint32_t)(s_target - s_done);
}

has_dec = ((s_accel_plan.t_dec_ms > 0U) &&
(s_accel_plan.dec_n > 0U) &&
(s_accel_plan.f_tgt != s_accel_plan.f_end)) ? 1U : 0U;

if (has_dec != 0U)
{
/*
* 减速进点 = 反向规划(与加速对称):
* 1) 时间:elapsed >= t_decel_start(t_acc + t_const,规划已算好)
* 2) 脉冲:remain <= dec_n(从段末反推,防止脉冲先耗尽)
* 二者谁先到谁触发;斜坡形状仍用 t_dec 时间轴,与加速 t_acc 对称。
*/
if (s_dec_armed == 0U)
{
if ((s_seg_elapsed_ms >= s_accel_plan.t_decel_start_ms) ||
(remain <= s_accel_plan.dec_n))
{
s_dec_armed = 1U;
if (s_seg_elapsed_ms >= s_accel_plan.t_decel_start_ms)
{
/* 按规划时刻进:与 FreqAtSegTime 同一时间原点 */
s_dec_t0_ms = s_accel_plan.t_decel_start_ms;
}
else
{
/* 脉冲域先到:从当前时刻起跑减速斜坡 */
s_dec_t0_ms = s_seg_elapsed_ms;
}
PlsrRunControlEnterPhase(PH_DECEL, s_accel_plan.f_tgt);
}
}

if (s_dec_armed != 0U)
{
t_rel = s_seg_elapsed_ms - s_dec_t0_ms;
next = PlsrAccelCurveFreqOnRampMs(s_accel_plan.f_tgt,
s_accel_plan.f_end,
t_rel,
s_accel_plan.t_dec_ms,
s_accel_plan.mode);
}
else if ((s_accel_plan.t_acc_ms > 0U) &&
(s_seg_elapsed_ms < s_accel_plan.t_acc_ms) &&
(s_accel_plan.f_cur != s_accel_plan.f_tgt))
{
/* 加速:从 t=0 正向规划 */
next = PlsrAccelCurveFreqOnRampMs(s_accel_plan.f_cur,
s_accel_plan.f_tgt,
s_seg_elapsed_ms,
s_accel_plan.t_acc_ms,
s_accel_plan.mode);
}
else
{
next = s_accel_plan.f_tgt;
}
}
else
{
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms);
}


/*
* 1ms 改频:段内统一时间轴;t_decel_start_ms 由规划反向算出,
* 减速为 f_tgt→f_end 直线,自然落到止速,末拍不再强行对齐。
*/
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms);
if (next < 1U) if (next < 1U)
{ {
next = 1U; next = 1U;
@@ -858,6 +930,8 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,


s_approach_from = f_start; s_approach_from = f_start;
s_decel_from = s_accel_plan.f_tgt; s_decel_from = s_accel_plan.f_tgt;
s_dec_armed = 0U;
s_dec_t0_ms = 0U;
if (s_pwm_on == 0U) if (s_pwm_on == 0U)
{ {
s_cur_freq = f_start; s_cur_freq = f_start;
@@ -902,6 +976,8 @@ static void PlsrRunControlFinishAll(void)
s_follow_cont = 0U; s_follow_cont = 0U;
s_chain_valid = 0U; s_chain_valid = 0U;
s_chain_freq = 0U; s_chain_freq = 0U;
s_dec_armed = 0U;
s_dec_t0_ms = 0U;
s_act_armed = 0U; s_act_armed = 0U;
s_act_expire_req = 0U; s_act_expire_req = 0U;
s_act_cut_pending = 0U; s_act_cut_pending = 0U;
@@ -1030,6 +1106,8 @@ void PlsrRunControlInit(void)
s_seg_elapsed_ms = 0U; s_seg_elapsed_ms = 0U;
s_approach_from = 0U; s_approach_from = 0U;
s_decel_from = 0U; s_decel_from = 0U;
s_dec_armed = 0U;
s_dec_t0_ms = 0U;
s_act_armed = 0U; s_act_armed = 0U;
s_act_expire_req = 0U; s_act_expire_req = 0U;
s_act_cut_pending = 0U; s_act_cut_pending = 0U;
@@ -1083,6 +1161,8 @@ void PlsrRunControlStop(void)
s_follow_cont = 0U; s_follow_cont = 0U;
s_chain_valid = 0U; s_chain_valid = 0U;
s_chain_freq = 0U; s_chain_freq = 0U;
s_dec_armed = 0U;
s_dec_t0_ms = 0U;
s_act_armed = 0U; s_act_armed = 0U;
s_act_expire_req = 0U; s_act_expire_req = 0U;
s_act_cut_pending = 0U; s_act_cut_pending = 0U;


Loading…
取消
儲存