Selaa lähdekoodia

增加段最后一个参数“跳转至”

master
hanyongwei 1 kuukausi sitten
vanhempi
commit
748ff59108
8 muutettua tiedostoa jossa 1710 lisäystä ja 1611 poistoa
  1. +2
    -0
      .gitignore
  2. +1578
    -1578
      iar/plsr.dep
  3. +60
    -1
      plsr/accel_curve/plsr_accel_curve.c
  4. +9
    -0
      plsr/accel_curve/plsr_accel_curve.h
  5. +4
    -4
      plsr/param/plsr_param.h
  6. +8
    -7
      plsr/path_plan/plsr_path_plan.c
  7. +1
    -1
      plsr/path_plan/plsr_path_plan.h
  8. +48
    -20
      plsr/run_control/plsr_run_control.c

+ 2
- 0
.gitignore Näytä tiedosto

@@ -21,3 +21,5 @@ build-plsr_host-Desktop_Qt_5_6_3_MinGW_32bit-Debug/
plsr/test/ plsr/test/
tools/ tools/
.cursor/ .cursor/
*.pdf
3. 定位控制手册.pdf

+ 1578
- 1578
iar/plsr.dep
File diff suppressed because it is too large
Näytä tiedosto


+ 60
- 1
plsr/accel_curve/plsr_accel_curve.c Näytä tiedosto

@@ -234,6 +234,57 @@ uint32_t PlsrAccelCurveFreqOnRampUs(uint32_t f0,
return PlsrAccelCurveLerp(f0, f1, r); return PlsrAccelCurveLerp(f0, f1, r);
} }


/**
* 斜坡第一拍频率(规划/开跑共用)。
* f0>=1:第一拍即 f0。
* f0==0:t=0 曲线为 0;若强行按 1Hz 计整周期(~1s),加速时间常被第一拍吃光,
* 表现为到不了目标频、曲线台阶/长拖尾。此处用 look-ahead 自洽点,且 ≥1Hz。
*/
uint32_t PlsrAccelCurveFirstPulseFreq(uint32_t f0,
uint32_t f1,
uint32_t T_us,
PlsrAccelMode_e mode)
{
uint32_t f;
uint32_t guess;
uint32_t per;
uint32_t fnew;
uint32_t i;

if (T_us == 0U)
{
f = (f1 >= 1U) ? f1 : 1U;
return f;
}

f = PlsrAccelCurveFreqOnRampUs(f0, f1, 0U, T_us, mode);
if (f >= 1U)
{
return f;
}

guess = (f1 >= 2U) ? (f1 / 2U) : 1U;
if (guess < 1U)
{
guess = 1U;
}
for (i = 0U; i < 8U; i++)
{
per = (1000000UL + (guess / 2UL)) / guess;
fnew = PlsrAccelCurveFreqOnRampUs(f0, f1, per, T_us, mode);
if (fnew < 1U)
{
fnew = 1U;
}
if (fnew == guess)
{
break;
}
guess = fnew;
}
return guess;
}

/** /**
* 脉冲起点锁频递推脉冲数(与 ISR 一致);f(t) 按 mode 形状。 * 脉冲起点锁频递推脉冲数(与 ISR 一致);f(t) 按 mode 形状。
* 仅任务/规划上下文;禁止进脉冲 ISR。 * 仅任务/规划上下文;禁止进脉冲 ISR。
@@ -264,7 +315,15 @@ static uint32_t PlsrAccelCurveEstimatePulses(uint32_t f_from,
f = PlsrAccelCurveFreqOnRampUs(f_from, f_to, elapsed_us, T_us, mode); f = PlsrAccelCurveFreqOnRampUs(f_from, f_to, elapsed_us, T_us, mode);
if (f < 1U) if (f < 1U)
{ {
f = 1U;
if ((elapsed_us == 0U) && (f_from == 0U))
{
f = PlsrAccelCurveFirstPulseFreq(f_from, f_to, T_us, mode);
}
else
{
/* 止速到 0:末段按 1Hz 计周期,与运行输出下限一致 */
f = 1U;
}
} }
elapsed_us += (1000000UL + (f / 2UL)) / f; elapsed_us += (1000000UL + (f / 2UL)) / f;
n++; n++;


+ 9
- 0
plsr/accel_curve/plsr_accel_curve.h Näytä tiedosto

@@ -43,6 +43,15 @@ uint32_t PlsrAccelCurveFreqOnRampUs(uint32_t f0,
uint32_t T_us, uint32_t T_us,
PlsrAccelMode_e mode); PlsrAccelMode_e mode);


/**
* 斜坡第一拍频率(起速为 0 时用自洽点,避免按 1Hz 整秒吃光加速相)。
* ISR 可用:O(1)。
*/
uint32_t PlsrAccelCurveFirstPulseFreq(uint32_t f0,
uint32_t f1,
uint32_t T_us,
PlsrAccelMode_e mode);

