5 电机
5.1 直流电机
通常有3种驱动方式,书中主要讲了使用达林顿驱动器,如上图ULN2803所示。
每一个io口控制一个电机,通过调节不同占空比的PWM波形来控制电机转速。
-
所述占空比为,高电平持续时间在一个周期时间内的百分比。
-
通过延时控制高低电平时间 或 使用PWM控制器
示例:
// P392节选
void qudong()
{
uchar i;
if(di_num != 0) // 等于0的话,电机满速运转
{
// pwm = 0
for(i = 0; i<di_num; i++) // di_num = 3,低电平时间占3/4
{
dianji = 0; // dianji控制电机的io口
delay();
}
}
// pwm = 1
for ( i = 0; i < gao_num; i++) // gao_num = 1,高电平时间占1/4
{
dianji = 1;
delay();
}
}
void main(){
while(1)
{
dianji = 0; // sbit dianji = P1^7;
qudong();
}
}
5.2 步进电机
5.2.1 工作原理
-
将电脉冲信号转变为角位移或线位移的开环控制元件。
- 电机的转速和停止位置只取决于脉冲信号的频率和脉冲数
-
步进电机的正反转由励磁脉冲产生的顺序来控制;每出现一个脉冲,步进电机只走一步;
假设旋转一圈需要200和脉冲信号来励磁,可以计算出每个励磁信号使步进电机前进1.8°。- 如图所示六线四相步进电机
- 如图所示六线四相步进电机
-
励磁方式
- 一相励磁:在每一瞬间,步进电机只有一个线圈导通;正向励磁顺序为1->2->3->4,4回到1.
- 二相励磁:……,……有两个线圈同时导通;正向励磁顺序为1->2->3->4,4回到1.
- 一-二相励磁:一相励磁和二相励磁交替导通;正向励磁顺序为1->2->3->4->5->6->7->8,8回到1.
5.2.2 六线四相步进电机与单片机连接
1、原理图
2、一相励磁示例代码节选(书P399)
//...
uchar code table1[]={0x01,0x02,0x04,0x08,0x08,0x04,0x02,0x01};
//...
void dispose()
{
switch(num)
{
case 0:
show_num = 2;
maichong = 5; // 利用maichong控制发送给电机脉冲的频率
break;
case 1:
show_num = 4;
maichong = 4;
break;
case 2:
show_num = 6;
maichong = 3;
break;
case 3:
show_num = 8;
maichong = 2;
break;
}
if( flag == 0)
table_begin = 0; // 正转
else
table_begin = 4; //反转
}
/**
* 工作函数
*/
void qudong()
{
uchar i, j;
for(j = 0 + table_begin; j < 4 + table_begin; ++j)
{
P1 = table1[j]; //给一次脉冲
for( i = 0 ; i < maichong; ++i)
{
delay();
}
}
}
void main(){
while(1)
{
key();
dispose();
qudong();
}
}
5.3 舵机(伺服机)
5.3.1 工作原理
-
通过控制pwm的占空比来改变舵机的位置(如图24.3.4所示)。
- 产生基本pwm周期信号
- 调整脉宽
-
单片机控制单个舵机的原理
单片机控制单个舵机比较简单,利用一个定时器即可。假设仅控制舵机5个角度转动其控制思路如下:
只利用一个定时器T0,定时时间为0.5ms;定义一个角度标识(jd,有几次0.5ms),数值可以为1、2、3、4、5,实现 0.5、1、1.5、2、2.5 ms 高电平的输出;再定义一个变量(count,当前第几个0.5ms),数值最大为 40,实现周期为 20ms。
每次进入定时中断,判断此时的角度标识,进行相应的操作。比如,此时为5,则进入前5次中断期间,信号输出为高电平,即为2.5ms的高电平;剩下的35 次中断期间,信号输出为低电平,即17.5ms的低电平。总的时间是 20 ms,为一个周期。
5.3.2 舵机与单片机连接
- 原理图
-
示例代码节选(P407)
// 主要理解jd和count的含义 //... void Time0_init() { TMOD = 0x01; // 定时器0工作在t1方式 IE = 0x82; TH0 = 0xfe; TL0 = 0x33; // 0.5ms TR0=1; } void Time0_int() interrupt 1 { TH0 = 0xfe; TL0 = 0x33; // 0.5ms if(count < jd) // 判断0.5ms的次数是否小于角度标识 pwm = 1; // 确实小于,则继续输出高电平 else pwm = 0; count = (count +1); // 0.5ms次数+1 count = count % 40; // 次数始终保持在40内,即保持周期为20ms } void keyscan() // 按键扫描——人为控制舵机角度加减 { if(jia == 0) // "加"按键按下 { delay(10); if(jia == 0) { jd++; // jd*0.5ms的高电平,控制舵机角度变大 count=0; // 按键按下,则20ms周期重新开始 if(jia == 6) jia = 5; // 已是108°,则保持 while(jia == 0); // 等待按键放开 } } if(jian == 0) { delay(10); if(jian == 0) { jd--; count = 0; if(jd=0) jd =1; while(jian == 0); } } } //... void main() { jd = 1; count = 0; Time0_init(); while(1) { keyscan(); //... } }
-
补充:控制8个舵机(P406第二段)