产品选型

51单片机pwm控制电机 看单片机如何控制PWM信号实现直流电机转速控制

小编 2024-10-23 产品选型 23 0

看单片机如何控制PWM信号实现直流电机转速控制

设计中采用了专门的芯片组成了PWM信号的发生系统并且对PWM信号的原理、产生方法以及如何通过软件编程对PWM信号占空比进行调节从而控制其输入信号波形等均作了详细的阐述。另外本系统中使用了红外对管对直流电机的转速进行测量,经过整形电路后将测量值送到单片机,并且最终作为反馈值输入到单片机进行PID运算从而实现了对直流电机速度的控制。在软件方面,文章中详细介绍了PID运算程序初始化程序等的编写思路和具体的程序实现。

1 单片机最小系统:单片机最小系统由51单片机,晶振电路,复位电路,电源组成。大家都比较熟悉,这里不再赘述。

2 四位数码管显示:在应用系统中,设计要求不同,使用的LED显示器的位数也不同,因此就生产了位数,尺寸,型号不同的LED显示器供选择,在本设计中,选择4位一体的数码型LED显示器,简称“4-LED”。本系统中前三位显示电压的整数位,最后一位显示转速的小数位。4-LED显示器引脚如图2所示,是一个共阴极接法的4位LED数码显示管,其中a,b,c,e,f,g为4位LED各段的公共输出端,1、2、3、4分别是每一位的位数选端,dp是小数点引出端,4位一体LED数码显示管的内部结构是由4个单独的LED组成,每个LED的段输出引脚在内部都并联后,引出到器件的外部。

3 电机驱动电路:电机驱动电中是采用ULN2003来驱动。ULN2003是高耐压、大电流达林顿陈列,由七个硅NPN达林顿管组成。该电路的特点:ULN2003的每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据,输入5VTTL电平,输出可达500mA/50V。ULN2003的引脚图,其中IN1~IN7为输入控制端;OUT1~OUT7为输出端;8脚为芯片的接地端;9脚为公共端,该脚是内部7个续流二极管负极的公共端,各二极管的正极分别接各达林顿管的集电极。用于感性负载时,该脚接负载电源正极,实现续流作用。如果该脚接地,实际上就是达林顿管的集电极对地接通。

当P1.0中为高电平时,其内部三极管导通,使电机转动。当P1.0为低电平时,内部三极管截止,电路断开,电机停止转动。所以在程序中可以利用P1.0口输出PWM波来控制电机的转速。

4 红外测速电路:发射管工作时发出红外线,当接收管收到红外信号时,其电阻变小(本设计相当于从无穷大变到1k左右)。利用其电阻变化,改变接收管分压情况。挡片是利用圆盘上剪四个孔,当挡片随电机转动时,接收管两端电平发生变化,产生脉冲。

5 整形电路:本设计的整形电路是用555定时器接成的施密特触发器。

6 源程序:

#include reg52.h

#define uchar unsigned char

#define uint unsigned int

