分享

用单片机控制步进电机与直流电机其原理是否一样?

 陸号鱼 2023-10-24 发布于山东

我们平时都用到电机,它是一种把电能转换为机械能的装置,下面我们用实例来说说步进电机和直流电机在控制方式上有什么不同。今天我们用两个实例来给刚学单片机的小伙伴们说明,两种电机控制方式的不同。

一、步进电机的控制

步进电机是以脉冲信号电流来驱动,例如步进电机每转一周需要200个脉冲信号来激励,就可以计算出每个励磁信号能使步进电机前进1.8度,其旋转角度与脉冲的个数成正比,而步进电机的正反转有励磁脉冲产生的顺序来控制。通过以上的原理,我们就可以用程序来控制步进电机了,

1)连接:

(一)将P2.0、P2.1、P2.2、P2.3口分别接到P30(在步进电机模块的左侧)的A、B、C、D上。

(二)将M3(步进电机驱动模块输出)的A、B、C、D分别接到步进电机的A、B、C、D四相上,步进电机的COM端接到VCC(M3接口标志的VCC)上。

2)电源:将P35(步进电机驱动模块的左下角)接口用短接冒短接,电源+5V

3)按键命名:与P1低位到高位依次连接的按键一下命名为按键KEY1~KEY8

4)效果:启动程序,步进电机默认停止状态

按键4:步进电机暂停/继续

按键5:步进电机停止/运行

步进电机控制原理图

步进电机仿真图

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

#define T0_COUNT 50 //定时器0的计数值

#define KEY P1 //按键控制

#define MOTOR P2 //步进电机接口

sbit LED = P3^3; //LED指示灯

uint count; //节拍计数值

uint count_time; //计时时间

uchar count_beat; //步进电机驱动数组中的数值计数/*A AB B BC C CD D DA*/

uchar forward[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //四相八拍 正转

/* A AD D DC C CB B BA*/

uchar reverse[8]={0x01,0x09,0x08,0x0c,0x04,0x06,0x02,0x03}; //四相八拍 反转

bit forward_flag; //电机正反转标志, 1:电机正转 0:电机反转

bit stop_flag; //电机停止/运行标志 1:停止 0;运行

bit suspend_flag; //电机暂停/继续标志 1:暂停 0:继续

函数名称:delay_ms软件延时,延时的单位时间在1ms左右

void delay_ms(uint n)

{

uint i;

uchar j;

for(i=0;i<n;i++)

for(j=0;j<120;j++);

}

函数名称:key_scan功 能:按键扫描返 回 值:扫描的结果,"0"为无按键按下、非"0"为按键值

uchar key_scan()

{

uchar temp = 0;

KEY = 0xff;

if(KEY!=0xff)

{

delay_ms(10); //按键消抖

KEY = 0xff;

if(KEY!=0xff)

{

temp = KEY;

while(KEY!=0xff) //等待按键释放

KEY = 0xff;

}

}

return temp;

}

函数名称:key_behav形 参:uchar key_val:按键值功 能:实现按键功能

void key_behav(uchar key_val)

{

switch(key_val)

{

case 0xfe: //步进电机加速

if((0==stop_flag)&&(0==suspend_flag))

{

count_time -= 10; //减少节拍之间的时间

if(count_time<40)

count_time = 40;

}

break;

case 0xfd: //步进电机减速

if((0==stop_flag)&&(0==suspend_flag))

{

if(count_time<150)

count_time += 10; //增加节拍之间的时间

}

break;

case 0xfb: //步进电机正或反转选择

if((0==stop_flag)&&(0==suspend_flag))

{

forward_flag = ~forward_flag; //切换电机旋转模式

count_beat = 0; //步进电机驱动数组中的数值计数

}

break;

case 0xf7: //步进电机 暂停/继续

if(stop_flag==0)

{

suspend_flag = ~suspend_flag;

if(suspend_flag)

TR0 = 0; //暂停

else

TR0 = 1; //继续

}

break;

case 0xef: //步进电机停止/运行

stop_flag =~ stop_flag;

if(stop_flag)

{ //停止

TR0 = 0; //停止输出

LED = 1; //关闭LED指示灯

count_beat = 0;

count_time = 1000;

forward_flag = 1;

suspend_flag = 0;

}

else

{

LED = 0; //点亮LED指示灯

TR0 = 1; //允许输出

}

break;

default:break;

}

}

函数名称:interrupt_init功 能:中断寄存器初始化 返 回 值:无

void interrupt_init()

{

TMOD = 0x01; //定时器工作方式1

TH0 = (65536-T0_COUNT)/256; //赋值初值

TL0 = (65536-T0_COUNT)%256;

ET0 = 1; //打开定时器 1 中断

EA = 1; //打开总中断

}

函数名称:variable_init功 能:变量、标志初始化

void variable_init() //初始化

{

count_beat = 0; //赋占空比初值

count_time = 100;

forward_flag = 1; //步进电机正转

suspend_flag = 0; //电机继续

stop_flag = 1; //电机停止

}

void main()/*-------------主函数----------*/

{

uchar key_val; //定义变量

variable_init(); //变量初始化

interrupt_init(); //中断初始化

while(1)

{

key_val = key_scan(); //按键扫描,判断哪个按键按下

key_behav(key_val); //按键按下,判断实现的功能

}

}

函数名称:moto_run功 能:中断函数;产生控制电机的PWM波形返 回 值:无

void moto_run() interrupt 1

{

TH0 = (65536-T0_COUNT)/256; //定时器赋初值

TL0 = (65536-T0_COUNT)%256;

count++;

if((count>=count_time))

{

count = 0;

if(forward_flag) //步进电机正转

MOTOR = forward[count_beat];

else //步进电机反转

MOTOR = reverse[count_beat];

count_beat++;

}

if(count_beat>7)

count_beat=0;

}

用单片机仿真板发出脉冲信号由ULN2003驱动5伏步进电机

二、直流电机控制

用单片机控制直流电机,我们都知道由于单片机I/O的灌电流仅有10毫安左右,工作电压为5伏,要驱动额定电压为12伏,额定电流为几百毫安的直流电动机,必须增加驱动电路,才能提供大的驱动电流,我们常用的直流电动机驱动电路有继电器控制的驱动电路、有三极管组成的H桥驱动电路、电机驱动芯片、达林顿管驱动器等。我了达到电机正反转,我焊接了一个由三极管组成的驱动桥电路,来驱动电机的正反转。

微型直流电机驱动桥

1)连接:

