前面几节主要介绍了如何使用C语言编程控制声光器件,本节再来说一点机械方面的经典器件——电机。然后我们在使用C语言编程单片机,制作一个“向日葵”,如下图:
[video width="544" height="960" mp4="https://www.xrkzn.cn/wp-content/uploads/2018/08/寻光器.mp4"][/video]
能够看出,电机会控制箭头始终指向光线最强的方向。
步进电机
电机的分类方式有很多,按照用途总体可分为两大类:以直流电机为代表的驱动类电机,和以步进电机为代表的控制类电机。驱动类电机主要应用在电钻、风扇、小车轮子等设备上,而控制类电机则主要用在自动化仪表、智能机器、空调扇叶转动等设备上。
那显然,我们制作“向日葵”的目标时,选择使用控制类电机是非常合适的。这里我选用的是 28BYJ-48 步进电机,如下图:
根据使用手册,步进电机 28BYJ-48 中的 28 表示步进电机的最大外径是 28 mm,B 表示是步进电机,Y表示是永磁式,J 表示电机是减速型的,48 表示电机是四相八拍的。
28BYJ-48 步进电机的工作原理
其实“48(四相八拍)”就是用于说明如何驱动这款步进电机的,先来看看它的内部原理图:
步进电机的内圈(转子,顾名思义,它与转动轴相连,负责电机转动)有 6 个齿,每个齿上都是永磁体(Y),带有永久的磁性。步进电机的外圈(定子,保持不动)与外壳相连,它有 8 个齿,每个齿上都绕制了线圈,正对着的两个线圈是串联在一起的,所以它们同时导通或者关闭,这就形成了所谓的“四相”。
定子上的线圈导通时,因为电磁感应,就会产生磁力,吸引靠其最近的转子齿。如果交替导通 4 对线圈,则步进电机就转动起来了。按照上图中的步进电机内外圈相对位置,完成一个 B-C-D-A 四节拍后,转子将转过一个定子齿的角度,依此类推,当完成 8个这样的“四节拍”后,电机就恰好转过一圈。
这样一来,显然一个节拍能够驱动步进电机转动 360/(8* 4)=11.25度。那么,有没有更加精细的控制方法呢?当然是有的,可以在每个节拍之间在加上一个节拍,形成 B-BC-C-CD-D-DA-A-AB 八节拍的控制方式,这样一个节拍能够驱动电机转动 5.626 度,控制就更精细了。
C语言编程51单片机,控制步进电机旋转
为了制作“向日葵”,应使用C语言编程51单片机,驱动步进电机实现正向旋转和反向旋转的功能,那么怎么实现呢?先来看看如何连线。
28BYJ-48 步进电机有 5 根控制线,其中一根线接 5V 驱动电源,另外 4 根就分别是 A、B、C、D 四个相了,可以使用单片机的 4 个 IO 口分别控制,这样一来,若想控制 A 相导通,只需编写C语言代码控制 A 相为低就可以了。8 个节拍的控制顺序如下:
考虑到51单片机的IO口电流驱动能力比较弱,所以按照第二节介绍的方法,使用三极管间接控制步进电机了,控制电路如下图:
这里将 A、B、C、D 依次连接到 P0 口的低 4 位了,所以若想导通 A 相,P0 的低 4 位应该是 0b1110,也就是 0xE,依此类推,其他几相应该是:
unsigned char code beatCode[8] = {0xe,0xc,0xd,0x9,0xb,0x3,0x7,0x6};
若想驱动电机转动,依次给 P0 赋值 beatCode[i] 就可以了。那么,多久赋值一次呢?再来看 28BYJ-48 步进电机的使用手册:
请注意 P.P.S 这个参数(pulses per second, 每秒脉冲数),也即 1 秒可以赋值 550 次,相当于一次赋值要维持 1/550 约为 1.8 ms。这样一来,控制步进电机转动的C语言程序可以这么写:
char motorIndex = 0;
void Delay2ms(unsigned int cnt)
{
unsigned int i = 2000;
while(cnt--)
while(i--);
}
void MotorTurn(unsigned int rounds)
{
while(rounds--){
P0 = beatCode[motorIndex];
motorIndex ++;
motorIndex = motorIndex&0x07;
Delay2ms(1);
}
}
MotorTurn() 函数就可以控制步进电机转动。代码很简单,就是依次向 P0 口赋值 beatCode 即可,因为 beatCode 只有 8 个元素,所以有 motorIndex = motorIndex&0x07; 这么一句。
假设上面的C语言代码是控制步进电机“正向旋转”的,那么我们还需要能够控制电机“反向旋转”的C语言程序,该怎么写呢?其实只要反向将 beatCode 赋值给 P0 就可以了,请看:
void MotorTurnBack(unsigned int rounds) // 反转
{
while(rounds--){
P0 = beatCode[motorIndex];
if(motorIndex > 0)
motorIndex --;
else
motorIndex = 7;
Delay2ms(1);
}
}
MotorTurnBack() 函数可以控制步进电机“反向转动”。现在用C语言编写 main 函数,控制电机正向转动一会,再反向转动一会,代码如下,请看:
void main()
{
while(1){
MotorTurn(1000);
MotorTurnBack(1000);
}
}
代码很简单,现在编译C语言程序,烧写到单片机,就能发现一切与预期一致。
制作“向日葵”
到这里,我们就完成了使用C语言编程单片机,控制步进电机正向和反向旋转的功能。再结合之前介绍的光敏电阻,就能实现文章开头的“向日葵”功能了,限于篇幅,下一节再说了。