步进电机参数变量
<p>[TOC]</p>
<h2>定义参数</h2>
<p>1.T1_FREQ --> (90000000/90) </p>
<pre><code>频率ft值 时钟源频率值/分频值=一个新的频率值 (用于定时器中断的频率,以控制步进电机的步进速度)</code></pre>
<p>2.FSPR --> 200</p>
<pre><code> 步进电机单圈步数 (步进电机的每一步都会使电机的转子转动一个固定的角度,单圈步数决定了电机旋转一圈所需的步数)</code></pre>
<p>3.MICRO_STEP --> 4</p>
<pre><code> 微步数 微步(或细分)是一种通过控制步进电机驱动器来减小电机每一步转动的角度的技术。通过微步控制,可以提高步进电机的分辨率和精度。每个全步被细分为4个微步,意味着电机的旋转将更加平滑和精确(就是转一圈,800步!!)</code></pre>
<p>4.SPR --> (FSPR * MICRO_STEP)</p>
<pre><code> 单圈所需要的脉冲数=全步数乘以微步数 为了控制步进电机旋转一圈,需要发送200*4 =800个脉冲信号给电机驱动器。(就是转一圈,800步!!)</code></pre>
<p>5.SPR --> (FSPR * MICRO_STEP)</p>
<pre><code> 单圈所需要的脉冲数=全步数*微步数 为了控制步进电机旋转一圈,需要发送200*4 =800个脉冲信号给电机驱动器。(就是转一圈,800步!!)</code></pre>
<p>6.ROUNDPS_2_STEPPS(rpm) --> ((rpm) * SPR / 60)</p>
<pre><code> 根据电机转速(r/min),计算电机步速(step/s)</code></pre>
<p>7.MIDDLEVELOCITY(vo,vt) --> ( ( (vo) + (vt) ) / 2 )</p>
<pre><code> S型加减速 加速段的中点速度 vo是初始速度,vt是目标速度。 计算方法是:取vo和vt的平均值。</code></pre>
<p>8.INCACCEL(vo,v,t) --> ( ( 2 * ((v) - (vo)) ) / pow((t),2) )</p>
<pre><code> k 是加速度的斜率=jerk 加加速度:加速度增加量 V - V0 = 1/2 * J * t^2 v是MIDDLEVELOCITY 加速段的中点速度 计算从初始速度vo到速度v在时间t内的加加速度(加速度的变化率)</code></pre>
<p>9.INCACCELSTEP(j,t) ( ( (j) * pow( (t) , 3 ) ) / 6.0f )</p>
<pre><code> 加加速段的位移量(步数) S = 1/6 * J * t^3 计算在加加速段内,给定加加速度j和时间t,电机所走的步数(位移)。</code></pre>
<p>10.ACCEL_TIME(t) ( (t) / 2 )</p>
<pre><code> 加加速段和减加速段的时间是相等的 计算加加速段(或减加速段,因为假设它们是对称的)的时间长度。 这里简单地假设加加速段和减加速段的时间是相同的,且等于总时间t的一半</code></pre>
<p>11.SPEED_MIN (T1_FREQ / (65536.0f))</p>
<pre><code> 最低频率/速度 15.2587890625
定义了一个最低速度,它是基于定时器频率T1_FREQ(之前定义)和这种假定的分辨率(这里使用了65536作为分母,可能是与某个定时器的分辨率或计数器范围相关)计算得出的。
这个最低速度是用于防止电机在非常低的频率下运行时出现不稳定或无法准确控制的情况!!!</code></pre>
<p>12.CW (0) /<em>顺时针</em>/
13.CCW (1) /<em>逆时针</em>/</p>
<h2>结构体/枚举</h2>
<p>1.speed_calc_t --> 速度计算</p>
<pre><code> int32_t vo; /* 初速度 单位 step/s */
int32_t vt; /* 末速度 单位 step/s */
int32_t accel_step; /* 加速段的步数单位 step */
int32_t decel_step; /* 减速段的步数单位 step */
float *accel_tab; /* 加速度表格 单位 step/s 步进电机的脉冲频率 */
float *decel_tab; /* 减速度表格 单位 step/s 步进电机的脉冲频率 */
float *ptr; /* 速度指针 */
int32_t dec_point; /* 减速点 */
int32_t step;
int32_t step_pos; //已走的步数</code></pre>
<p>1.motor_state_typedef --> 电机状态类型</p>
<pre><code> STATE_ACCEL = 1, /* 电机加速状态 */
STATE_AVESPEED = 2, /* 电机匀速状态 */
STATE_DECEL = 3, /* 电机减速状态 */
STATE_STOP = 0, /* 电机停止状态 */
STATE_IDLE = 4, /* 电机空闲状态 */</code></pre>
<h2>步进电机速度定义</h2>
<pre><code>//垂直运动
#define V_START_V 0 /* 初速度 */
#define V_END_V 120 /* 末速度 */
#define ACCELTIME_V 3.0f /* 加速时间 (s) */
#define DECEELTIME_V 3.0f /* 减速时间 (s) */
//水平运动
#define V_START_H 0 /* 初速度 */
#define V_END_H 40 /* 末速度 */
#define ACCELTIME_H 3.0f /* 加速时间 (s) */
#define DECEELTIME_H 3.0f /* 减速时间 (s) */
#define V_START_R 0 /* 初速度 */
#define V_END_R 120 /* 末速度 */
#define ACCELTIME_R 3.0f /* 加速时间 (s) */
/*表示电机的加速时间,单位是秒(s)。f 后缀表明这是一个浮点数(float 类型),
尽管在某些情况下宏定义可能不会直接处理类型后缀,但这里的使用表明了对精确度的要求。
在这个例子中,电机将用3秒的时间从静止加速到目标速度。*/
#define DECEELTIME_R 3.0f /* 减速时间 (s) */
////低速运动(原先的低速)
//#define V_START_RL 0 /* 初速度 */
//#define V_END_RL 60 /* 末速度 */
//#define ACCELTIME_RL 5.0f /* 加速时间 (s) */
//#define DECEELTIME_RL 5.0f /* 减速时间 (s) */
//低速运动(修改过的低速)
#define V_START_RL 0 /* 初速度 */
#define V_END_RL 30 /* 末速度 */
#define ACCELTIME_RL 3.0f /* 加速时间 (s) */
#define DECEELTIME_RL 7.0f /* 减速时间 (s) */</code></pre>
<h2>全局变量</h2>
<pre><code class="language-c">uint32_t g_toggle_pulse[MAX_MOTOR_NUM]; /* 用于存储每个电机的脉冲频率控制值*/
extern volatile motor_state_typedef g_motor_sta[MAX_MOTOR_NUM]; /* 用于存储每个电机的状态 */
extern volatile speed_calc_t g_calc_t[MAX_MOTOR_NUM]; /*用于存储与每个电机速度计算相关的信息 用于速度计算所需的各种参数和结果,比如当前速度、加速度、目标速度等。*/</code></pre>
<h3>S型加减速</h3>
<ol>
<li>
<p>二维数组,第二维分别是 4000 和 4500,这代表了加速度和减速度表中每个电机对应的速度数据点的数量。
这些数值的选择取决于具体的应用需求,如加速度和减速度曲线的精细程度、控制周期等。
在控制程序中,根据当前电机状态和目标状态(如速度、位置等),程序会查询相应的加速度或减速度表,以决定下一控制周期内的电机控制指令</p>
<p>float velocity_tab_a[MAX_MOTOR_NUM][4000]; //加速度表
float velocity_tab_d[MAX_MOTOR_NUM][4500]; //减速度表</p>
</li>
</ol>
<p>2.计算速度表1 ,2</p>
<pre><code class="language-c">
uint8_t calc_speed1(int32_t vo, int32_t vt, float time) /*计算速度1 计算并生成一个速度表(velocity_tab_a 或 velocity_tab_d),
用于控制电机在加速或减速过程中的每一步速度。它接受初始速度 vo、目标速度 vt 和时间 time 作为输入,
并基于这些参数计算出一个平滑的加减速过程。*/
{
uint8_t is_dec = FALSE; //是否减速:不是减速
int32_t i = 0;
int32_t vm = 0;//中间速度 加速段的中点速度
int32_t inc_acc_stp = 0; //加速度步数
int32_t dec_acc_stp = 0; //减速度步数
int32_t accel_step = 0; // 加速段总步数
float jerk = 0;
float ti = 0; //时间变量
float sum_t = 0; //时间变量
float delta_v = 0; //速度变化量 (加速度)
float ti_cube = 0; //时间立方的变量
if(vo &gt; vt) //减速处理 生成速度表 velocity_tab_d
{
is_dec = TRUE;
//交换 vo 和 vt 的值
g_calc_t[0].vo = ROUNDPS_2_STEPPS(vt); //电机转速-&gt;电机步数 (vt)
g_calc_t[0].vt = ROUNDPS_2_STEPPS(vo); //电机转速-&gt;电机步数 (vo)
time = ACCEL_TIME(time);
//计算中间速度 vm
vm = (g_calc_t[0].vo + g_calc_t[0].vt) / 2 ;//S型加减速 加速段的中点速度
//计算加加速度 jerk
jerk = fabs(2.0f * (vm - g_calc_t[0].vo) / (time * time));//计算一个浮点数的绝对值 k=jerk (加加速度;加速度增加量)
//计算减加速和减减速阶段的步数,和总步数
inc_acc_stp = (int32_t)(g_calc_t[0].vo * time + INCACCELSTEP(jerk, time));//初始速度*时间=路程 + 加加速段的步数
dec_acc_stp = (int32_t)((g_calc_t[0].vt + g_calc_t[0].vo) * time - inc_acc_stp);//总步数-加速步数
accel_step = dec_acc_stp + inc_acc_stp;
//生成速度表(减速) velocity_tab_d
//判断减速总步数是否为奇数 奇数+1 (不能用减减速阶段)
if(accel_step % 2 != 0)
{
accel_step += 1;
}
//设置初始条件
decel_pulse_num[0] = accel_step;//电机减速阶段脉冲数量 = 总步数
//计算第一个减速点的速度
ti_cube = 6.0f * 1.0f / jerk; //公式 s=(1/6)*jerk* t的立方 反推t的立方
ti = pow(ti_cube, (1 / 3.0f));// 把t的立方变成t(时间间隔 ti) 用于计算一个数的幂 (double x, double y) x 的 y 次幂,即 x^y
sum_t = ti;//累计时间
delta_v = 0.5f * jerk * pow(sum_t, 2);//速度变化量 Vm - V0
//更新减速度表velocity_tab_d的第一个元素
velocity_tab_d[0][0] = g_calc_t[0].vo + delta_v; //初始速度+速度变化量
if(velocity_tab_d[0][0] &lt;= SPEED_MIN) //如果小于等于最低速度
{
velocity_tab_d[0][0] = SPEED_MIN;
}
//循环计算剩余减速点的速度
for(i = 1; i &lt; accel_step; i++)
{
ti = 1.0f / velocity_tab_d[0][i - 1]; //减速 总: ti变大-&gt;加速变大,减速变小
if(i &lt; inc_acc_stp) //减加速阶段 ti变大-&gt; 减速表中的速度变大
{
sum_t += ti;//累计的时间
delta_v = 0.5f * jerk * pow(sum_t, 2);
velocity_tab_d[0][i] = g_calc_t[0].vo + delta_v;
if(velocity_tab_d[0][i] &lt;= SPEED_MIN)
{
velocity_tab_d[0][i] = SPEED_MIN;
}
if(i == inc_acc_stp - 1)
{
sum_t = fabs(sum_t - time); //取绝对值,(不能出现负的时间)
}
}
else //减减速阶段 ti变大-&gt; 减速表中的速度变小
{
sum_t += ti;
delta_v = 0.5f * jerk * pow(fabs(time - sum_t), 2);
velocity_tab_d[0][i] = g_calc_t[0].vt - delta_v;
if(velocity_tab_d[0][i] &lt;= SPEED_MIN)
{
velocity_tab_d[0][i] = SPEED_MIN;
}
if(velocity_tab_d[0][i] &gt;= g_calc_t[0].vt)//直到速度接近或达到目标速度g_calc_t[0].vt。
{
accel_step = i;
break;
}
}
}
}
else //加速处理 生成加速过程的速度表 velocity_tab_a
{
is_dec = FALSE;
g_calc_t[0].vo = ROUNDPS_2_STEPPS(vo);
g_calc_t[0].vt = ROUNDPS_2_STEPPS(vt);
time = ACCEL_TIME(time);
vm = (g_calc_t[0].vo + g_calc_t[0].vt) / 2 ;
jerk = fabs(2.0f * (vm - g_calc_t[0].vo) / (time * time));
inc_acc_stp = (int32_t)(g_calc_t[0].vo * time + INCACCELSTEP(jerk, time));
dec_acc_stp = (int32_t)((g_calc_t[0].vt + g_calc_t[0].vo) * time - inc_acc_stp);
accel_step = dec_acc_stp + inc_acc_stp;
//生成加速过程的速度表 velocity_tab_a
if(accel_step % 2 != 0)
{
accel_step += 1;
}
accel_pulse_num[0] = accel_step;
ti_cube = 6.0f * 1.0f / jerk;
ti = pow(ti_cube, (1 / 3.0f));
sum_t = ti;
delta_v = 0.5f * jerk * pow(sum_t, 2);
velocity_tab_a[0][0] = g_calc_t[0].vo + delta_v;
if(velocity_tab_a[0][0] &lt;= SPEED_MIN)
{
velocity_tab_a[0][0] = SPEED_MIN;
}
for(i = 1; i &lt; accel_step; i++)
{
ti = 1.0f / velocity_tab_a[0][i - 1]; //加速
if(i &lt; inc_acc_stp) //加加速阶段 ti变大-&gt; 加速表中的速度变大
{
sum_t += ti;
delta_v = 0.5f * jerk * pow(sum_t, 2);
velocity_tab_a[0][i] = g_calc_t[0].vo + delta_v;
if(velocity_tab_a[0][i] &lt;= SPEED_MIN)
{
velocity_tab_a[0][i] = SPEED_MIN;
}
if(i == inc_acc_stp - 1)
{
sum_t = fabs(sum_t - time);
}
}
else //减加速阶段 ti变大-&gt; 加速表中的速度变小
{
sum_t += ti;
delta_v = 0.5f * jerk * pow(fabs(time - sum_t), 2);
velocity_tab_a[0][i] = g_calc_t[0].vt - delta_v;
if(velocity_tab_a[0][i] &lt;= SPEED_MIN)
{
velocity_tab_a[0][i] = SPEED_MIN;
}
if(velocity_tab_a[0][i] &gt;= g_calc_t[0].vt)
{
accel_step = i;
break;
}
}
}
}
if(is_dec == TRUE)
{
//速度表调整
float tmp_Speed = 0;
/*在减速处理中,如果 is_dec 为真,
则将速度表 velocity_tab_d 的前半部分和后半部分进行反转,
以符合减速过程的特性(即速度从高到低)。*/
for(i = 0; i &lt; (accel_step / 2); i++)
{
tmp_Speed = velocity_tab_d[0][i];
velocity_tab_d[0][i] = velocity_tab_d[0][accel_step - 1 - i];
velocity_tab_d[0][accel_step - 1 - i] = tmp_Speed;
}
//结果存储
g_calc_t[0].decel_tab = velocity_tab_d[0];
g_calc_t[0].decel_step = accel_step;
}
else //不是减速
{
g_calc_t[0].accel_tab = velocity_tab_a[0];
g_calc_t[0].accel_step = accel_step;
}
return TRUE;//函数总是返回 TRUE,表示计算成功。
}</code></pre>
<ol>
<li>水平电机和垂直电机 ---> 共用计算速度1 旋转电机—————> 用计算速度2</li>
</ol>