提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
步进电机一般由前后端盖、轴承、中心轴、转子铁芯、定子铁芯、定子组件、波纹垫圈、螺钉等部分组成,与直流电机不同的是,步进电机内部有很多线圈在定子上用来产生磁场,中间是一个永磁体,会随着外部线圈磁场的不断变化持续转动。
步进电机的“相”表明步进电机有几个线圈,也称为绕组;“极性”则分为单极性和双极性这两种。区别单极性与双极性主要是看线圈能不能双向导电,即电流是否既能从线圈某个端口进入或者出来。下图分别是两相四线双极性和两相五线单极性步进电机。
前文提到过步进电机的转子是一个永磁铁,我们需要控制定子的磁场变化才能使步进电机转动。步进电机的驱动方式主要分为全步、半步、微步。
全步驱动
半步驱动
从图中可以看出全步驱动电流改变了四次(即一个小循环为四拍),半步驱动电流改变了八次(即一个小循环为八拍)。
在没有使用驱动芯片的前提下,我使用的是全步工作方式。观察电流时序会发现使用全步工作时,A相和B相是分别互补的两路互补的PWM波,且A相和B相相位相差90°,这里使用的是STM32F4单片机高级定时器的互补输出功能,可以得到两路互补的PWM波。
示波器测得A+、A-波形
示波器测得A+、B-波形
微步驱动
改变电流的大小,可以改变线圈产生的磁场强度,不同线圈的磁场强度不一样,转子的平衡位置就会发生改变,这就是微步驱动的原理。
使用加减速控制步进电机得目的主要是为了防止步进电机的频率过快而无法正常启动,避免控制脉冲频率变化太大造成电机丢步或过冲。
梯形加减速的目的就是电机在加减速之后仍然能够达到目标位置。梯形加速度的速度加速度曲线如下图所示。
对于步进电机速度的改变是接收脉冲的频率,接收脉冲频率越快步进电机的速度就越快,不过这个频率也有上限和下限(太快不能正常启动容易堵转或丢步)。这里产生不同频率的PWM波主要使用的是STM32F4定时器的比较输出功能,通过下文提到的算法不断改变输出脉冲的频率从而达到梯形加减速的效果。对于代码的实现,加速度减速度以及希望运动的步数由开发者设定。
考虑步进电机每一步收到的脉冲频率不一样,t0到t1为第一个脉冲间隔时间,t1到t2为第二个脉冲时间,假设定时器计数周期为tt,改变每次定时器计数器的计数个数就能得到不同的时间和脉冲输出时间相匹配。
其中α为步进电机步距角,Cn为不同步数所对应的计数个数,通过位移公式可以知道每一个脉冲相对应的时间关系,进而求出Cn与C0的关系。
n1为加速度需要的脉冲数,n2为减速度需要的脉冲数ω’1:加速度
ω’2:减速度,简单处理后可以得到加速度步数,减速度步数与总步数之间的关系。n1 * ω’1=n2 * ω’2为了方便后面计算,等式左右两边加上n1 * ω’2,得到n1 * ω’1+n1 * ω’2=n2 * ω’2+n1 * ω’2
最终得到n1=(n1+n2)*ω’2/(ω’1+ω’2)。在限定步数的情况下,存在能够在有限步数加速到指定速度,以及有限速度不能加速到指定速度的情况。
max_s_lim:达到设定最大速度需要的脉冲数
根据公式n1=(n1+n2)*ω’2/(ω’1+ω’2)可以得到accle_lim=(step *decle)/(accel+decel)
根据公式n *ω’=ω’n/2 *α可以得到max_s_lim=n=speed *speed/(2 *α *accel)
从数学角度将模型的两种情况分为了accle_lim>max_s_lim的和accle_lim
decel_val=(max_s_lim *accel)/decel
2.accle_lim
相比梯形加减速,S型加减速在速度开始以及到达目标速度的时候更加稳定(由于该时刻速度变化量比较小)。同时S型加减速也有加加速(加速度增大的加速运动)、加减速(加速度减小的加速运动)、匀速运动、减加速(加速度增大的加速运动)、减减速(加速度减小的减速运动)五个状态。对于S型加速在某些方面与梯形加速度有着相同的地方,同样是计算每一步对应的脉冲时间间隔。不同的是S型加减速它的加速度随时间变化,其中S型加减速的速度曲线和加速度曲线如下图所示。
对于S型加减速,加速度呈线性变化,所以不方便设定加速度。方便整个过程的实现,人为设定的已知量为总步数、目标速度、加速时间、减速时间。上文提到S型速度曲线为五段过程,1、2(加加速,加减速)与4、5(减加速,减减速)是相反的两个过程,所以整个S型加速考虑前面两个阶段即可。对于加加速和加减速过程,中间速度正好是T/2的时候(T为设定的加速时间),有以下公式
k为加速度变化率,T/2加速时间的速度已知,s为加加速阶段的总位移,知道加加速阶段位移(即加加速阶段步数)可以计算出每一步的时间,根据V=V0+1/2at²可以求得每一步对应的速度。对于加减速阶段
T为设定的总加速时间,accelstep为上文求得的加加速阶段的步数,SumT为累积总时间,通过以上两个公式,我们就可以求得加减速阶段每一步所对应的速度。将加加速阶段和加减速阶段每一步的速度存放进一个数组,即可得到加速阶段的速度表,那么将它倒序排列就是减速阶段的速度表,整个S型加减速除了匀速阶段其他时刻每一步对应的速度我们就可以知道。
S形加减速和梯型加减速一样,会存在设定步数不够达到目标速度的情况(即没有匀速运动的阶段)。
和梯形加减速类似,通过给定加速时间以及目标速度,会计算达到目标速度加上完成整个S型加减速过程需要多少步(即为VT,V为目标速度,T为加速时间),若小于设定步数,则有匀速的阶段,若大于设定步数,则需要计算设定步数完成整个S型加减速过程所能达到的最大速度,即(step/2=V0/2·T,step为设定步数,T为加速时间,可求得能达到最大速度V0,这里设置加速时间和减速时间一样)。
if(htim->Instance==TIM8)
{
tim_count = __HAL_TIM_GET_COUNTER(&g_atimx_handle);
tmp = tim_count+g_srd.step_delay/2; /* 整个C值里边是需要翻转两次的所以需要除以2 */
__HAL_TIM_SET_COMPARE(&g_atimx_handle,ATIM_TIMX_PWM_CH1,tmp);
i++; /* 定时器中断次数计数值 */
if(i == 2) /* 2次,说明已经输出一个完整脉冲 */
{
i = 0; /* 清零定时器中断次数计数值 */
switch(g_srd.run_state) /* 加减速曲线阶段 */
{
case STOP:
step_count = 0; /* 清零步数计数器 */
rest = 0; /* 清零余值 */
/* 关闭通道*/
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
ST3_EN(EN_OFF);
g_motion_sta = 0; /* 电机为停止状态 */
break;
case ACCEL:
g_add_pulse_count++; /* 只用于记录相对位置转动了多少度 */
step_count++; /* 步数加1*/
if(g_srd.dir == CW)
{
g_step_position++; /* 绝对位置加1 记录绝对位置转动多少度*/
}
else
{
g_step_position--; /* 绝对位置减1*/
}
g_srd.accel_count++; /* 加速计数值加1*/
new_step_delay = g_srd.step_delay - (((2 *g_srd.step_delay) + rest)/(4 * g_srd.accel_count + 1));/* 计算新(下)一步脉冲周期(时间间隔) */
rest = ((2 * g_srd.step_delay)+rest)%(4 * g_srd.accel_count + 1); /* 计算余数,下次计算补上余数,减少误差 */
if(step_count >= g_srd.decel_start) /* 检查是否到了需要减速的步数 */
{
g_srd.accel_count = g_srd.decel_val; /* 加速计数值为减速阶段计数值的初始值 */
g_srd.run_state = DECEL; /* 下个脉冲进入减速阶段 */
}
else if(new_step_delay <= g_srd.min_delay) /* 检查是否到达期望的最大速度 计数值越小速度越快,当你的速度和最大速度相等或更快就进入匀速*/
{
last_accel_delay = new_step_delay; /* 保存加速过程中最后一次延时(脉冲周期)*/
new_step_delay = g_srd.min_delay; /* 使用min_delay(对应最大速度speed)*/
rest = 0; /* 清零余值 */
g_srd.run_state = RUN; /* 设置为匀速运行状态 */
}
break;
case RUN:
g_add_pulse_count++;
step_count++; /* 步数加1 */
if(g_srd.dir == CW)
{
g_step_position++; /* 绝对位置加1 */
}
else
{
g_step_position--; /* 绝对位置减1*/
}
new_step_delay = g_srd.min_delay; /* 使用min_delay(对应最大速度speed)*/
if(step_count >= g_srd.decel_start) /* 需要开始减速 */
{
g_srd.accel_count = g_srd.decel_val; /* 减速步数做为加速计数值 */
new_step_delay = last_accel_delay; /* 加阶段最后的延时做为减速阶段的起始延时(脉冲周期) */
g_srd.run_state = DECEL; /* 状态改变为减速 */
}
break;
case DECEL:
step_count++; /* 步数加1 */
g_add_pulse_count++;
if(g_srd.dir == CW)
{
g_step_position++; /* 绝对位置加1 */
}
else
{
g_step_position--; /* 绝对位置减1 */
}
g_srd.accel_count++;
new_step_delay = g_srd.step_delay - (((2 * g_srd.step_delay) + rest)/(4 * g_srd.accel_count + 1)); /* 计算新(下)一步脉冲周期(时间间隔) */
rest = ((2 * g_srd.step_delay)+rest)%(4 * g_srd.accel_count + 1); /* 计算余数,下次计算补上余数,减少误差 */
/* 检查是否为最后一步 */
if(g_srd.accel_count >= 0) /* 判断减速步数是否从负值加到0是的话 减速完成 */
{
g_srd.run_state = STOP;
}
break;
}
g_srd.step_delay = new_step_delay; /* 为下个(新的)延时(脉冲周期)赋值 */
}
}
波形的获取主要是通过采集引脚波形以及通过编码器测量采集得到的,所使用的编码器为EB62-CWZ6C为步进电机编码器,旋转一圈能产生200个脉冲,通过单片机的编码器模式能获取脉冲信号从而获得步进电机得位置信号,采集得到的数据如下图所示。
梯形加减速输出波形
上位机实测梯形速度曲线
上位机实测S型速度曲线
本例主要是介绍了步进电机加减速的相关理论知识,包括步进电机的驱动方式以及梯形加减速、S型加减速控制算法的实现,学习的同时对于单片机高级定时器的比较输出功能、互补输出功能有了进一步的学习,在理解步进电机的工作原理的同时对定时器的一些功能也有了进一步的学习。最后的上位机速度曲线是通过编码器测得的,可以看到梯形速度曲线与S型速度曲线基本符合理论。整个加减速理论学起来其实并不复杂,但是将算法理论转化为单片机程序最后再逐步修改是花费了一定的时间,对于单片机定时器的一些功能以前知道的不多,现在慢慢学习才有了更输入的认识。
完成整个步进电机的梯形加减速,主要在难度在代码这一块。虽然拿到了相关历程,但是对于一些配置还不算熟悉,特别是我使用STM32CUBEMX配置相关代码,不太理解一些相关配置,这就导致有些例程代码引脚配置不一样需要去修改引脚才能使用,是慢慢摸索出来如何使用这些东西的,所以也花费了一些时间去完成相关代码的小修改。
后面测相关数据波形的时候,需要用到串口、定时器、中断等功能,开始采集到的数据一直都不甚理想,出现了在低速状态电机无法运动出现剧烈抖动的情况(即电机无法完成单步运动),在最先测试的时候电机是能完成单步测试的,在导师的提醒下才发现不能单步运行,最后才想到检查芯片的问题,可能在某次实验中,步进电机停止工作但任长时间给予外界电压,导致芯片长时间带大电流,可能芯片也因此烧坏了,出现了在低频率脉冲信号往返抖动的问题(即方向引脚已经失效),这导致上位机数据一直有问题(因为步进电机一直行进有问题)。