/** 拟合斜坡时间(ms),使离散模型脉冲数尽量等于 max_pulses(任务上下文) */ /** 拟合斜坡时间(ms),使离散模型脉冲数尽量等于 max_pulses(任务上下文) */
uint32_t PlsrAccelCurveFitRampTimeMs(uint32_t f_from, uint32_t PlsrAccelCurveFitRampTimeMs(uint32_t f_from,
uint32_t f_to, uint32_t f_to,


+ 4
- 4
plsr/param/plsr_param.h Näytä tiedosto

@@ -47,7 +47,7 @@
#define PLSR_SEG_OFF_WAIT 4U /* 等待类型 */ #define PLSR_SEG_OFF_WAIT 4U /* 等待类型 */
#define PLSR_SEG_OFF_WAIT_MS 5U #define PLSR_SEG_OFF_WAIT_MS 5U
#define PLSR_SEG_OFF_ACT_MS 6U #define PLSR_SEG_OFF_ACT_MS 6U
#define PLSR_SEG_OFF_JUMP 7U /* 0=顺序下一段;1~N=跳转段号 */
#define PLSR_SEG_OFF_JUMP 7U /* 0=结束;1~N=跳转目标段号 */


/* 分帧传输状态(上位机可轮询) */ /* 分帧传输状态(上位机可轮询) */
#define PLSR_PARAM_XFER_RECV_REG 0x0FFCU #define PLSR_PARAM_XFER_RECV_REG 0x0FFCU
@@ -102,8 +102,8 @@ typedef struct {
uint16_t seg_count; uint16_t seg_count;
uint16_t start_seg; /* 1-based */ uint16_t start_seg; /* 1-based */
uint32_t default_speed; /* 脉冲默认速度 Hz:定加减速斜率 K;段频为 0 时也作段目标 */ uint32_t default_speed; /* 脉冲默认速度 Hz:定加减速斜率 K;段频为 0 时也作段目标 */
uint32_t start_speed; /* 脉冲起始速度:首段(或断链重启)从该频起跳 */
uint32_t end_speed; /* 脉冲终止速度:末段减速落到该频后再停 */
uint32_t start_speed; /* 起速Hz;0=从静止按斜率爬升,输出≥1Hz */
uint32_t end_speed; /* 止速Hz;0=规划减到0,输出收到≥1Hz再停 */
uint16_t accel_ms; /* 默认速度加速时间 ms(定加速斜率) */ uint16_t accel_ms; /* 默认速度加速时间 ms(定加速斜率) */
uint16_t decel_ms; /* 默认速度减速时间 ms(定减速斜率) */ uint16_t decel_ms; /* 默认速度减速时间 ms(定减速斜率) */
} PlsrCfg_t; } PlsrCfg_t;
@@ -115,7 +115,7 @@ typedef struct {
PlsrWaitType_e wait_type; PlsrWaitType_e wait_type;
uint16_t wait_ms; uint16_t wait_ms;
uint16_t act_ms; uint16_t act_ms;
uint16_t jump_seg; /* 0=顺序;1~N=跳转 */
uint16_t jump_seg; /* 0=结束;1~N=跳转目标段号 */
} PlsrSeg_t; } PlsrSeg_t;


/* ---------- 运行映像访问 ---------- */ /* ---------- 运行映像访问 ---------- */


+ 8
- 7
plsr/path_plan/plsr_path_plan.c Näytä tiedosto

@@ -11,16 +11,17 @@ int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based)
uint16_t n = PlsrParamGetSegCount(); uint16_t n = PlsrParamGetSegCount();
uint16_t jump = seg->jump_seg; uint16_t jump = seg->jump_seg;


/* jump=0:顺序下一;越界则结束 */
/*
* 跳转目标(1-based):
* 0 → 结束(含末段写 0)
* 1..N → 跳到对应段(可顺序、回跳循环、任意段)
* 其它 → 结束
*/
if (jump == 0U) if (jump == 0U)
{ {
if ((cur_seg_0based + 1U) >= n)
{
return -1;
}
return (int16_t)(cur_seg_0based + 1U);
(void)cur_seg_0based;
return -1;
} }
/* jump=1..N:跳到指定段;非法则结束 */
if ((jump >= 1U) && (jump <= n)) if ((jump >= 1U) && (jump <= n))
{ {
return (int16_t)(jump - 1U); return (int16_t)(jump - 1U);


+ 1
- 1
plsr/path_plan/plsr_path_plan.h Näytä tiedosto

@@ -14,7 +14,7 @@
* @brief 解析下一段索引 * @brief 解析下一段索引
* @param cur_seg_0based 当前段 0-based * @param cur_seg_0based 当前段 0-based
* @return 下一段 0-based;无下一段或非法跳转返回 -1 * @return 下一段 0-based;无下一段或非法跳转返回 -1
* @note jump=0 顺序下一段;jump=1~N 跳到对应段
* @note jump=0 结束;jump=1~N 跳到对应段(可循环)
*/ */
int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based); int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based);




+ 48
- 20
plsr/run_control/plsr_run_control.c Näytä tiedosto

