您现在的位置是:首页 >学无止境 >51单片机(十五)直流电机驱动(PWM)网站首页学无止境

51单片机(十五)直流电机驱动(PWM)

乘凉~ 2024-06-17 10:20:00
简介51单片机(十五)直流电机驱动(PWM)

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
?专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
? 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
?专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf

本节主要介绍学习直流电机驱动(PWM)的相关知识,包括直流电机驱动(PWM)介绍、本节目标等;并利用两个小实验来写程序进行练习,分别是LED呼吸灯以及 直流电机调速,最后附上相关代码。

一、直流电机驱动(PWM)和本节目标

1.1 直流电机驱动(PWM)基础知识

直流电机介绍

在这里插入图片描述
本节我们主要学习的是直流电机,当然除了直流电机外还有很多其他种类的电机,比如步进电机、舵机、无刷电机、空心杯电机灯;

步进电机的结构中,外壳一整圈都分布着磁铁,中间有个转子,转子也是永磁体;通过对不同角度的磁铁进行通电,从而产生不同方向的磁力,改变转子的角度,最终吸引转子朝着特定的方向转动; 其好处就是,转子转动的速度,完全是由我们代码写入的通电时间决定的;

舵机可以输出固定的角度;常用与小车的转向电机;

无刷电机一般在四轴飞行器中会用到;其转速非常快,适合为飞机起飞提供强劲的动力;功率比较大,动力比较足;

电机驱动电路

在这里插入图片描述
电机对于单片机来说也是一种功率比较大的负载;如果将电机直接接在单片机的i/o口上,肯定是驱动不了的;而且有可能会损坏单片机的i/o口;所以我们需要在电机和i/o口之间加入驱动电路;

常见的驱动电路由两种,分别是大功率器件直接驱动和H桥驱动;

大功率器件直接驱动方式的特点是,它只能驱动电机朝着一个方向转动;因为这种电路不具备调换电机正反方向的功能;

H桥驱动方式是电机驱动里面非常有名的一种驱动方式;这种方式可以控制电机正反转;所以如果我们需要驱动电机正反转,那么就选H桥驱动电路;

在这里插入图片描述
大功率器件直接驱动方式跟三极管开关差不多,图中的Q1 PNP三极管要求选择一个功率比较大的器件;常见的达林顿管或mos管;

当IN输入低电平时,Q1三极管就会导通,电流就会由上往下(上图中)流动;D1二极管是用来保护电路的,称为续流二极管;正常驱动时,电流由上往下流动时,经过B1,就会驱动B1电机进行旋转;

续流二极管的作用是:因为电机是感性负载元件,所以在驱动时就要留意其感性值(电感值);即当电路正常通电,电机正常运转一段时间,突然断电后,由于电感的特性,在断电的瞬间,电感会产生很大的电压,如果不加续流二极管,则电感产生的电压有反向击穿三极管的风险;加了续流二极管后,电感和续流二极管则会连通形成回路,消耗电机在断电瞬间产生的电压,直到消耗完;

下面是H桥驱动:
在这里插入图片描述
因为整天的形状像是H,所以这个电路被称为H桥;

在这里插入图片描述

如果使Q1和Q4两个三极管导通,而Q3和Q2两个三极管断开,那么电流就是从左上角流向右下角,如上图所示,这样电机就会朝着一个方向转动;如果反过来,Q3和Q2两个三极管导通,Q1和Q4两个三极管断开,则电流就是从右上角流向左下角,如下图所示,这样电机就会朝着另一个方向转动;通过这种方式控制电机的正反转,因为电流方向既可以向右又可以向左;

在这里插入图片描述
在H桥驱动中,因为电流可以正方向也可以反方向,所以没办法加续流二极管,所以就要求四个三极管具有很强的耐压特性,以保证能够扛得住电感在断电瞬间感应出来的高电压;

下面介绍电机调速的相关知识

在这里插入图片描述
PWM通俗解释:

第一种情况,可以先让电机通电转1ms,然后将其断开5ms,此时,断电后电机由于惯性还在转,只是速度会缓慢下降;下降5ms后,继续通电,又加速转了1ms,然后又断开,用惯性减速5ms;这样反复进行,电机通电增长的速度远小于断电后下降的速度,最终电机则会以一个比较缓慢的速度在运行;

