临近期末,学校的单片机课程需要做课程设计,主要内容是基于51单片机的可调速电机,具体要求如下,在此记录一下具体的一个解题方案。
- 要求利用单片机输出PWM波形,通过改变占空比,改变电枢两端电压的平均值,从而改变电动机的转速
- 通过按键进行手动速度调整(速度+ 速度-)
- 利用串口调试助手或编写上位机软件,通过上位机控制直流速度调整
- 测量直流电机转速,并实时显示
原理图
首先是绘制原理图如下,右下角示波器为方便观察PWM脉冲波形用,可忽略
驱动电路
由于单片机的输出功率不足以驱动电机运动,因此这里使用L298芯片搭建一个驱动电路,驱动电压为12V,用于驱动电机运动。驱动电路如图。L298芯片的工作电压为5V(VCC接5V电压),支持同时驱动两台电机,可接驱动电压范围为(+5V~+46V),输出电流高达4A。
L298芯片控制引脚状态与电机对应状态如下图。因此,若要让电机运动则需要,ENA置1,IN1与IN2引脚所处电平相反。
ENA | IN1 | IN2 | 直流电机状态 |
---|---|---|---|
0 | X | X | 停止 |
1 | 0 | 0 | 制动 |
1 | 0 | 1 | 正转 |
1 | 1 | 0 | 反转 |
1 | 1 | 1 | 制动 |
MOTOR-ENCODER详解
这里由于需要测量电机转速,使用需要使用带有编码器的电机,Proteus中带有这样的一个电机,元件名称为MOTOR-ENCODER。MOTOR-ENCODER有5根引脚,其中左右两个接工作电压。上面三根引脚,左边与右边电机每转一圈就输出设定的脉冲数(这里设定每转一圈输出360个脉冲),二者脉冲相位相差90°。中间的引脚电机每转一圈引脚输出一个脉冲。 电机具体属性参数如下,这里设置电机额定电压为12V(因为驱动电路的驱动电压为12V),每转脉冲数为360(取值范围为1~360),其余保持默认。
串口通信
由于需要用到串口通信,因此需要用到Proteus中的虚拟串口COMPIM,将元件端口设置为COM1,波特率设置为9600,数据位8位,无校验位,停止位1位。将虚拟串口的RXD与单片机的RXD相连,TXD与TXD相连(与一般的串口连接不同,一般需要TXD与RXD交叉相连)。
然后打开VSPD虚拟串口连接软件(VSPD软件的下载与使用可参考该文章: 虚拟串口 VSPD 的使用),将COM1与COM2端口进行虚拟链接。然后进入串口助手打开COM2端口(一定不能打开COM1口,因为COM1口已被单片机占用) 设置好波特率、校验位与停止位,即可与单片机成功硬件连接。
电机测速原理
测速原理:单位时间内,根据该时间段内统计的脉冲数计算电机实际速度,这里单位时间为50ms。
由于编码器设置为每圈发出360个脉冲,则统计在50ms内的脉冲数即可知道在这50ms内电机转了多少圈,从而可推算出电机每分钟的转速。
设编码器单圈总脉冲数为C,在时间T0内,统计到的编码器脉冲数为M0,则转速n的计算公式为:
n = M0/(C*T0)。
PWM
PWM即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效的获得所需要的模拟参量。
其实就是通过控制高低电平的时间,来对输出的波形进行控制。
其中有几个重要的参数
PWM的频率:
是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);
也就是说一秒钟PWM有多少个周期
单位: Hz
表示方式: 50Hz 100Hz
PWM的周期:
T=1/f
周期=1/频率
50Hz = 20ms 一个周期
如果频率为50Hz ,也就是说一个周期是20ms 那么一秒钟就有 50次PWM周期
占空比:
是一个脉冲周期内,高电平的时间与整个周期时间的比例
单位: % (0%-100%)
表示方式:20%
一个简单的生成PWM的方法: 利用定时器进行定时中断,分别设置两个变量counter和compare。其中compare表示占空比。假设每100us定时器产生一次中断,则每进一次中断counter++,中断100次为一个周期,即T=10ms。
假设设置compare为60,即占空比为60%
每次定时器进入中断后,将当前counter值与compare进行判断,若counter<compare则置引脚为高电平,否则置低电平。这样在一个周期中,counter从1至100计数,counter为1~60时引脚均为高电平,即在一个周期内有60%的时间引脚都处于高电平。
这样我们就可以通过调整compare变量的值来控制PWM的占空比,从而达到控制电机转速的目的。
有关PWM的详细知识可参考以下文章
51单片机-PWM调速(直流电机,智能小车的电机调速)
PWM原理 PWM频率与占空比详解
软件部分
#include <REG51.H>
#define K 21/8
void UartInit(void);
void UART_SendByte(unsigned char Byte);
void Timer0Init(void);
sbit motor1_IN1=P0^0;
sbit motor1_IN2=P0^1;
sbit motor1_ENA1=P0^2;
sbit ADD=P0^3;
sbit SUBTRACT=P0^4;
unsigned char led_mod[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳极字模
unsigned char led_point[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//带小数点字模
unsigned char counter,compare;//compare为占空比
unsigned int n,m,rad;//n为脉冲数
void delay(unsigned char time) //1ms@11.0592MHz
{
unsigned char i, j;
i = 15*time;
j = 90;
do
{
while (--j);
} while (--i);
}
void Display() //LED显示
{
P2=(0x01);
P1=led_mod[(rad/100)%10];
delay(1);
P2=(0x01<<1);
P1=led_mod[(rad/10)%10];
delay(1);
P2=(0x01<<2);
P1=led_point[rad%10];
delay(1);
P2=(0x01<<3);
P1=led_mod[(rad%10)];
delay(1);
}
void move(void) //启动电机
{
motor1_IN1=1;
motor1_IN2=0;
}
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时初始值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //定时器1开始计时
ES=1; //开启中断
EA=1; //开启中断
PS=1; //设置优先级
}
void Timer0Init(void) //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0xA4; //设置定时初始值
TH0 = 0xA4; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //定时器0中断开启
EA=1; //EA开启
PT0=0; //定时器0开始计时
}
void UART_Routine(void) interrupt 4 //串口接收中断
{
if(RI==1)
{
compare=SBUF; //接收串口传输来的数据
SBUF=compare; //将当前占空比发送回上位机
while(!TI); //等待发送完毕
TI=0; //标志位复位
RI=0; //标志位复位
}
}
void Timer0_Routine(void) interrupt 1 //定时器0中断,用于PWM生成
{
TL0 = 0xA4; //设置定时初始值
TH0 = 0xA4; //设置定时初始值
counter++;
m++;
counter%=100;
if(counter<compare) //PWM生成
motor1_ENA1=1;
else
motor1_ENA1=0;
if(m==500) //50ms后计算一次转速
{
rad=n*K;//计算转速,若结果与实际有较大误差则调整比例系数K
m=0;
n=0;
}
}
void interrupt0_int() //电机编码器脉冲中断初始化
{
IT0=1;
EX0=1;
EA=1;
PX0=0;
}
void motor_Routine(void) interrupt 0 //编码器脉冲中断函数
{
n++; //脉冲数+1
}
void main()
{
Timer0Init(); //定时器0初始化
interrupt0_int(); //电机编码器中断初始化
UartInit(); //串口中断初始化
compare=70; //初始占空比70%
n=0; //电机旋转圈数初始化
m=0; //计时次数初始化
move(); //启动电机
while(1)
{
if(ADD==0)
{
compare=compare+10; //按下按键占空比+10
if(compare>100)
compare=100;
while(!ADD) //等待松开
Display();
}
if(SUBTRACT==0)
{
compare=compare-10; //按下按键占空比-10
if(compare<0)
compare=0;
while(!SUBTRACT) //等待松开
Display();
}
Display();
}
}
成果
电机正常转动,同时数码管显示当前转速,可通过ADD按键和SUBTRACT按键对转速进行加减速 。文章来源:https://www.toymoban.com/news/detail-412962.html
可通过串口对转速大小进行调整。
文章来源地址https://www.toymoban.com/news/detail-412962.html
到了这里,关于Proteus基于51单片机通过PWM脉冲调制控制电机转速_按键与串口控制转速_电机转速可测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!