(1)将P2.0、P2.1口接到P31(在直流电机模块的左侧)的DC_A、DC_B上。

(2)将B1(直流电机驱动模块输出)接到直流电机上。

(3)将P3.3口接到某一个LED接口上(P8或P17)。作为直流电机状态指示灯:亮,直 流电机运行;灭,直流电机停止

2)电源:将P36(直流电机驱动模块的左上角)接口用短接冒短接,电源+5V

3)按键命名:与P1低位到高位依次连接的按键一下命名为按键1~8

4)效果:启动程序,直流电机默认停止状态,运行指示灯熄灭

按键1:在直流电机运行的状态下,直流电机加速

按键2:在直流电机运行的状态下,直流电机减速

按键3:在直流电机运行的状态下,直流电机正反转切换

按键4:直流电机暂停/继续

按键5:直流电机停止/运行

直流电机控制原理图

直流电机仿真图

直流电机控制参考程序

#include<at89x52.h>

#define uchar unsigned char

#define uint unsigned int

#define T0_COUNT 100 //定时器0的计数值

#define KEY P1 //按键控制

#define PWM 100 //PWM计数值的上限值

#define INIT_VAL_PWM 20 //PWM占空比初始值

#define INCREMENT_PWM 10 //PWM控制时的增量大小

sbit DC_Moto_A = P2^0; //脉冲输入引脚

sbit DC_Moto_B = P2^1;

sbit LED = P3^3; //LED指示灯接口

uchar count_PWM; //PWM计数值

uchar val_PWM; //PWM占空比的值(加速可调)

bit forward_flag; //电机正反转标志, 1:电机正转 0:电机反转

bit stop_flag; //电机停止/运行标志 1:停止 0;运行

bit suspend_flag; //电机暂停/继续标志 1:暂停 0:继续

函数名称:delay_ms,形参:uint n:延时时间的长度,功能是软件延时,延时的单位时间在1ms左右

void delay_ms(uint n)

{

uint i;

uchar j;

for(i=0;i<n;i++)

for(j=0;j<120;j++);

}

函数名称:key_scan,功能:按键扫描,返 回 值:扫描的结果,"0"为无按键按下、非"0"为按键值

