Explorar el Código

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

master
hanyongwei hace 1 mes
padre
commit
748ff59108
Se han modificado 8 ficheros con 1710 adiciones y 1611 borrados
  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 Ver fichero

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

+ 1578
- 1578
iar/plsr.dep
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 60
- 1
plsr/accel_curve/plsr_accel_curve.c Ver fichero

@@ -234,6 +234,57 @@ uint32_t PlsrAccelCurveFreqOnRampUs(uint32_t f0,
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。
@@ -264,7 +315,15 @@ static uint32_t PlsrAccelCurveEstimatePulses(uint32_t f_from,
f = PlsrAccelCurveFreqOnRampUs(f_from, f_to, elapsed_us, T_us, mode);
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;
n++;


+ 9
- 0
plsr/accel_curve/plsr_accel_curve.h Ver fichero

@@ -43,6 +43,15 @@ uint32_t PlsrAccelCurveFreqOnRampUs(uint32_t f0,
uint32_t T_us,
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(任务上下文) */
uint32_t PlsrAccelCurveFitRampTimeMs(uint32_t f_from,
uint32_t f_to,


+ 4
- 4
plsr/param/plsr_param.h Ver fichero

@@ -47,7 +47,7 @@
#define PLSR_SEG_OFF_WAIT 4U /* 等待类型 */
#define PLSR_SEG_OFF_WAIT_MS 5U
#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
@@ -102,8 +102,8 @@ typedef struct {
uint16_t seg_count;
uint16_t start_seg; /* 1-based */
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 decel_ms; /* 默认速度减速时间 ms(定减速斜率) */
} PlsrCfg_t;
@@ -115,7 +115,7 @@ typedef struct {
PlsrWaitType_e wait_type;
uint16_t wait_ms;
uint16_t act_ms;
uint16_t jump_seg; /* 0=顺序;1~N=跳转 */
uint16_t jump_seg; /* 0=结束;1~N=跳转目标段号 */
} PlsrSeg_t;

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


+ 8
- 7
plsr/path_plan/plsr_path_plan.c Ver fichero

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

/* jump=0:顺序下一;越界则结束 */
/*
* 跳转目标(1-based):
* 0 → 结束(含末段写 0)
* 1..N → 跳到对应段(可顺序、回跳循环、任意段)
* 其它 → 结束
*/
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))
{
return (int16_t)(jump - 1U);


+ 1
- 1
plsr/path_plan/plsr_path_plan.h Ver fichero

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



+ 48
- 20
plsr/run_control/plsr_run_control.c Ver fichero

@@ -152,6 +152,16 @@ static uint32_t PlsrRunControlClampSpeed(uint32_t 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)
{
/*
@@ -374,6 +384,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start)
/*
* ARPE 超前一拍:这里算出的 next 是“再下一拍”的预装载。
* remain==2 时预装载最后一拍 → 必须为 f_end;remain==1 最后一拍已在跑。
* (止速参数为 0 时规划端点已是 1Hz,最后一拍落到 1Hz 再段结束停表。)
*/
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
{
/* 起速可为 0:规划/斜率按 0;开跑第一拍用 FirstPulseFreq(≥1Hz) */
f_from = PlsrRunControlClampSpeed(cfg->start_speed);
}

@@ -709,6 +719,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0)
}
else
{
/* 止速可为 0:规划减到 0;运行输出下限 1Hz */
f_end = PlsrRunControlClampSpeed(cfg->end_speed);
}
}
@@ -866,29 +877,46 @@ void PlsrRunControlTickMs(void)
{
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 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_accel_plan.f_tgt,
per,
T_us,
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;


Cargando…
Cancelar
Guardar