51单片机笔记[6]-电机控制

实验目的

  1. 学习直流电机的工作原理,利用PWM脉冲控制直流电机的转动速度
  2. 学习步进电机的工作原理和控制方式,掌握简单的控制电路和电动机的基础知识

实验内容

直流电机控制

  1. 通过按键K1控制正反转
  2. 通过K2控制电机转速,每按一次,则速度增大一档,共3档
  3. 采用PWM控制电机转速

步进电机控制

[https://blog.csdn.net/m0_56646606/article/details/125025259]

  1. 使用L298驱动电机
  2. 通过K1-K4分别控制电机的正转,反转,加速,减速

原理

直流电机的分类

  • 步进电机:将电脉冲信号转变为角位移或线位移的开环控制元件,一般不带有编码器
  • 空心杯电机
  • 舵机

PWM信号

脉冲宽度调制 PWM 是一种模拟信号电平数字编码方法.
通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%.2、如何实现PWM信号输出那么如果要实现PWM信号输出如何输出呢?

1)可以直接通过芯片内部模块输出PWM信号,前提是这个I/O口要有集成模块

2)利用I/O口设置一些参数来输出PWM信号,因为PWM 信号其实就是一高一低的一系列电平组合在一起。具体方法是给I/O加一个定时器,对于你要求输出的PWM信号频率与你的定时器一致,用定时器中断来计数,

舵机的控制

常用舵机为SG90、MG996R等
舵机控制的另一个专业名字叫伺服控制。
经过百度,伺服”—词源于希腊语“奴隶”的意思。人们想把“伺服机构”当个得心应手的驯服工具,服从控制信号的要求而动作。在讯号来到之前,转子静止不动;讯号来到之后,转子立即转动;当讯号消失,转子能即时自行停转。由于它的“伺服”性能,因此而得名——伺服系统。
模拟舵机:需要不断的发送相应角度的PWM信号,才能旋转到指定位置。例如:我现在让它旋转90度,我就需要在一个时间内不断的发送90度的PWM信号,舵机转动到指定位置就会停止。

数字舵机:只需给一个目的地PWM信号,即可旋转到指定位置。例如:我现在让它旋转90度,我只需要发送一次90度的PWM信号,它就可以旋转到90度。

L298

L298N
是专用驱动集成电路,属于H桥集成电路,与L293D的差别是其输出电流增大,功率增强。其输出电流为2A,最高电流4A,最高工作电压50V,可以驱动感性负载,如大功率直流电机,步进电机,电磁阀等,特别是其输入端可以与单片机直接相联,从而很方便地受单片机控制。当驱动直流电机时,可以直接控制步进电机,并可以实现电机正转与反转,实现此功能只需改变输入端的逻辑电平。

L298N芯片可以驱动两个二相电机,也可以驱动一个四相电机,输出电压最高可达50V,可以直接通过电源来调节输出电压;可以直接用单片机的IO口提供信号;而且电路简单,使用比较方便。

L298N可接受标准TTL逻辑电平信号VSS,VSS可接4.5~7V电压。4脚VS接电源电压,VS电压范围VIH为+2.5~46V。输出电流可达2A,可驱动电感性负载。1脚和15脚下管的发射极分别单独引出以便接入电流采样电阻,形成电流传感信号。L298可驱动2个电动机,OUT1,OUT2和OUT3,OUT4之间可分别接电动机。

实验过程

原理图

直流电机控制 步进电机控制
👈

流程图

直流电机控制 步进电机控制

囿于水平有限,有所疏漏在所难免😳

代码

文件:26.c

//步进电机有点问题
#include <stdio.h>
#include <stc15f2k60s2.h>
#define u8 unsigned char
#define uchar unsigned char
#define u16 unsigned int
//***直流电机
sbit KEY1=P0^0;//正反转
sbit KEY2=P0^2;//加速
//***步进电机
sbit KEY3=P0^4;//正转
sbit KEY4=P0^6;//反转
sbit KEY5=P1^0;//加速
sbit KEY6=P1^2;//减速
sbit CONTROL_A=P3^0;
sbit CONTROL_B=P3^1;//控制正反转的功能管脚
sbit LED1=P4^0;
sbit LED2=P4^2;
sbit LED3=P4^3;
sbit MOTOR_IN1=P6^0;
sbit MOTOR_IN2=P6^1;
sbit MOTOR_IN3=P6^2;
sbit MOTOR_IN4=P6^3;
uchar code step_table[]={0x8,0xa,0x2,0x6,0x4,0x5,0x1,0x9};
unsigned char code BeatCode[8] = { //步进电机节拍对应的 IO 控制代码
	0xE, 0xC, 0xD, 0x9, 0xB, 0x3, 0x7, 0x6
};
void delay_ms(u16 t);//延时函数
u8 key_scan(void);//按键扫描函数
void time0_init(void);//定时器0初始化函数