uchar code table[10]={0x3f,0x06,0x5b,

0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管显示码(0-9)

sbit xiaoshudian=P0^7;

sbit wei1=P2^4; //数码管位选定义

sbit wei2=P2^5;

sbit wei3=P2^6;

sbit wei4=P2^7;

sbit beep=P2^3; //蜂鸣器控制端

sbit motor = P1^0; //电机控制

sbit s1_jiasu = P1^4; //加速按键

sbit s2_jiansu= P1^5; //减速按键

sbit s3_jiting=P1^6; //停止/开始按键

uint pulse_count; //INT0接收到的脉冲数

uint num=0; //num相当于占空比调节的精度

uchar speed[3]; //四位速度值存储

float bianhuasudu; //当前速度(理论计算值)

float reallyspeed; //实际测得的速度

float vv_min=0.0;vv_max=250.0;

float vi_Ref=60.0; //给定值

float vi_PreError,vi_PreDerror;

uint pwm=100; //相当于占空比标志变量

int sample_time=0; //采样标志

float v_kp=1.2,v_ki=0.6,v_kd=0.2; //比例,积分,微分常数

void delay (uint z)

{

uint x,y;

for(x=z;x0;x--)

for (y=20;y0;y--);

}

void time_init()

{

ET1=1; //允许定时器T1中断

ET0=1; //允许定时器T0中断

TMOD = 0x15; //定时器0计数,模式1;定时器1定时,模式1

TH1 = (65536-100)/256; //定时器1值,负责PID中断 ,0.1ms定时

TL1 = (65536-100)%6;

TR0 = 1; //开定时器

TR1 = 1;

IP=0X08; //定时器1为高优级

EA=1; //开总中断

}

void keyscan()

{

float j;

if(s1_jiasu==0) //加速

{

delay(20);

if(s1_jiasu==0)

vi_Ref+=10;

j=vi_Ref;

}

while(s1_jiasu==0);

if(s2_jiansu==0) //减速

{

delay(20);

if(s2_jiansu==0)

vi_Ref-=10;

j=vi_Ref;

}

while(s2_jiansu==0);

if(s3_jiting==0)

{

delay(20);

motor=0;

P1=0X00;

P3=0X00;

P0=0x00;

}

while(s3_jiting==0);

}

float v_PIDCalc(float vi_Ref,float vi_SpeedBack)

{

register float error1,d_error,dd_error;

error1=vi_Ref-vi_SpeedBack; //偏差的计算

d_error=error1-vi_PreError; //误差的偏差

dd_error=d_error-vi_PreDerror; //误差变化率

vi_PreError=error1; //存储当前偏差

vi_PreDerror=d_error;

bianhuasudu=(v_kp*d_error+v_ki*vi_PreError+v_kd*dd_error);

return (bianhuasudu);

}

void v_Display()

{

uint sudu;

sudu=(int)(reallyspeed*10); //乘以10之后强制转化成整型

speed[3]=sudu/1000; //百位

speed[2]=(sudu00)/100; //十位

speed[1]=(sudu0)/10; //个位

speed[0]=sudu; //小数点后一位

wei1=0; //第一位打开

P0=table[speed[3]];

delay(5);

wei1=1; //第一位关闭

wei2=0;

P0=table[speed[2]];

delay(5);

wei2=1;

wei3=0;

P0=table[speed[1]];

xiaoshudian=1;

delay(5);

wei3=1;

wei4=0;

P0=table[speed[0]];

delay(5);

wei4=1;

}

void BEEP()

{

if((reallyspeed)=vi_Ref+5||(reallyspeed

{

beep=~beep;

delay(4);

}

}

void main()

{

time_init();

motor=0;

while(1)

{

v_Display();

BEEP();

}

if(s3_jiting==0) //对按键3进行扫描,增强急停效果

{

delay(20);

motor=0;

P1=0X00;

P3=0X00;

P0=0x00;

}

while(s3_jiting==0);

}

void timer0() interrupt 1

{

}

void timer1() interrupt 3

{

TH1 = (65536-100)/256; //1ms定时

TL1 = (65536-100)%6;

sample_time++;

if(sample_time==5000) //采样时间0.1ms*5000=0.5s

{

TR0=0; //关闭定时器0

sample_time=0;

pulse_count=TH0*255+TL0; //保存当前脉冲数

keyscan(); //扫描按键

reallyspeed=pulse_count/(4*0.6); //计算速度

pwm=pwm+v_PIDCalc(vi_Ref,reallyspeed);

if(pwm

if(pwm100)pwm=100;

TH0=TL0=0;

TR0=1; //开启定时器0

}

num++;

if(num==pwm) //此处的num值,就是占空比

{

motor=0;

}

if(num==100) //100相当于占空比调节的精度

{

num=0;

motor=1;

}

}

STM32F0单片机 PWM + ADC 控制有刷电机

1. 有刷电机驱动电路

有刷电机是电机里面最简单,也是历史最悠久的一种,到现在仍然广泛应用于各个领域。他的控制很简单,在电机的两个电极加正向电压,则正向旋转,如果加反向电压,则旋转方向也反过来。电机的转速可以通过控制加在电极上的电压来调节。

在电机控制电路中最常用的器件就是 MOS 管了。可以分为两个大的类型:P 沟道 MOS 和 N 沟道 MOS。MOS 管可以简单的理解为一个自来水阀门,Gate 是控制端,调节 Drain 和 Source 端之间流过的电流大小。

下面是两种 MOS 的典型用法。P 沟道的 MOS 一般 S 接电源正极,然后 Vgs 需要一个负电压来打开电流通道,而 N 沟道的 S 极一般接电源的负极,Vgs 需要一个正电压来打开电流通道。

资料来源于 IOR 公司数据手册

我们先从一个最简单的驱动电路开始。单片机控制 MOS 管栅极为高时,电流从电源经过电机和 MOS 管到地。当栅极为低时,MOS 管断开,此时电机线圈内的电流继续通过续流二极管回流电机的正极。我们通过调节栅极控制端的PWM占空比,就可以控制电机的转速。

2. TIM模块

TIM 模块最重要的三个寄存器是:

Counter Register (TIMx_CNT) 计数寄存器

Auto-Reload Register (TIMx_ARR) 重置寄存器

Capture/compare mode register 1 (TIMx_CCMRx) 输入捕获/输出比较寄存器

Counter 在时钟的驱动下计数

Auto-Reload 设定计数的最大限制值

Capture/Compare 锁存一个事件发生时的计数值到Capture/计数达到 Compare 值后触发一个事件

在 PWM 模式下,Auto-Reload 寄存器设定PWM的周期,Compare 设定占空比。

有一点需要注意的是一个 TIM 模块只有一个计数器和一个重置寄存器,而有多个输入捕获/输出比较寄存器。所以一个 TIM 模块的多个通道可以设置不同的占空比,但周期都是相同的。

所以我们在选用 MCU 的时候,如果需要产生多种周期的 PWM,不仅要看它的定时器模块一共有多少通道数,还要看是否有足够的独立 TIM 模块。

3. 代码

我们在下面这个工程的基础上修改来实现用一个可调电阻控制PWM占空比,来控制电机的转速。

STM32Cube_FW_F0_V1.11.0\Projects\STM32F030R8-Nucleo\Examples\TIM\TIM_PWMOutput\MDK-ARM\Project.uvprojx

这个工程默认使用TIM3模块输出4路PWM,我们可以只保留其中一路。

然后把ADC采样的代码添加进来:

Step 1:

stm32f0xx_hal_conf.h

#define HAL_ADC_MODULE_ENABLED

Step 2:

main.h

添加ADC相关宏定义

Step 3:

stm32f0xx_hal_msp.c

添加ADC使用的引脚的初始化代码

Step 4:

把ADC的驱动文件添加进工程,在主程序初始化ADC。

Step 5:

读取 ADC 的值,写入 TIM 的 CCR 寄存器,观察 PWM 占空比的变化。根据电机的特性,还可能需要改变 PWM 的周期。

如果需要参考代码,可以在 Github 搜索 TopSemic 找到。

参考资料:

PM0215 STM32F0xxx Cortex-M0 programming manual

UM1785 Description of STM32F0 HAL and low-layer drivers

STM32F030 Datasheet

STM32F030 Reference Manual

相关问答

步进 电机 怎样用 51单片机 调速( pwm 方法)?

如果你用的是步进电机驱动器驱动步进电机,每来一个驱动脉冲,步进电机就走一步,所以改变驱动脉冲的频率即方波的频率就可以调速。如果你用的是步进电机驱动器...

51单片机pwm 直流 电机 怎么调速?

最简单的做法是选用stc单片机,用它的pwm引脚驱动h全桥,再由全桥驱动直流电机。编程时用单片机内部的pwm寄存器,输出不同占空比的脉冲就可以实现电机调速。将p...

51单片机控制pwm 风扇原理?

原理是当输出频率一定时,输出电压与高电平的占空比成正比,即PWM每个周期中高电平脉宽越宽输出电压越高。单片机使用方法是1.设置定时器的工作模式为PWM和输...

51单片机控制 输出的 pwm 波频率范围?

不同的单片机是不同的,拿STC15系列单片机来说:PWM的频率=PCA时钟输入频率/256PCA的时钟源有以下几种:sysclk,sysclk/2,sysclk/4,sysclk/6,sysclk/8...

STC 单片机 直流 电机 PWM 具体怎么使用?

一般用单片机控制直流电机运转的控制方法有两种,一种为电平控制(可能不准确),另一种为PWM控制。如果你选用第一种,你需要为你的直流电机设计一个驱动控制模...

直流 电机PWM 调速器该如何设计?

首先设计一个PWM调速器需要电子电路的设计,还有单片机程序的设计。下面我来分享一下直流电机PWM调速器的各种设计方案。觉得不错的话,请帮忙点赞和关注哦。如...

如何实现一块 单片机 (机器人), 控制 4个以上的伺服 电机 (单独运行)?

要实现单独的4路舵机控制的话,我建议使用具有至少4路PWM的单片机。比如AVR系列的有Atmega128,可同时产生6路12位的PWM。51系列的有STC12C5410AD带4路PWM。具体...

怎么用 51单片机 来实现 pwm 调节占空比?

可以用两级中断来实现,该方法可实现精确占空比与频率的调整。。。大致思想是:1.在定时器T0中开定时器T1,并使pwm=1,2.在定时器T1中关掉T1,即TR1=0;并使pw...

如何用atmega128实现8M系统时钟50hz 电机 pwm控制 ?

采用atmega128单片机与SA828配合来生成SPWM信号,这样外围的硬件结构比较简洁。采用atmega128单片机与SA828配合来生成SPWM信号,这样外围的硬件结构比较简洁。

请教直流 电机 PWM 驱动时的干扰问题?

由于电机在正常工作时对电源的干扰很大,只用一组电源时会影响单片机的正常工作。所以选用双电源供电。一组电源给单片机和控制电路供电,另外一组电源给电机...

猜你喜欢