步进电机的基本步距角:对F相的步进电机有F个绕组(就是定子中包含的绕组个数),它们被均匀的镶嵌在定子上。 步进电机各相轮流接入整步电流后所产生的步距角叫做该步进电机的基本步距角。也就是说相序产生一轮后步进电机并不会转1转。
那么转子转一圈的步数(也就是需要几组时序)是多少呢?
公式 A=360/M(A为基本步距角,M为步数)。
根据公式,基本步距角是不能随意取值的。我们往往希望步进电机转一圈为 100 步或其倍数,这在 2/4 相和 5 相步进电机容易做到,但对于三相步进电机其基本步距角不可能做到转一圈为 100 步或 200 步,但可以是 300 步。 有些厂家所标的三相步进电机的步距角为 1.2 度或 3 度,相当每圈 300 步或 120 步,是 3 的整数倍,这种标注很正常。
什么是细分呢?所谓细分,就是驱动器在接到控制发来的每一个脉冲时,只给电机发几分之一个脉冲(用“脉冲”这个词不准确,实际是正弦波一个周期的几分之一)。
我们用297芯片写过步进电机的驱动,其中CW/CWW引脚还记得吗?这个引脚有什么作用呢,当我将他设置为1时,我每输入一个脉冲,其输出产生一组相序,也就是1个步距。同理,当其设置为0时,它只产生一半的相序。
如何找出步进电机的基本步距呢,当然我是看说明书的(哈哈)。如果没有说明书的话可以试试如下的方法:
①用数字万用表找到公共线。其他引线与 公共线之间的电阻测量值都相同。
将此线连接到电池的V+。5V或6V就足够测试用了。
②胶带粘贴到步进电机的输出铀上,并使它垂直于轴端伸出成为一个标志。此标志的作用在于判断电机是否转动。
③任意挑出一条引线称之为相1。若将此线接地,则电机输出轴将做轻微的转动。现在步进电机被锁定在相1的位置上。
④取另一根引线并将其接地,仔细观察输出轴上的胶带。如果输出轴向右轻微地旋转,那么此根引线是相2。 ⑤取另一根线并将其接地,仔细观察输出轴上的胶带。如果输出轴向左轻微地旋转,那么此根引线是相4。如图4所示。
⑥再取另一根线并将其接地,仔细观察输出轴上胶带的运动状态。如果输出轴不旋转,那么此根引线就是相3。
确定相位之后,找一个参照相,然后挨个给一个脉冲,看看走了多少度。
四相六根和八根线的,如何使用两相四线驱动器?问题解决:1 和2为一相,分别接A和/A;3和4为一相,分别接B和/B。不过在你有了一个步进电机驱动芯片后完全不用考虑这些小问题,只需一个命令搞定。
HF=0;
IN1=0;
IN2=1;
为何要给步进电机设计一个恼人的加速减速程序呢,根据步进电机的原理来看,当其某一相进行运转时,不是及时就停住了吗,那我要加速函数有何意义?我可以直接设置终值,尽管可能因为惯性是的我的电机最终到达稳定时的时间长一些,可是我确确实实可以这样做啊。
事实上,由于步进电机是要悬挂负载的,因此我不能单单只是考虑步进电机自身的问题,我还要考虑在这个高低点平上的突变问题(有兴趣的小伙伴可以画一画波形图)。在这个突变的间隔内是不是会猛然加重步进电机的负担。那么什么样的变化过程是最好的呢当然是正弦函数,可惜我们只能用线性变化来代替正弦变化。(谁叫我们用的是数电呢)
了解了步进电机的一些工作原理,下面我们来分装步进电机的函数:
/****************
函数名称 : forward()
函数功能 :使步进电机正转一定的圈数
传入参数 :正转的圈数和频率
返回值 : 无
说明: 每过一定的周期给一次脉冲
*****************/
void forward(uchar sum;uchar T){
while(sum!=0){
if(time >= T){
clk = 1;
delay (延时一定的时间,根据实际测量得出)
clk = 0;
sum--;
time = 0;
}
}
}
在上述函数中,time是一个通过Timer0_isr interrupt 1进行计数的变量这个脉冲的频率与T有关,行进的圈数与sum有关,频率与T有关。
这个函数存在以下的问题:
1 sum是一个步数,而不是圈数,这对于人机交互来说并不理想
2 T是时间量,而非频率量,电机的快慢和其成反比
3 对于一个从中断器获得的变量time来说,我并不信任它,因为他完全可能超过我执行这个函数时的设定值
首先我来解决3的问题,因为这个问题十分严重:
现在我提出一个方案:将这个函数整个放到Timer0_isr()里面,那么我就需要时刻对这个中断进行改变,已完成不同的命令,甚至是终止。经过框图的推演:将条件加载time判断的里面比较好。
void Timer0_isr() interrupt 1 {
static unsigned char time;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
if(time==circle){
if(num!=0){
num--;
clk = ~clk;
if (num%M==0) r--;
}
time = 0;
}
}
该函数初步具备了控制步进电机的步数和速度的要求。
然后我们返回自己的要求:
1 控制电机的正反转
2 实现电机的加速减速
现在我越来越觉得自己做了一个超级英明的决定,我将clk放入中断中,而这个中断可以改变的参数真是超级的多。
下面我们返回到main中实现我们的第一个要求:
unsigned int num = 0;
en = 1;
hf = 1;
cw = 1;
num = r*M; //M是我们测得的步进电机的步数/圈
circle = f;
通过这些改变我将获得一个可以转r圈的num,当然我把它打包成函数
/****************
函数名称 : forward()
函数功能 :使步进电机正转一定的圈数
传入参数 :正转的圈数和频率
返回值 : 无
说明:
*****************/
void forward(uint r;uint f){
en = 1;
hf = 1;
cw = 1;
num = r*M;
circle = f;
}
/****************
函数名称 : backward()
函数功能 :使步进电机正转一定的圈数
传入参数 :正转的圈数和频率
返回值 : 无
说明:
*****************/
void backward(uint r;uint f){
en = 1;
hf = 1;
cw = 0;
num = r*M;
circle = f;
}
之后我们来实现加速和减速的功能,刚刚我们利用了num参数,可是我的中断可是很神奇的,我还有一个circle,哈哈,体会到这样做的好处了吧
首先我给电机提供一个num,使电机转动。
en = 1;
hf = 1;
cw = 1;
num = r*M;
circle = f0;
下面是对circle的的控制,在这里,我想让circle和num联系起来,于是在我的中断里多了这样一句 if (num%M==0) r--;
while(r!=0){
if (circle!=f)
circle --;
}
//f是我要变到的速度 ,现在我把它打包一下
/****************
函数名称 : speedup()
函数功能 :使步进电机在一定的圈数内加速到某频率
传入参数 :正转的圈数,初频率和末频率
返回值 : 无
说明:
*****************/
void speedup(uint r;uint f0;uint f){
en = 1;
hf = 1;
cw = 1;
num = r*M;
circle = f0;
while(r!=0){
if (circle!=f) circle --;
}
}
/****************
函数名称 : speeddowm()
函数功能 :使步进电机在一定的圈数内减速到某频率
传入参数 :正转的圈数,初频率和末频率
返回值 : 无
说明:
*****************/
void speeddown(uint r;uint f0;uint f){
en = 1;
hf = 1;
cw = 1;
num = r*M;
circle = f0;
while(r!=0){
if (circle!=f) circle ++;
}
}
好了,打包程序到此结束了,主程序就交给你们了。