u8 key_value;
u16 speed_adj=25;
void step_motor(){
	int i;
	u8 tmp; //定义一个临时变量
	u8 index = 0; //定义节拍输出索引
	if(LED1==0){
		
		for(i=0;i<8;i++){
			P6=step_table[i];
		}
	}
	if(LED2==0){
	
		for(i=0;i<8;i++){
			P6=step_table[i];
		}
	}

	for(i=0;i<8;i++){
		tmp = P2; //用 tmp 把 P2 口当前值暂存
		tmp = tmp & 0xF0; //用&操作清零低 4 位
		tmp = tmp | BeatCode[index]; //用|操作把节拍代码写到低 4 位
		P2 = tmp; //把低 4 位的节拍代码和高 4 位的原值送回 P2
		index++; //节拍输出索引递增
		index = index & 0x07; //用&操作实现到 8 归零
		delay_ms(2); //延时 2ms,即 2ms 执行一拍
	}
}

void main()
{
    time0_init();//定时器0初始化
    while(1)
  {
        key_value=key_scan();//传递按键键值
        if(key_value)//判断是否有按键按下
        {
            if(key_value==1)//正反转
            {
							switch((int)LED1){
								case 0:LED2=0;LED1=1;break;
								case 1:LED2=1;LED1=0;break;
							}
            }
            if(key_value==2)//加速
            {
                speed_adj+=5;
								if(speed_adj>35) speed_adj=25;
            }
            if(key_value==3)//正转
            {
								LED2=0;
								LED1=1;
								step_motor();
            }    
            if(key_value==4)//反转
            {
                LED2=1;
								LED1=0;
								step_motor();
            }       
            if(key_value==5)//加速
            {
                speed_adj+=5;
								step_motor();
            }                 
						if(key_value==6)//减速
						{
							speed_adj-=5;
							step_motor();
						}
        }
  }    
} 

void time0_int(void)    interrupt 1
{
    static u16 counter; 
    TH0=0XFF;
    TL0=0XA3;//100us
    counter=++counter%100;//周期:10ms
    if(LED1==0)//反转
    {
        if(counter<speed_adj)
        {
            CONTROL_A=1;//占空比
            CONTROL_B=0;
        }
        else
        {
            CONTROL_A=0;
            CONTROL_B=0;
        }    
    }
    if(LED2==0)//正转
    {
        if(counter<speed_adj)
        {
            CONTROL_B=1;//占空比
            CONTROL_A=0;
        }
        else
        {
            CONTROL_B=0;
            CONTROL_A=0;
        }
    }
}

void time0_init(void)//定时器0初始化
{
    TMOD &=0XF0;
    TMOD |=0X01;
    TH0=0XFF;
    TL0=0XA3;//100us
    ET0=1;
    EA=1;
    TR0=1;// 打开定时器0
}
void delay_ms(u16 t)//延时函数
{
    u8 i;
    while(t--)
    {
        for(i=114;i>0;i--);
    }
}

u8 key_scan(void)//按键扫描函数
{
    u8 key_num=0;
    if(KEY1==0){delay_ms(10);if(KEY1==0)key_num=1;}while(!KEY1);
    if(KEY2==0){delay_ms(10);if(KEY2==0)key_num=2;}while(!KEY2);
    if(KEY3==0){delay_ms(10);if(KEY3==0)key_num=3;}while(!KEY3);
    if(KEY4==0){delay_ms(10);if(KEY4==0)key_num=4;}while(!KEY4);
    if(KEY5==0){delay_ms(10);if(KEY5==0)key_num=5;}while(!KEY5);
		if(KEY6==0){delay_ms(10);if(KEY6==0)key_num=6;}while(!KEY6);
    return key_num;
}
posted @ 2022-09-10 19:49  qsBye  阅读(553)  评论(0编辑  收藏  举报