@@ -152,6 +152,16 @@ static uint32_t PlsrRunControlClampSpeed(uint32_t spd)
return spd; return spd;
} }


/** 运行输出下限:参数起/止速为 0 时曲线可算到 0,TIM 最低按 1Hz 输出 */
static uint32_t PlsrRunControlOutFreq(uint32_t f)
{
if (f < 1U)
{
return 1U;
}
return f;
}

static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start)
{ {
/* /*
@@ -374,6 +384,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start)
/* /*
* ARPE 超前一拍:这里算出的 next 是“再下一拍”的预装载。 * ARPE 超前一拍:这里算出的 next 是“再下一拍”的预装载。
* remain==2 时预装载最后一拍 → 必须为 f_end;remain==1 最后一拍已在跑。 * remain==2 时预装载最后一拍 → 必须为 f_end;remain==1 最后一拍已在跑。
* (止速参数为 0 时规划端点已是 1Hz,最后一拍落到 1Hz 再段结束停表。)
*/ */
if ((remain <= 1U) || (T_us == 0U)) if ((remain <= 1U) || (T_us == 0U))
{ {
@@ -409,16 +420,14 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start)
} }
} }


if ((do_start != 0U) || (next != s_pending_freq) || (s_pwm_on == 0U))
if (next < 1U)
{ {
PlsrRunControlApplyOutFreq(next, do_start);
next = 1U;
} }


if ((next == 0U) && (s_phase == PH_DECEL) && (s_state == RC_RUN) &&
(s_done < s_target))
if ((do_start != 0U) || (next != s_pending_freq) || (s_pwm_on == 0U))
{ {
s_done = s_target;
PlsrRunControlAfterSegDone();
PlsrRunControlApplyOutFreq(next, do_start);
} }
} }


@@ -683,6 +692,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0)
} }
else else
{ {
/* 起速可为 0:规划/斜率按 0;开跑第一拍用 FirstPulseFreq(≥1Hz) */
f_from = PlsrRunControlClampSpeed(cfg->start_speed); f_from = PlsrRunControlClampSpeed(cfg->start_speed);
} }


@@ -709,6 +719,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0)
} }
else else
{ {
/* 止速可为 0:规划减到 0;运行输出下限 1Hz */
f_end = PlsrRunControlClampSpeed(cfg->end_speed); f_end = PlsrRunControlClampSpeed(cfg->end_speed);
} }
} }
@@ -866,29 +877,46 @@ void PlsrRunControlTickMs(void)
{ {
PlsrRunControlEnterPhase(PH_CONST, s_approach_from); PlsrRunControlEnterPhase(PH_CONST, s_approach_from);
} }
/* 第一个脉冲 = 脉冲起始速度(不是目标频、不是 1Hz) */
PlsrRunControlApplyOutFreq(s_approach_from, 1U);
/* /*
* ARPE:立刻预装载第 2 拍频率,否则第 2 拍仍是起速(等于多锁一拍低频)。
* 第一拍:起速>0 用起速;起速=0 用 FirstPulseFreq(≥1Hz 自洽点)。
* 禁止整拍按 1Hz(周期约 1s)开跑,否则会吃光加速相。
*/ */
if ((s_phase == PH_APPROACH) && (s_approach_from >= 1U) &&
(s_approach_from != s_accel_plan.f_tgt))
{ {
uint32_t T_us = s_accel_plan.t_acc_ms * 1000UL; uint32_t T_us = s_accel_plan.t_acc_ms * 1000UL;
uint32_t per = (1000000UL + (s_approach_from / 2UL)) /
s_approach_from;
uint32_t f2 = PlsrAccelCurveFreqOnRampUs(
uint32_t f_start;
uint32_t per;
uint32_t f2;

if (s_phase == PH_CONST)
{
f_start = PlsrRunControlOutFreq(s_approach_from);
if ((s_approach_from == 0U) &&
(s_accel_plan.f_tgt >= 1U))
{
f_start = s_accel_plan.f_tgt;
}
PlsrRunControlApplyOutFreq(f_start, 1U);
}
else
{
f_start = PlsrAccelCurveFirstPulseFreq(
s_approach_from, s_approach_from,
s_accel_plan.f_tgt, s_accel_plan.f_tgt,
per,
T_us, T_us,
s_accel_plan.mode); s_accel_plan.mode);
if (f2 < 1U)
{
f2 = 1U;
f_start = PlsrRunControlOutFreq(f_start);
PlsrRunControlApplyOutFreq(f_start, 1U);
per = (1000000UL + (f_start / 2UL)) / f_start;
f2 = PlsrAccelCurveFreqOnRampUs(
s_approach_from,
s_accel_plan.f_tgt,
per,
T_us,
s_accel_plan.mode);
f2 = PlsrRunControlOutFreq(f2);
PlsrRunControlApplyOutFreq(f2, 0U);
PlsrPulseDriverApplyPending();
} }
PlsrRunControlApplyOutFreq(f2, 0U);
PlsrPulseDriverApplyPending();
} }
} }
return; return;


Ladataan…
Peruuta
Tallenna