motor_cs103/User/lib/control/src/s_curve.c

172 lines
4.2 KiB
C

#include "s_curve.h"
// s曲线加速度各段参数定义
// 起始速度
#define F0 0.0f
// 加加速度与减减速度
#define FAA 0.0f
#define FRR 0.0f
// 加速段三个时间
#define TAA 0.1f
#define TUA 0.2f
#define TRA 0.1f
// 匀速段
#define TUU 5.0f
// 减速段
#define TAR 0.1f
#define TUR 0.2f
#define TRR 0.1f
// 表格长度
#define S_CURVE_TABLE_LEN 400
int16_t s_curve_table[S_CURVE_TABLE_LEN] = {0};
static int16_t s_curve_func(s_curve_t *s, float32 t, float32 *freq, float32 *acc)
{
// 辅助常数项
float32 A, B, C, D, E, F;
// 表达式中间值
float32 f3, f4, f5;
// 加速段,匀速段,减速段时间
float32 Ta, Tu, Tr;
// 减加速与加减速段斜率
float32 fra, far;
// 起始频率与加加速频率,减减速频率
float32 f0, faa, frr;
float32 taa, tua, tra, tuu, tar, tur, trr;
// 获取参数
faa = s->faa;
frr = s->frr;
taa = s->taa;
tua = s->tua;
tra = s->tra;
tuu = s->tuu;
tar = s->tar;
tur = s->tur;
trr = s->trr;
f0 = s->f0;
fra = faa * taa / tra;
far = frr * trr / tar;
Ta = taa + tua + tra;
Tu = tuu;
Tr = tar + tur + trr;
A = f0;
B = f0 - 0.5 * faa * taa * taa;
C = f0 + 0.5 * faa * taa * taa + faa * taa * tua + 0.5 * fra * (taa + tua) * (taa + tua) - fra * Ta * (taa + tua);
// f1 = f0 + 0.5 * faa * taa * taa;
// f2 = f0 + 0.5 * faa * taa * taa + faa * taa * tua;
f3 = 0.5 * fra * Ta * Ta + C;
D = f3 - 0.5 * far * (Ta + Tu) * (Ta + Tu);
f4 = -far * 0.5 * (Ta + Tu + tar) * (Ta + Tu + tar) + far * (Ta + Tu) * (Ta + Tu + tar) + D;
E = f4 + far * tar * (Ta + Tu + tar);
f5 = -far * tar * (Ta + Tu + Tr - trr) + E;
F = f5 + frr * (Ta + Tu + Tr) * (Ta + Tu + Tr - trr) - 0.5 * frr * (Ta + Tu + Tr - trr) * (Ta + Tu + Tr - trr);
// 如果时间点在全行程规定的时间段内
if ((t >= 0) && (t <= Ta + Tu + Tr))
{
// 加加速段
if ((t >= 0) && (t <= taa))
{
*freq = 0.5 * faa * t * t + A;
*acc = faa * t;
}
// 匀加速段
else if ((t >= taa) && (t <= taa + tua))
{
*freq = faa * taa * t + B;
*acc = faa * taa;
}
// 加减速段
else if ((t >= taa + tua) && (t <= taa + tua + tra))
{
*freq = -0.5 * fra * t * t + fra * Ta * t + C;
*acc = -fra * t + fra * Ta;
}
// 匀速段
else if ((t >= Ta) && (t <= Ta + tuu))
{
*freq = f3;
*acc = 0;
}
// 加减速段
else if ((t >= Ta + Tu) && (t <= Ta + Tu + tar))
{
*freq = -0.5 * far * t * t + far * (Ta + Tu) * t + D;
*acc = -far * t + far * (Ta + Tu);
}
// 匀减速
else if ((t >= Ta + Tu + tar) && (t <= Ta + Tu + tar + tur))
{
*freq = -far * tar * t + E;
*acc = -far * tar;
}
// 减减速
else if ((t >= Ta + Tu + Tr - trr) && (t <= Ta + Tu + Tr))
{
*freq = 0.5 * frr * t * t - frr * (Ta + Tu + Tr) * t + F;
*acc = frr * t - frr * (Ta + Tu + Tr);
}
}
else
{
return -1;
}
return 0;
}
// S型曲线初始化
void s_curve_table_gen(uint16_t tmin, uint16_t tmax)
{
uint16_t i, tint;
float32 ti;
float32 freq;
float32 acc;
float32 fi;
s_curve_t s;
osel_memset((uint8_t *)&s, 0, sizeof(s_curve_t));
s.f0 = F0;
s.taa = TAA;
s.tua = TUA;
s.tra = TRA;
s.tuu = TUU;
s.tar = TAR;
s.tur = TUR;
s.trr = TRR;
// 根据约束条件求出加加速段与减减速段斜率
s.faa = 2.0 / (s.taa * (s.taa + s.tra + 2 * s.tua));
s.frr = 2.0 / (s.trr * (s.tar + s.trr + 2 * s.tur));
for (i = 0; i < S_CURVE_TABLE_LEN; i++)
{
// 求出每个时间点对应的频率以及加速度
fi = i * (TAA + TUA + TRA + TUU + TAR + TUR + TRR) / S_CURVE_TABLE_LEN;
s_curve_func(&s, fi, &freq, &acc);
// 根据最大与最小装载值确定定时器实际值
ti = tmax - (tmax - tmin) * freq;
// 转换为整数值
tint = (uint16_t)ti;
// 存入s曲线表
s_curve_table[i] = tint;
}
}