uchar key_scan() //按键检测

{

uchar temp = 0;

KEY = 0xff;

if(KEY!=0xff) //按键消抖

{

delay_ms(10);

KEY = 0xff;

if(KEY!=0xff)

{

temp = KEY;

while(KEY!=0xff) //等待按键释放

KEY = 0xff;

}

}

return temp;

}

函数名称:key_behav,形 参:uchar key_val:按键值,功能:实现按键功能

void key_behav(uchar key_val)

{

switch(key_val)

{

case 0xfe: //电机加速

if((0==stop_flag)&&(0==suspend_flag))

{

val_PWM += INCREMENT_PWM; //增加占空比

if(val_PWM>PWM) //PWM表示占空比的上限值

val_PWM = PWM;

}

break;

case 0xfd: //电机减速

if((0==stop_flag)&&(0==suspend_flag)) //他是如何加速的事通过什么来实现的呢

{

if(val_PWM>=INCREMENT_PWM)

val_PWM -= INCREMENT_PWM; //增加占空比

}

break;

case 0xfb: //电机正或反转选择

if((0==stop_flag)&&(0==suspend_flag))

forward_flag = ~forward_flag; //切换电机旋转模式

break;

case 0xf7: //电机暂停/继续

if(stop_flag==0)

{

suspend_flag = ~suspend_flag;

if(suspend_flag)

{

TR0 = 0; //暂停

DC_Moto_A = 0;

DC_Moto_B = 0;

}

else

TR0 = 1; //继续

}

break;

case 0xef: //电机停止/运行

stop_flag =~ stop_flag;

if(stop_flag)

{ //停止

TR0 = 0; //停止PWM输出

val_PWM = INIT_VAL_PWM; //初始化变量和标志

LED = 1; //关闭指示灯

forward_flag = 1;

suspend_flag = 0; //停止运行的时候初始化一下

DC_Moto_A = 0;

DC_Moto_B = 0;

}

else

{

LED = 0; //点亮指示灯

TR0 = 1; //允许输出PWM波形

}

break;

default:break;

}

}

函数名称:interrupt_init,功能:中断寄存器初始化

void interrupt_init() //初始化

{

TMOD = 0x01; //选择定时器/计数器工作方式1

TH0 = (65536-T0_COUNT)/256;

TL0 = (65536-T0_COUNT)%256;

ET0 = 1; //开定时器/计数器中断

TR0 = 1;

EA = 1; //开总中断

}

函数名称:variable_init,功能:变量、标志初始化

void variable_init() //变量初始化

{

val_PWM = INIT_VAL_PWM;

forward_flag = 1; //电机正反转标志

suspend_flag = 0; //电机暂停/继续标志

stop_flag = 1; //电机停止/运行标志

LED = 1; //关闭指示灯

DC_Moto_A = 0; //P2^0口输入

DC_Moto_B = 0; //P2^1口输入

}

void main() /*-------------主函数----------*/

{

uchar key_val;

variable_init(); //变量初始化

interrupt_init(); //中断函数初始化

while(1)

{

do

key_val = key_scan();

while(0==key_val);

key_behav(key_val);

}

}

函数名称:moto_run,功 能:中断函数;产生控制电机的PWM波形(定时器1中断)

void moto_run() interrupt 1 //选择正转还是反转跳入中断

{

TH0 = (65536-T0_COUNT)/256; //核心是在中断里面

TL0 = (65536-T0_COUNT)%256;

count_PWM++; //PWM计数值

if(forward_flag)

{ //电机正转

DC_Moto_B = 0;

if(count_PWM<val_PWM) //产生PWM

DC_Moto_A = 1;

else

DC_Moto_A = 0;

}

else

{ //电机反转

DC_Moto_A = 0;

if(count_PWM<val_PWM) //产生PWM

DC_Moto_B = 1;

else

DC_Moto_B = 0;

}

if(count_PWM>=PWM)

count_PWM = 0;

}

用单片机仿真板发出PWM波形去控制H桥来驱动直流小电机

以上程序我们是用PWM实现对电机的调速的,因为PWM信号只有两种状态,高电平和低电平,对于一个给定的周期来说,高电平所占的时间和周期之比我们称之为占空比,我们只要改变控制信号的占空比就可以改变电机的转速。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多