51单片机学习笔记-13直流电机

13 直流电机

[toc]

注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。
注:工程及代码文件放在了本人的Github仓库。


13.1 直流电机与PWM波

13.1.1 直流电机
直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。直流电机主要由永磁体(定子)、线圈(转子)和换向器组成。除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空心杯电机等。

51单片机学习笔记-13直流电机_第1张图片
图13-1 直流电机实物图
51单片机学习笔记-13直流电机_第2张图片
图13-2 直流电机原理图及驱动方式

根据上述原理图可以看出,由于单片机的IO口没有驱动能力,所以还是依靠外接的ULN2003D芯片进行驱动。从OUT1~OUT4任选两个端口即可完成驱动。对于直流电机,主要有两种供电方式:

  1. 大功率器件直接驱动:只能单向驱动。图中,续流二极管的作用是防止三极管截止时,直流电机中的电容击穿三极管。
  2. H桥驱动:可以双向驱动。
  3. 当然,开发板上采用的驱动芯片ULN2003D,在之前的“9蜂鸣器”一节已经介绍过。

13.1.2 PWM介绍
UP主最开始自己接了电位器(滑动变阻器)来控制直流电机转速,而电源供电端保持电压不变。最后发现,只有当电阻非常小的时候直流电机才开始转。但是直流电机需要的电流大,很容易就使得变阻器发热甚至烧毁。所以此方法并不好,还是要控制电源端的变化,也就是下面的PWM。
PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。PWM重要参数:

  • 频率 = 1/TS。频率越高,平均电压波形的谐波含量就越低。但后续使用生成PWM时,定时器重装频率过快会使主函数执行效率大幅下降。一般设置10~20kHz。
  • 占空比 = TON/TS
  • 精度 = 占空比变化步距

在软件层面,可以使用纯软件延时的方式完成PWM波,常用于“呼吸灯”等需要占空比频繁变化的场合;而对于电机调速这样的场合,期望程序在不调节时保持当前的占空比不变,这种场合下更常用的方法是使用定时器产生PWM波

  1. 对定时器进行计数,计数周期就是PWM波的周期。
  2. 在PWM波发生函数中,设定一个比较阈值,用于控制占空比。
  3. 显然,定时器的精度就是PWM波的精度。
51单片机学习笔记-13直流电机_第3张图片
图13-3 使用定时器产生PWM波原理

13.2 实验:LED呼吸灯

需求:全体LED以1秒为周期进行“呼吸式”亮度变化。

注:本实验建议纯软件延时完成PWM调节。即,只有一个主函数。

代码展示:
- mian.c

#include 

sbit LED0 = P2^0;
unsigned int PWM_Period = 100;
unsigned int PWM_Duty = 99;

// 延时函数一定要有,但单次延时应在10us以下
void Delay(unsigned int cycles){
	while(cycles--);
}

void main(){
  unsigned char i;
  P2 = 0xff; //LED初始全部熄灭
  while(1){
    for(PWM_Duty=0;PWM_Duty<PWM_Period;PWM_Duty++){
      for(i=0;i<10;i++){
        LED0 = 0;
        Delay(PWM_Duty);
        LED0 = 1;
        Delay(PWM_Period-PWM_Duty);
      }
    }
    for(PWM_Duty=PWM_Period-1;PWM_Duty>0;PWM_Duty--){
      for(i=0;i<10;i++){
        LED0 = 0;
        Delay(PWM_Duty);
        LED0 = 1;
        Delay(PWM_Period-PWM_Duty);
      }
    }
  }
}

编程感想:

  1. 关于延时函数:TMD天坑啊!思路其实很简单,但是一定要注意呼吸灯的PWM频率一定要非常快!!量级在1KHz以上(由于PWM周期为100,所以意味着延时函数在10us以下)才会有一个很好的效果。否则就会发现灯亮一下又闪,大晚上一直盯着灯看眼都快瞎了……