第二种情况,让电机通电转5ms,然后将其断开1ms,此时断电后电机由于惯性还在转,只是速度会缓慢下降;下降1ms后,继续通电,又加速转了5ms,然后又断开,用惯性减速1ms;这样反复进行,电机通电增长的速度远小于断电后下降的速度,电机则会以一个比较快速的速度在运行,电机的转速会远大于第一种情况;

第三种情况,让电机通电转5ms,然后将其断开5ms,此时断电后电机由于惯性还在转,只是速度会缓慢下降;下降5ms后,继续通电,又加速转了5ms,然后又断开,用惯性减速5ms;这样反复进行,电机通电增长的速度基本等于断电后下降的速度,电机则会以一个比中间的的速度在运行,比第一种情况速度大,比第二种情况的速度小;

总结一下就是,转的时间比较短,停的时间比较长,那么速度就比较低;反之,转的时间比较长,停的时间比较短,则转速比较高;

当然这里只是举个例子,具体在应用中设置多长时间通电和多长时间断电,就是下面要学习的PWM,脉冲宽度调制;

PWM经常用于这种存在惯性的场景,比如LED,断电后不会立马灭,而是有余晖慢慢变灭;比如电机,断电后不会立马停止转动,而是由于惯性慢慢的减速; 在这些具有惯性的场景中,PWM还是有很好的应用效果的;

PWM的参数包括:
频率:对于电机来说,就是断电和通电的次数,如果频率比较高,则电机转动的比较平滑;反之如果频率比较低,则电机转动的会有抖动;

占空比:占空比就是打开的时间比上一个周期的总时间;

精度:精度就是占空比的变化步距;

学习完PWM,就可以猜到电机调速的大致思想就是,不断的给电机高电平->低电平->高电平->低电平->高电平->低电平->高电平->低电平->高电平.........;通过控制频率就能控制电机的速度;

1.2 本节目标

目标1:LED呼吸灯

如下图所示,第一个LED灯以呼吸灯的形式进行亮灭

在这里插入图片描述
目标2:直流电机调速

将直流电机插在开发板上,按键K1、K2、K3可以对直流电机进行调速;

当按下K1时,1级速度速,如下图:
在这里插入图片描述

当按下K2时,2级速度速,如下图:

在这里插入图片描述

当按下K3时,3级速度速,如下图:

在这里插入图片描述

二、LED呼吸灯

代码路径:51单片机入门教程资料课件及程序源码程序源码KeilProject15-1 LED呼吸灯

具体代码:

#include <REGX52.H>

sbit LED=P2^0;

void Delay(unsigned int t)
{
	while(t--);
}

void main()
{
	unsigned char Time,i;
	while(1)
	{
		for(Time=0;Time<100;Time++)		//改变亮灭时间,由暗到亮
		{
			for(i=0;i<20;i++)			//计次延时
			{
				LED=0;					//LED亮
				Delay(Time);			//延时Time
				LED=1;					//LED灭
				Delay(100-Time);		//延时100-Time
			}
		}
		for(Time=100;Time>0;Time--)		//改变亮灭时间,由亮到暗
		{
			for(i=0;i<20;i++)			//计次延时
			{
				LED=0;					//LED亮
				Delay(Time);			//延时Time
				LED=1;					//LED灭
				Delay(100-Time);		//延时100-Time
			}
		}
	}
}

二、直流电机调速

代码路径:51单片机入门教程资料课件及程序源码程序源码KeilProject15-2 直流电机调速

具体代码:

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Timer0.h"

sbit Motor=P1^0;

unsigned char Counter,Compare;	//计数值和比较值,用于输出PWM
unsigned char KeyNum,Speed;

void main()
{
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Speed++;
			Speed%=4;
			if(Speed==0){Compare=0;}	//设置比较值,改变PWM占空比
			if(Speed==1){Compare=50;}
			if(Speed==2){Compare=75;}
			if(Speed==3){Compare=100;}
		}
		Nixie(1,Speed);
	}
}

void Timer0_Routine() interrupt 1
{
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;	//计数值变化范围限制在0~99
	if(Counter<Compare)	//计数值小于比较值
	{
		Motor=1;		//输出1
	}
	else				//计数值大于比较值
	{
		Motor=0;		//输出0
	}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。