目录
橙色
直流电机实验
在未学习 PWM 之前, 我们先简单使用 GPIO 来控制电机的旋转和停止。 不能直接使用 GPIO 来驱动电机, 而需要相应的驱动芯片来驱动电机, 开发板板载了一个 ULN2003 驱动芯片
, 该芯片是一个单片高电压、 高电流的达林顿晶体管阵列集成电路。 不仅可以用来驱动我们的直流电机
, 还可用来驱动五线四相步进电机, 比如 28BYJ-48 步进电机。 本章使用的是 ULN2003 芯片来驱动, 本章所要实现的功能是: 直流电机工作约 5S 后停止。
直流电机介绍
直流电机是指能将直流电能转换成机械能(直流电动机) 或将机械能转换成直流电能(直流发电机) 的旋转电机。 它是能实现直流电能和机械能互相转换的电机。 当它作电动机运行时是直流电动机, 将电能转换为机械能; 作发电机运行时是直流发电机, 将机械能转换为电能。
直流电机没有正负之分, 在两端加上直流电就能工作。 需要知道直流电机的额定电压和额定功率, 不能使之长时间超负荷运作。 在交换接线后, 可以形成正反转。
开发板配置的直流电机为 5V 直流电机, 其主要参数如下:
- 轴长: 8mm
- 轴径: 2mm
- 电压: 1-6V
- 参考电流: 0.35-0.4A
- 3V 转速: 17000-18000 转每分钟
外观实物图如下:
ULN2003 芯片介绍
51 单片机主要是用来控制而非驱动, 如果直接使用芯片的 GPIO管脚去驱动大功率器件, 要么将芯片烧坏, 要么就驱动不起来。 所以要驱动大功率器件, 比如电机。 就必须搭建驱动电路, 开发板上板载的驱动芯片是 ULN2003,该芯片是一个单片高电压、 高电流的达林顿晶体管阵列集成电路。 不仅可以用来驱动直流电机, 还可用来驱动五线四相步进电机, 比如 28BYJ-48 步进电机。 本章我们使用 ULN2003 来驱动直流电机, 下面来具体介绍下 ULN2003 芯片的使用。
ULN2003 是一个单片高电压、 高电流的达林顿晶体管阵列集成电路。它是由7 对 NPN 达林顿管组成的, 它的高电压输出特性和阴极箝位二极管可以转换感应负载。 单个达林顿对的集电极电流是 500mA。 达林顿管并联可以承受更大的电流。此电路主要应用于继电器驱动器, 字锤驱动器, 灯驱动器, 显示驱动器(LED 气体放电) , 线路驱动器和逻辑缓冲器。ULN2003 的每对达林顿管都有一个 2.7k串联电阻, 可以直接和 TTL 或 5V CMOS 装置。
(1)主要特点
①500mA 额定集电极电流(单个输出)
②高电压输出: 50V
③输入和各种逻辑类型兼容
④继电器驱动器
(2) 逻辑框图
从上图可以很容易理解该芯片的使用方法, 其内部相当于非门电路, 即输入高输出为低, 输入为低输出是高, 这里要注意: 因为 ULN2003 的输出是集电极开路, ULN2003 要输出高电平, 必须在输出口外接上拉电阻。 这也就能解释在后面连接直流电机时为什么不能直接将 ULN2003 的 2 个输出口接电机线, 而必须一根线接电源,另一个才接 ULN2003 输出口。
若使用该芯片驱动直流电机, 只可实现单方向控制, 电机一端接电源正极,另一端接芯片的输出口。 若想控制五线四相步进电机, 则可将四路输出接到步进电机的四相上, 电机另一条线接电源正。
硬件设计
本实验使用到硬件资源如下:
(1) 步进电机驱动模块
(2) 直流电机
开发板上的步进电机驱动模块电路如下图所示:
从上图可知, ULN2003 的输入口与单片机的 P1.0-P1.3 连接, 对应输出则是OUT1-OUT4, 而 J47 则是提供给外部连接电机的接口, 可以支持直流电机、 五线四相步进电机 28BYJ-48 连接。 本实验使用的是直流电机, 电机的一根线连接在VCC 上, 另一根连接在 OUT1 上, 因此可通过单片机 P1.0 口输出高电平来控制电机旋转, 输出低电源控制电机停止。 注意: 单片机 P1.0 输出低电平时, ULN2003的 OUT1 并不会输出高电平导致停止, 而是因为集电极开路, 导致电机无电流流入致使停止。
软件设计
本实验所要实现的功能是: 直流电机工作约 5S 后停止。
c
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义直流电机控制管脚
sbit DC_Motor=P1^0;
#define DC_MOTOR_RUN_TIME 5000 //定义直流电机运行时间为5000ms
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{
DC_Motor=1;//开启电机
delay_ms(DC_MOTOR_RUN_TIME);
DC_Motor=0;//关闭电机
while(1)
{
}
}
实验现象
线怎么接都行,程序中用的是01端口,所以注意直流电机的两根线要连接在 J47 端子的 01 和 5V 上,没顺序,两根线接在电机的一端也没顺序,怎么接都行
步进电机实验
步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。 本章所要实现的功能是: 通过 ULN2003 驱动模块控制 28BYJ48 步进电机运行方向及速度, 当按下 KEY1 键可调节电机旋转方向; 当按下 KEY2 键, 电机加速; 当按下 KEY3 键, 电机减速。
步进电机简介
步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。 在非超载的情况下, 电机的转速、 停止的位置只取决于脉冲信号的频率和脉冲数, 而不受负载变化的影响, 即给电机加一个脉冲信号, 电机则转过一个步距角。 这一线性关系的存在, 加上步进电机只有周期性的误差而无累计误差等特点。 使得在速度、位置等控制领域用步进电机来控制变的非常的简单。 虽然步进电机已被广泛的应用, 但步进电机并不能像普通的直流电机, 交流电机在常规下使用。 它必须由双环形脉冲信号、 功率驱动电路等组成控制系统方可使用。 因此用好步进电机也并
非易事, 它涉及到机械、 电机、 电子及计算机等多专业知识。 下图即为混合式步进电机组成图。
步进电机的工作原理
通常步进电机的转子为永磁体, 当电流流过定子绕组时, 定子绕组产生一矢量磁场。 磁场会带动转子旋转一定的角度, 使得转子的一对磁场方向与定子的磁场方向一致。 当定子的矢量磁场旋转一个角度。 转子也随着该磁场转步距角。 每输入一个电脉冲, 电动机转动一个角度前进一步。 它输出的角位移与输入的脉冲数成正比、 转速与脉冲频率成正比。 改变绕组通电的顺序, 电机就会反转。 所以可以控制脉冲数量、 频率及电动机各相绕组的通电顺序来控制步进电机的转动。
步进电机极性区分
步进电机又分为单极性的步进电机和双极性的步进电机; 具体简易图如下图所示:
其中左侧为单极性步进电机, 右侧为双极性的步进电机, 从上图中不难看出区别是什么。 单双极性是指一个步进电机里面有几种电流的流向, 左侧的五线四相步进电机就是单极性的步进电机, 图中的红色箭头为电流的走向, 四根线的电流走向汇总到公共线, 所以称之为单极性电机; 但是右侧则不同, 电机中有两个电流的回路, 两个电流的回路自然就是双极性, 所以称之为双极性电机。
单极性绕组
单极性步进电机使用的是单极性绕组。 其一个电极上有两个绕组, 这种联接方式为当一个绕组通电时, 产生一个北极磁场; 另一个绕组通电, 则产生一个南极磁场。 因为从驱动器到线圈的电流不会反向, 所以可称其为单极绕组。
双极性绕组
双极性步进电机使用的是双极性绕组。 每相用一个绕组, 通过将绕组中电流反向, 电磁极性被反向。 典型的两相双极驱动的输出步骤在电气原理图和下图中的步进顺序中进一步阐述。 按图所示, 转换只利用绕组简单地改变电流的方向,就能改变该组的极性。
永磁步进电机包括一个永磁转子、 线圈绕组和导磁定子, 只要将线圈通电根据电磁铁的原理就会产生磁场, 分为南北极, 见上图所示; 通过改变步进电机定子的磁场, 转子就会因磁场的变化而发生转动, 同理, 依次改变通电的顺序就可以使得电机转动起来。
双极性步进电机驱动原理
下图是一个双极性的步进电机整步, 步进顺序。 在第一步中: 将 A 相通电,根据电磁铁原理, 产生磁性, 并且因异性相吸, 所以磁场将转子固定在第一步的位置; 第二步: 当 A 相关闭, B 相通电时, 转子会旋转 90° ; 第三步: B 相关闭、 A 相通电, 但极性与第 1 步相反, 这促使转子再次旋转 90° 。 在第四步中:A 相关闭、 B 相通电, 极性与第 2 步相反。 重复该顺序促使转子按 90° 的步距角顺时针旋转。
上图中显示的步进顺序是单相激励步进, 也可以理解为每次通电产生磁性的相只有一个, 要么 A 相, 要么 B 相; 但是更常用的是双相激励, 但是在转换时,一次只能换相一次, 具体详见下图:
上图是两相同时通电的旋转顺序, 与单相激励不同的是, 单相通电后被固定在了与定子正对着的绕组极性, 但是双相同时激励时转子却被固定在两个绕阻的极性中间; 此时通电顺序就变成了 AB 相同时通电即可。
在双相激励的过程中, 也可以在换相位时加一个关闭相位的状态而产生走半步的现象, 这将步进电机的整个步距角一分为二, 例如,一个 90° 的步进电机将每半步移动 45°
, 具体见下图。
- A 相通电, B 相不通电
- A、B 相全部通电, 且电流相同, 产生相同磁性
- B 相通电, A 断电
- B 相通电, A 相通电, 且电流相等, 产生相同磁性
- A 相通电, B 断电
- A、 B 相全部通电, 且电流相同, 产生相同磁性
- B 相通电, A 断电
- B 相通电, A 相通电, 且电流相等, 产生相同磁性
其中 1~4 步与 5~8 步的电流方向相反(电流相反, 电磁的极性就相反) 这样就产生了顺时针旋转, 同理逆时针是将通电顺序反过来即可。
单极性步进电机驱动原理
单极性与双极性步进电机驱动类似, 都可以分为整步与半步的驱动方式, 不同的是, 双极性的步进电机可以通过改变电流的方向来改变每相的磁场方向, 但是单极性的就不可以了, 它有一个公共端, 这就直接决定了, 电流方向。 具体旋转顺序详见下图:
上图是单极性步进电机整步旋转的过程, 其中, 在图示中分为 5 根线, 分别为 A、 B、 C、 D 和公共端(+) , 公共端需要一直通电, 剩下 ABCD 相中只要有一个相通电, 即可形成回路产生磁场, 图中的通电顺序为 A->B->C->D, 即可完成上图中的顺时针旋转, 如果想要逆时针旋转只需要将其倒序即可。
以上是单相通电产生的整步旋转, 两相通电也可以产生, 两个相邻的相通电,这样相邻的两个相就都产生了回路, 也就产生了磁场, 图中的通电顺序为AB->BC->CD->DA, 同理逆时针旋转的顺序为逆序。 具体看下图:
上面两张图清晰的描述了单极性步进电机的通电顺序与旋转的过程, 综合这两张图就是单极性步进电机半步的通电顺序, 具体看下图:
上图兼容了前两张图的所有特点, 也可以说前两张图是这张图的子集, 图中的通电顺序为: A->AB->B->BC->C->CD->D->DA 转子每次只走半步 45 度, 所以这也被称为半步驱动, 与整步相比半步的旋转方式旋转起来更加的顺滑。
细分驱动原理
对于细分驱动的原理, 不分单双极性步进电机, 下图以单极性为例:
在上图中均为双相激励; 其中图(a) 为 A 相电流很大, B 相的电流极其微弱, 接近 0; 图 © 为 A 相和 B 相的电流相同, 电流决定磁场, 所以说 A 相和 B 相的磁场也是相同的, (a) 和(c) 可以是极限特殊的情况, 再看图(b)和图(d) 这两个是由于 A 相和 B 相的电流不同产生位置情况; 由此可以得出改变定子的电流比例就可以使得转子在任意角度停住。 细分的原理就是: 通过改变定子的电流比例, 改变转子在一个整步中的不同位置, 可以将一个整步分成多个小步来运行。
在上图中就是一个整步分成了 4 步来跑, 从(a) ~(d) 是 A 相的电流逐渐减小, B 相电流逐渐增大的过程, 如果驱动器的细分能力很强, 可以将其分成32 细分、 64 细分等; 这不仅提高了步进电机旋转的顺畅度,而且提高了每步的精度。
28BYJ-48 步进电机简介
28BYJ48 步进电机自带减速器, 为四相无线步进电机, 直径为 28mm, 实物如下所示:
28BYJ48 电机内部结构等效图如下所示:
旋转驱动方式如下表:
主要参数如下所示:
在上图中 28BYJ48 步进电机主要参数中可以看到有一个减速比:1:64, 步进角为 5.625/64 度, 如果需要转动一圈, 那么需要 360/5.625*64=4096 个脉冲信号
软件设计
本章所要实现的功能是: 通过 ULN2003 驱动模块控制 28BYJ48 步进电机运行方向及速度, 当按下 KEY1 键可调节电机旋转方向; 当按下 KEY2 键, 电机加速;当按下 KEY3 键, 电机减速。
c
/**************************************************************************************
实验名称:步进电机实验
接线说明:
实验现象:下载程序后,当按下KEY1键可调节电机旋转方向;当按下KEY2键,电机加速;
当按下KEY3键,电机减速
注意事项:将步进电机红色线对接到"步进电机模块"输出端子J47的5V上,其它相序依次接入。
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义ULN2003控制步进电机管脚
sbit IN1_A=P1^0;
sbit IN2_B=P1^1;
sbit IN3_C=P1^2;
sbit IN4_D=P1^3;
//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
// 定义步进电机速度,值越小,速度越快
// 最小不能小于1
#define STEPMOTOR_MAXSPEED 1
#define STEPMOTOR_MINSPEED 5
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : step_motor_28BYJ48_send_pulse
* 函数功能 : 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
* 输 入 : step:指定步进序号,可选值0~7
dir:方向选择,1:顺时针,0:逆时针
* 输 出 : 无
*******************************************************************************/
void step_motor_28BYJ48_send_pulse(u8 step,u8 dir)
{
u8 temp=step;
if(dir==0) //如果为逆时针旋转
temp=7-step;//调换节拍信号
switch(temp)//8个节拍控制:A->AB->B->BC->C->CD->D->DA
{
case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break;
case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break;
case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break;
case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break;
case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break;
case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break;
case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break;
case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break;
default: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=0;break;//停止相序
}
}
/*******************************************************************************
* 函 数 名 : key_scan
* 函数功能 : 检测独立按键是否按下,按下则返回对应键值
* 输 入 : mode=0:单次扫描按键
mode=1:连续扫描按键
* 输 出 : KEY1_PRESS:K1按下
KEY2_PRESS:K2按下
KEY3_PRESS:K3按下
KEY4_PRESS:K4按下
KEY_UNPRESS:未有按键按下
*******************************************************************************/
u8 key_scan(u8 mode)
{
//static关键字,第二次调用函数时key不会被该行代码初始化为1,其值为第一次调用该函数后key的值
static u8 key=1;
if(mode)key=1;//连续扫描按键
if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
{
delay_10us(1000);//消抖
key=0;
if(KEY1==0)
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEY3==0)
return KEY3_PRESS;
else if(KEY4==0)
return KEY4_PRESS;
}
//无按键按下,则始终保持key为1,等待按键按下
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
{
key=1;
}
return KEY_UNPRESS;
}
void main()
{
u8 key=0;
u8 dir=0;//默认逆时针方向
u8 speed=STEPMOTOR_MAXSPEED;//默认最大速度旋转
u8 step=0;
while(1)
{
key=key_scan(0);
if(key==KEY1_PRESS)//换向
{
dir=!dir;
}
else if(key==KEY2_PRESS)//加速
{
if(speed>STEPMOTOR_MAXSPEED)
speed-=1;
}
else if(key==KEY3_PRESS)//减速
{
if(speed<STEPMOTOR_MINSPEED)
speed+=1;
}
step_motor_28BYJ48_send_pulse(step++,dir);
if(step==8)step=0;
delay_ms(speed);
}
}