13.3 实验:直流电机调速

需求:设置直流电机转速等级:Stop、40%、50%、75%、100%。

每按下一次按键Key1,直流电机速度等级就上升一级(上升到最高归零)。
LCD第一行显示“DC motor:”;LCD第二行显示“xxx% Power”,如果为0就闪烁显示“Stop!”。
注:综合考虑程序效率和硬件效果,可设置定时器中断周期100us,PWM周期为100个定时器中断。

51单片机学习笔记-13直流电机_第4张图片
图13-4 “直流电机调速”代码调用

代码展示:
-main.c

#include 
#include "LCD1602.h"
#include "PushKey.h"
#include "Timer0.h"

#define motor P1_0
unsigned int PWM_Peri = 100;
unsigned int PWM_Duty = 0;
unsigned char speed_motor[5] = {0,40,50,75,100};

void main(){
  unsigned char key_num=0;//按键的编号
  unsigned char speed_index=0;//转速等级索引
  //LCD1602初始化
  LCD1602_Init();
  LCD1602_DispString(1,1,"DC motor:");
  LCD1602_DispString(2,1,"Stop!");
  //初始化定时器
  Timer0_Init();
  
  while(1){
    key_num = PushKey_GetKey();
    if(key_num==1){
      speed_index++;
      speed_index%=5;
      //调整PWM占空比(转速)
      PWM_Duty = speed_motor[speed_index];  
    }
    //LCD更新显示转速等级
    switch(speed_index){
      case 0:LCD1602_DispString(2,1,"Stop!     ");break;
      case 1:LCD1602_DispString(2,1," 40% Power");break;
      case 2:LCD1602_DispString(2,1," 50% Power");break;
      case 3:LCD1602_DispString(2,1," 75% Power");break;
      case 4:LCD1602_DispString(2,1,"100% Power");break;
      default:;
    }
  }
}

// 定义定时器T0中断后要执行的动作
void Timer0_Routine() interrupt 1{
  static unsigned int count1_T0,count2_T0; //中断次数
  TH0 = 0xFF; TL0 = 0xA4; // 恢复溢出周期,近似100us
  //对于PWM所需的中断
  count1_T0++; //更新中断次数
  if(count1_T0>PWM_Peri){
    count1_T0 = 0;    
  }else{
    if(count1_T0<PWM_Duty){motor=1;}//电机运行
    else                  {motor=0;}//电机不运行
  }
  //按键检测所需的中断
  count2_T0++; //更新中断次数
  if(count2_T0>20){
    count2_T0 = 0;
    PushKey_Loop();
  }
}

LCD1602.hLCD1602.c与第12节的实验代码相同。PushKey.hTimer0.h与13.2“温度报警器”的代码相同。

编程感想:

  1. 只要直流电机连着,就没法下载程序。必须要拔掉直流电机下载好之后,断电插上直流电机,插电。推测是因为USB所需电流激增,导致电脑主板进行端口保护,就不再进行串口通信??
  2. 直流电机和LCD显示屏冲突:USB电源的电流一般不超过1000MA(一般限流在750mA),当电流大时,电压下降得厉害,不能启动LCD1602。 所以可以使用其他驱动电流小的元件(如数码管),来显示当前的速度等级。
  3. 关于直流电机:注意电机引脚拉高时启动,因为达林顿晶体管阵列是非门。另外当PWM占空比过低时,也会导致直流电机平均启动电压过小而不转。
  4. 下面是使用LED来指示转速的代码:
//LCD更新显示转速等级
switch(speed_index){
    case 0:P2 = 0xff;break;
    case 1:P2 = 0xfc;break;
    case 2:P2 = 0xf0;break;
    case 3:P2 = 0xc0;break;
    case 4:P2 = 0x00;break;
    default:;
}

你可能感兴趣的:(#,51单片机-江科大,51单片机,学习,单片机)