在HCS08系列MCU上用软件实现仪表步进电机的驱动
时间:11-30
来源:互联网
点击:
分步方式程序
从前面的图5中,可以看到分步方式下的驱动信号是周期性变化的,每个周期对应转子旋转一圈(输出轴旋转2度),其中包含6个分步,分别对应转子的6个平衡位置,我们也可以把它们叫做6个相位。因此,分步驱动方式下MCU的4个I/O口输出的电平也有6种组合,分别对应这6个相位。
在程序中,使用一个静态局部变量bPhase来保存步进电机当前所处的相位,步进电机每走一个分步,相位就加1(逆时针转)或者减1(顺时针转),然后在一个switch…case结构中按新的相位设置I/O口的输出状态,如下:
switch(bPhase)
{
case 0:
STEPPER_LP = 1;
STEPPER_LN = 0;
STEPPER_RP = 1;
STEPPER_RN = 0;
break;
case 1:
STEPPER_LP = 0;
STEPPER_LN = 0;
STEPPER_RP = 1;
STEPPER_RN = 0;
break;
case 2:
STEPPER_LP = 0;
STEPPER_LN = 1;
STEPPER_RP = 0;
STEPPER_RN = 0;
break;
case 3:
STEPPER_LP = 0;
STEPPER_LN = 1;
STEPPER_RP = 0;
STEPPER_RN = 1;
break;
case 4:
STEPPER_LP = 0;
STEPPER_LN = 0;
STEPPER_RP = 0;
STEPPER_RN = 1;
break;
case 5:
STEPPER_LP = 1;
STEPPER_LN = 0;
STEPPER_RP = 0;
STEPPER_RN = 0;
break;
default:
;
}
微步方式程序
从前面的图7中,可以看到微步方式下的驱动信号是近似于正弦波的阶梯电流信号,每个周期对应转子旋转一圈(输出轴旋转2度),当把每个分步细分成4个微步的时候,一个正弦波周期里就有24个阶梯。本文利用PWM来产生这些阶梯电流,并且近似地认为PWM的占空比与平均电流大小成正比。
首先,把TPM1的通道0和1初始化成边沿对齐的PWM工作模式,设置TPM1的工作时钟为总线时钟,预分频系数为1,设置TPM1MOD的值为255,这样当总线时钟频率为16MHz时,所产生的PWM信号的频率是64KHz。在对TPM进行设置的时候需要考虑两个方面:
其一,因为PWM的占空比与平均电流大小成正比,所以要使产生的平均电流尽量接近理想的正弦波分成24个阶梯时的值,就要求PWM占空比的精度比较高。TPM1MOD的值决定了每个PWM周期里有多少个时钟周期,脉冲宽度则由各个通道的Value寄存器的值决定,最小为0(对应占空比为0),最大为(TPM1MOD+1)(对应占空比为100%),设置Value寄存器的值大于(TPM1MOD+1)的效果和设为等于(TPM1MOD+1)是一样的。PWM的占空比其实就是Value寄存器的值(TPM1MOD+1)的比值,由于寄存器里的值只能是整数,所以占空比的精度只能达到1/(TPM1MOD+1)。因此,要使占空比的精度较高,就要给TPM1MOD设置比较大的值。
其二,因为电机的线圈是个感性负载,所以用PWM驱动的时候,线圈上的电流是波浪式变化的,如图11所示。电流的变化导致磁场强度的变化,两个线圈各自产生的磁场强度变化则导致合成磁场的强度和方向都发生变化,这种波浪式的变化将使电机产生振动和噪声。显然,电流波纹的幅度是PWM信号的周期的单调增函数,即PWM的周期越长则电流波纹的幅度越大。因此,PWM的周期应当尽量短,而PWM的周期等于(TPM1MOD+1)乘以TPM1的工作时钟的周期,所以应当使TPM1的工作时钟的频率尽量高,而且TPM1MOD的值不宜设得太大。
设置完PWM的工作时钟频率和模值(TPM1MOD)后,还要计算出各个阶梯电流所对应的占空比,即Value寄存器的值,计算公式如下:
把算出的数值做成查找表放在FLASH存储器中。两个线圈的电流相位相差60度
,而
,因此把由上式计算得到的一组数字的顺序循环移动4个位置就得到另一个线圈的电流对应的查找表。由于PWM的占空比只能控制平均电流的大小,而电流的方向由其他设置决定,所以程序中这两个表的数字都取绝对值,它们的定义如下:
static const word waCosineTable[] =
{
256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246,
256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246
};
static const word waShiftCosTable[] =
{
127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65,
127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65
};
与分步方式程序相似地,本文把这24个阶梯叫做24个相位,用一个静态局部变量bPhase来保存步进电机当前所处的相位,步进电机每走一个微步,相位就加1(逆时针转)或者减1(顺时针转),然后在两个查找表中取出相应的数值写到TPM1的两个通道的Value寄存器中。为了实现电流的方向变化,需要在电流过零对应的相位时改变PWM输出的极性和连接线圈另一极的GPIO口输出的电平,在程序中用switch…case结构来完成这个任务,代码如下:
void MoveStepper1Micro(void)
{
static byte bPhase;
if(bDirection == 1)
{
if(bPhase == 0)
bPhase = 23;
else
bPhase--;
switch(bPhase)
{
case 17:
V
I
t
STEPPER_LN = 1; //设置左线圈负极GPIO口输出高电平,并
TPM1C0SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 21:
STEPPER_RN = 1; //设置右线圈负极GPIO口输出高电平,并
TPM1C1SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 5:
STEPPER_LN = 0; //设置左线圈负极GPIO口输出低电平,并
TPM1C0SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
case 9:
STEPPER_RN = 0; //设置右线圈负极GPIO口输出低电平,并
TPM1C1SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
default:
;
}
wCurrentPosition++;
}
else if(bDirection == 0xFF)
{
if(bPhase == 23)
bPhase = 0;
else
bPhase++;
switch(bPhase)
{
case 6:
STEPPER_LN = 1; //设置左线圈负极GPIO口输出高电平,并
TPM1C0SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 10:
STEPPER_RN = 1; //设置右线圈负极GPIO口输出高电平,并
TPM1C1SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 18:
STEPPER_LN = 0; //设置左线圈负极GPIO口输出低电平,并
TPM1C0SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
case 22:
STEPPER_RN = 0; //设置右线圈负极GPIO口输出低电平,并
TPM1C1SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
default:
;
}
wCurrentPosition--;
}
TPM1C0V = waCosineTable[bPhase];
TPM1C1V = waShiftCosTable[bPhase];
}
从前面的图5中,可以看到分步方式下的驱动信号是周期性变化的,每个周期对应转子旋转一圈(输出轴旋转2度),其中包含6个分步,分别对应转子的6个平衡位置,我们也可以把它们叫做6个相位。因此,分步驱动方式下MCU的4个I/O口输出的电平也有6种组合,分别对应这6个相位。
在程序中,使用一个静态局部变量bPhase来保存步进电机当前所处的相位,步进电机每走一个分步,相位就加1(逆时针转)或者减1(顺时针转),然后在一个switch…case结构中按新的相位设置I/O口的输出状态,如下:
switch(bPhase)
{
case 0:
STEPPER_LP = 1;
STEPPER_LN = 0;
STEPPER_RP = 1;
STEPPER_RN = 0;
break;
case 1:
STEPPER_LP = 0;
STEPPER_LN = 0;
STEPPER_RP = 1;
STEPPER_RN = 0;
break;
case 2:
STEPPER_LP = 0;
STEPPER_LN = 1;
STEPPER_RP = 0;
STEPPER_RN = 0;
break;
case 3:
STEPPER_LP = 0;
STEPPER_LN = 1;
STEPPER_RP = 0;
STEPPER_RN = 1;
break;
case 4:
STEPPER_LP = 0;
STEPPER_LN = 0;
STEPPER_RP = 0;
STEPPER_RN = 1;
break;
case 5:
STEPPER_LP = 1;
STEPPER_LN = 0;
STEPPER_RP = 0;
STEPPER_RN = 0;
break;
default:
;
}
微步方式程序
从前面的图7中,可以看到微步方式下的驱动信号是近似于正弦波的阶梯电流信号,每个周期对应转子旋转一圈(输出轴旋转2度),当把每个分步细分成4个微步的时候,一个正弦波周期里就有24个阶梯。本文利用PWM来产生这些阶梯电流,并且近似地认为PWM的占空比与平均电流大小成正比。
首先,把TPM1的通道0和1初始化成边沿对齐的PWM工作模式,设置TPM1的工作时钟为总线时钟,预分频系数为1,设置TPM1MOD的值为255,这样当总线时钟频率为16MHz时,所产生的PWM信号的频率是64KHz。在对TPM进行设置的时候需要考虑两个方面:
其一,因为PWM的占空比与平均电流大小成正比,所以要使产生的平均电流尽量接近理想的正弦波分成24个阶梯时的值,就要求PWM占空比的精度比较高。TPM1MOD的值决定了每个PWM周期里有多少个时钟周期,脉冲宽度则由各个通道的Value寄存器的值决定,最小为0(对应占空比为0),最大为(TPM1MOD+1)(对应占空比为100%),设置Value寄存器的值大于(TPM1MOD+1)的效果和设为等于(TPM1MOD+1)是一样的。PWM的占空比其实就是Value寄存器的值(TPM1MOD+1)的比值,由于寄存器里的值只能是整数,所以占空比的精度只能达到1/(TPM1MOD+1)。因此,要使占空比的精度较高,就要给TPM1MOD设置比较大的值。
其二,因为电机的线圈是个感性负载,所以用PWM驱动的时候,线圈上的电流是波浪式变化的,如图11所示。电流的变化导致磁场强度的变化,两个线圈各自产生的磁场强度变化则导致合成磁场的强度和方向都发生变化,这种波浪式的变化将使电机产生振动和噪声。显然,电流波纹的幅度是PWM信号的周期的单调增函数,即PWM的周期越长则电流波纹的幅度越大。因此,PWM的周期应当尽量短,而PWM的周期等于(TPM1MOD+1)乘以TPM1的工作时钟的周期,所以应当使TPM1的工作时钟的频率尽量高,而且TPM1MOD的值不宜设得太大。
设置完PWM的工作时钟频率和模值(TPM1MOD)后,还要计算出各个阶梯电流所对应的占空比,即Value寄存器的值,计算公式如下:
把算出的数值做成查找表放在FLASH存储器中。两个线圈的电流相位相差60度
,而
,因此把由上式计算得到的一组数字的顺序循环移动4个位置就得到另一个线圈的电流对应的查找表。由于PWM的占空比只能控制平均电流的大小,而电流的方向由其他设置决定,所以程序中这两个表的数字都取绝对值,它们的定义如下:
static const word waCosineTable[] =
{
256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246,
256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246
};
static const word waShiftCosTable[] =
{
127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65,
127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65
};
与分步方式程序相似地,本文把这24个阶梯叫做24个相位,用一个静态局部变量bPhase来保存步进电机当前所处的相位,步进电机每走一个微步,相位就加1(逆时针转)或者减1(顺时针转),然后在两个查找表中取出相应的数值写到TPM1的两个通道的Value寄存器中。为了实现电流的方向变化,需要在电流过零对应的相位时改变PWM输出的极性和连接线圈另一极的GPIO口输出的电平,在程序中用switch…case结构来完成这个任务,代码如下:
void MoveStepper1Micro(void)
{
static byte bPhase;
if(bDirection == 1)
{
if(bPhase == 0)
bPhase = 23;
else
bPhase--;
switch(bPhase)
{
case 17:
V
I
t
STEPPER_LN = 1; //设置左线圈负极GPIO口输出高电平,并
TPM1C0SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 21:
STEPPER_RN = 1; //设置右线圈负极GPIO口输出高电平,并
TPM1C1SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 5:
STEPPER_LN = 0; //设置左线圈负极GPIO口输出低电平,并
TPM1C0SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
case 9:
STEPPER_RN = 0; //设置右线圈负极GPIO口输出低电平,并
TPM1C1SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
default:
;
}
wCurrentPosition++;
}
else if(bDirection == 0xFF)
{
if(bPhase == 23)
bPhase = 0;
else
bPhase++;
switch(bPhase)
{
case 6:
STEPPER_LN = 1; //设置左线圈负极GPIO口输出高电平,并
TPM1C0SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 10:
STEPPER_RN = 1; //设置右线圈负极GPIO口输出高电平,并
TPM1C1SC = 0x24; //设置PWM极性为低有效,使电流方向为负
break;
case 18:
STEPPER_LN = 0; //设置左线圈负极GPIO口输出低电平,并
TPM1C0SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
case 22:
STEPPER_RN = 0; //设置右线圈负极GPIO口输出低电平,并
TPM1C1SC = 0x28; //设置PWM极性为高有效,使电流方向为正
break;
default:
;
}
wCurrentPosition--;
}
TPM1C0V = waCosineTable[bPhase];
TPM1C1V = waShiftCosTable[bPhase];
}
步进电机 电路 MCU Freescale 电流 电压 PWM 电阻 传感器 ADC 电感 总线 相关文章:
- 单芯片集成电路优化自适应转向大灯系统设计(07-03)
- 汽车仪表步进电机控制算法的仿真(02-15)
- 灵活的现代CPLD汽车数字仪表板(06-04)
- 基于步进电机控制技术的汽车辅助照明随动系统设计(01-25)
- 基于步进电机驱动器MC33991的车速表设计(11-14)
- 基于CAN总线的一体化步进电机驱动器的设计与实现(11-25)