51单片机PID控制直流电机实验报告

基于51单片机的

直流电机PID控制

一、 试验器件选择

1、控制芯片的作用主要是与L289相连接驱动直流电机,以及与八位数码管相连显示。

(1)、AT89C51是一种带4K自己FLASH存储器的低压、高性能CMOS8为微处理器。单片机的可擦除只读存储器可以反复擦除1000次。该器件采用ATMEL高密度非易失真存储制造技术制造,与工业标准的MCS-51指令集和输出关键相兼容。由于将多功能8位CPU和闪存组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。AT89C51单片机为很多嵌入式控制系统提供了一种灵活性奥高且廉价的方案。

(2)、AT89C51引脚图如下:

2、电机驱动芯片

(1)、电机驱动芯片选择L298。其主要功能是作为单片机与直流电机中间的过度链接,单片机输出的信号通过L298加载到直流电机上驱动直流电机运行。其引脚图如下:

(2)、主要工作原理:

1、15脚分别是两个H桥的电流反馈脚,不用时可以直接接地;

2、3为一对输出端口,13、14为一对输出端口;

4为驱动电压输入,最小值必须比输入的低电平高2;

5、7一对输入端口,10、12一对输入端口,TTL电平兼容

6、11使能端,低电平禁止输出;

8、9分别为接地和逻辑电源

3、直流电机。在protues中选择motor-encoder直流电机,引脚图如下:

上方左右的两个引脚在点击运转时输出频

率相同的方波,但是在相位上相差90 ,而且

在正转和反转是相反,因此可以根据这两个引

脚的输出情况判断点击的转向。上方中间的引

脚每当电机转一圈就输出一个正脉冲,可以据

此册数点击的转速。左右两个引脚是电机的电

压输入端。

4、74HC74。当D触发器的D和CLK输入端分别接电机上方的左右两个输出端口时可以根据D触发器的输出情况判断点击的转速。

5、八位数码管。用以显示。

二、系统硬件设计连接

1、系统的器件连接图如下:

2、单片机与数码管通过P0口和P2口相连,其中P2口选择点亮哪一个数码管,P0口则控制被点亮的数码管显示的数据。

3、单片通过P1^0和P1^1和L298的第一对输入端IN1和IN2相连,然后又L298的第一对输出端OUT1和OUT2与直流电机相连,已达到控制直流电机的目的。

4、从P1^4到P1^7分别接一个Button按钮来实现PID控制,P3^6和P3^7分别接Button按钮实现对电机的加速与减速控制。

5、双刀双掷开关SW1课实现点击的正转与反转,单刀双掷开关SW2可实现点击的开启与停止。

三、 系统程序设计及功能实现

1、程序流程图:

2、各部分实现程序:

(1)、普通延时:

#include

void delayms(unsigned char x)

{

unsigned char i ;

while(x--)

for(i = 0 ; i

}

(2)、数码管显示:

#include

#include

#include

void display_lilun(double num)

{

char code table[] = {

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, //0~7对应数码 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //8~F对应数码 long int n=num;

P0 = 0; P2 =0x7f; P0 = table[n % 1000/100]; delayms(2);//百位加小数点

P0 = 0; P2 =0xbf; P0 = table[n % 100 / 10]; delayms(2);//十位

P0 = 0; P2 =0xdf; P0 = table[n % 10]; delayms(2);//个位

P0 = 0; //关闭显示器

}

void display(double num,int dir)

{

char code table[] = {

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, //0~7对应数码 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //8~F对应数码 long int n=num*10;

P0 = 0; P2 =0xf7; P0 = table[n / 1000]; delayms(2); //百位加小数点

P0 = 0; P2 =0xfb; P0 = table[n % 1000/100]; delayms(2); //百位加小数点

P0 = 0; P2 =0xfd; P0 = table[n % 100 / 10]+128; delayms(2);//十位

P0 = 0; P2 =0xfe; P0 = table[n % 10]; delayms(2);//个位

P0 = 0; //关闭显示器

if(dir==1)

{

P0=0;P2=0xef;P0=0x40;delayms(2);

}

}

(3)、按键扫描:

#include

sbit jiashi=P1^3; //

sbit jianshi=P1^4;

sbit jia=P1^5;

sbit jian=P1^6;

sbit enter=P1^7;

extern int num_key[5]; //

void keyscan()

{

if(jiashi==0)

{

while(!jiashi);

num_key[0]++;

}

if(jianshi==0)

{

while(!jianshi);

num_key[1]++;

}

if(jia==0)

{

while(!jia);

num_key[2]++;

}

if(jian==0)

{

while(!jian);

num_key[3]++;

}

if(enter==0)

{ 对各个按钮进行位定义定义全局变量

while(!enter);

num_key[4]++;

}

}

(4)、PWM波输出:

#include

#include

#include

extern int PWM ; //赋初值

extern int start,sudu_lilun;

extern double dis_count;

sbit S2 =P3^6 ; //PWM值减少键

sbit S3 =P3^7 ; //PWM值增加键

void PWM_duty()

{

if(start>=1)

PWM=sudu_lilun;

do

{

if(PWM!=0xff)

{

PWM++ ;

delayms(10);

}

}

while(S3==0);

do

{

if(PWM>=0x02)

{

PWM-- ;

delayms(10);

}

}

while(S2==0);

}

(5)、中断服务程序:

#include

extern int PWM,count,count1,dir,count20ms_flag;

extern double dis_count;

sbit PWM_OUT1=P1^1;

sbit PWM_OUT2=P1^0;

void timer0() interrupt 1

{

long int i;

TR1=0 ;

dir=0;

TL0=0x00;

TH0=0xd8; //10ms

TL0=0xf0;

TH1=PWM ;

TR1=1 ;

PWM_OUT1=0 ; //启动输出

PWM_OUT2=0;

if(i++==492)

{

count20ms_flag=1;

i=0;

dis_count=(double)(count+count1)/2;

count=0;

count1=0;

}

}

void timer1() interrupt 3

{

TR1=0 ;

if(dir==0)

{

PWM_OUT1=1 ; //结束输出

PWM_OUT2=0;

}

else

{

PWM_OUT1=0;

PWM_OUT2=1;

}

}

void EIRQ0(void) interrupt 0

{

EX0=0;

count++;

EX0=1;

}

void EIRQ1(void) interrupt 2

{

EX1=0;

count1++;

EX1=1;

}

(6)、PID控制:

#include

#include

int P,I,D;

extern int sudu_lilun;

typedef struct PID //定义结构体

{

int SetPoint; //目标

long SumError; //误差

double Proportion; //比例系数

double Integral; //积分系数

double Derivative; //微分系数

int LastError;

int PrevError;

}PID;

static PID sPID;

static PID *sptr = &sPID;

void IncPIDInit()

{

sptr->SumError = 0;

sptr->LastError =0; //Error[-1]

sptr->PrevError =0; //Error[-2]

sptr->Proportion =0.5; //比例系数

sptr->Integral =0.3; //积分系数

sptr->Derivative = 0.3; //微分系数

sptr->SetPoint =sudu_lilun;

}

int IncPIDCalc(int NextPoint)

{

register int iError, iIncpid; //当前的误差值

iError = sptr->SetPoint - NextPoint; //计算增加量

iIncpid = sptr->Proportion * iError //E[k]项

- sptr->Integral * sptr->LastError //E[k-1]项

+ sptr->Derivative * sptr->PrevError; //E[k-2]项

//存储当前误差以便后面计算

sptr->PrevError = sptr->LastError;

sptr->LastError = iError;

//返回增量值

return(iIncpid);

}

(7)、main函数:

#include

#include

#include

#include

#include

#include

#include

sbit P10=P1^2; //确定电机转向

int num_key[5];

int PWM,PWM1,count,count1,dir,sudu_lilun,start,count20ms_flag; double dis_count;

int PWM_PID;

void init();

void main()

{

init();

while(1)

{

PWM_duty();

if(P10==1)

dir=0;

else

dir=1;

keyscan();

sudu_lilun=num_key[0]*10-num_key[1]*10+num_key[2]-num_key[3]; display_lilun(sudu_lilun);

if(num_key[4]==1)

start=1;

display(dis_count,dir);

if(start>=1&&count20ms_flag==1)

{

count20ms_flag=0;

IncPIDInit();

PWM_PID=IncPIDCalc(dis_count);

PWM=PWM+PWM_PID*2;

}

}

}

void init() //定时器、外部中断初始化 {

TMOD=0x01 ;

TH0=0xd8;

TL0=0xf0;

IT0=1;

EX0=1;

IT1=1;

EX1=1;

TH1=PWM ;

TL1=0xff ;

EA=1;

ET0=1;

ET1=1;

TR0=1 ;

}

3、程序实现效果:

基于51单片机的

直流电机PID控制

一、 试验器件选择

1、控制芯片的作用主要是与L289相连接驱动直流电机,以及与八位数码管相连显示。

(1)、AT89C51是一种带4K自己FLASH存储器的低压、高性能CMOS8为微处理器。单片机的可擦除只读存储器可以反复擦除1000次。该器件采用ATMEL高密度非易失真存储制造技术制造,与工业标准的MCS-51指令集和输出关键相兼容。由于将多功能8位CPU和闪存组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。AT89C51单片机为很多嵌入式控制系统提供了一种灵活性奥高且廉价的方案。

(2)、AT89C51引脚图如下:

2、电机驱动芯片

(1)、电机驱动芯片选择L298。其主要功能是作为单片机与直流电机中间的过度链接,单片机输出的信号通过L298加载到直流电机上驱动直流电机运行。其引脚图如下:

(2)、主要工作原理:

1、15脚分别是两个H桥的电流反馈脚,不用时可以直接接地;

2、3为一对输出端口,13、14为一对输出端口;

4为驱动电压输入,最小值必须比输入的低电平高2;

5、7一对输入端口,10、12一对输入端口,TTL电平兼容

6、11使能端,低电平禁止输出;

8、9分别为接地和逻辑电源

3、直流电机。在protues中选择motor-encoder直流电机,引脚图如下:

上方左右的两个引脚在点击运转时输出频

率相同的方波,但是在相位上相差90 ,而且

在正转和反转是相反,因此可以根据这两个引

脚的输出情况判断点击的转向。上方中间的引

脚每当电机转一圈就输出一个正脉冲,可以据

此册数点击的转速。左右两个引脚是电机的电

压输入端。

4、74HC74。当D触发器的D和CLK输入端分别接电机上方的左右两个输出端口时可以根据D触发器的输出情况判断点击的转速。

5、八位数码管。用以显示。

二、系统硬件设计连接

1、系统的器件连接图如下:

2、单片机与数码管通过P0口和P2口相连,其中P2口选择点亮哪一个数码管,P0口则控制被点亮的数码管显示的数据。

3、单片通过P1^0和P1^1和L298的第一对输入端IN1和IN2相连,然后又L298的第一对输出端OUT1和OUT2与直流电机相连,已达到控制直流电机的目的。

4、从P1^4到P1^7分别接一个Button按钮来实现PID控制,P3^6和P3^7分别接Button按钮实现对电机的加速与减速控制。

5、双刀双掷开关SW1课实现点击的正转与反转,单刀双掷开关SW2可实现点击的开启与停止。

三、 系统程序设计及功能实现

1、程序流程图:

2、各部分实现程序:

(1)、普通延时:

#include

void delayms(unsigned char x)

{

unsigned char i ;

while(x--)

for(i = 0 ; i

}

(2)、数码管显示:

#include

#include

#include

void display_lilun(double num)

{

char code table[] = {

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, //0~7对应数码 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //8~F对应数码 long int n=num;

P0 = 0; P2 =0x7f; P0 = table[n % 1000/100]; delayms(2);//百位加小数点

P0 = 0; P2 =0xbf; P0 = table[n % 100 / 10]; delayms(2);//十位

P0 = 0; P2 =0xdf; P0 = table[n % 10]; delayms(2);//个位

P0 = 0; //关闭显示器

}

void display(double num,int dir)

{

char code table[] = {

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, //0~7对应数码 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //8~F对应数码 long int n=num*10;

P0 = 0; P2 =0xf7; P0 = table[n / 1000]; delayms(2); //百位加小数点

P0 = 0; P2 =0xfb; P0 = table[n % 1000/100]; delayms(2); //百位加小数点

P0 = 0; P2 =0xfd; P0 = table[n % 100 / 10]+128; delayms(2);//十位

P0 = 0; P2 =0xfe; P0 = table[n % 10]; delayms(2);//个位

P0 = 0; //关闭显示器

if(dir==1)

{

P0=0;P2=0xef;P0=0x40;delayms(2);

}

}

(3)、按键扫描:

#include

sbit jiashi=P1^3; //

sbit jianshi=P1^4;

sbit jia=P1^5;

sbit jian=P1^6;

sbit enter=P1^7;

extern int num_key[5]; //

void keyscan()

{

if(jiashi==0)

{

while(!jiashi);

num_key[0]++;

}

if(jianshi==0)

{

while(!jianshi);

num_key[1]++;

}

if(jia==0)

{

while(!jia);

num_key[2]++;

}

if(jian==0)

{

while(!jian);

num_key[3]++;

}

if(enter==0)

{ 对各个按钮进行位定义定义全局变量

while(!enter);

num_key[4]++;

}

}

(4)、PWM波输出:

#include

#include

#include

extern int PWM ; //赋初值

extern int start,sudu_lilun;

extern double dis_count;

sbit S2 =P3^6 ; //PWM值减少键

sbit S3 =P3^7 ; //PWM值增加键

void PWM_duty()

{

if(start>=1)

PWM=sudu_lilun;

do

{

if(PWM!=0xff)

{

PWM++ ;

delayms(10);

}

}

while(S3==0);

do

{

if(PWM>=0x02)

{

PWM-- ;

delayms(10);

}

}

while(S2==0);

}

(5)、中断服务程序:

#include

extern int PWM,count,count1,dir,count20ms_flag;

extern double dis_count;

sbit PWM_OUT1=P1^1;

sbit PWM_OUT2=P1^0;

void timer0() interrupt 1

{

long int i;

TR1=0 ;

dir=0;

TL0=0x00;

TH0=0xd8; //10ms

TL0=0xf0;

TH1=PWM ;

TR1=1 ;

PWM_OUT1=0 ; //启动输出

PWM_OUT2=0;

if(i++==492)

{

count20ms_flag=1;

i=0;

dis_count=(double)(count+count1)/2;

count=0;

count1=0;

}

}

void timer1() interrupt 3

{

TR1=0 ;

if(dir==0)

{

PWM_OUT1=1 ; //结束输出

PWM_OUT2=0;

}

else

{

PWM_OUT1=0;

PWM_OUT2=1;

}

}

void EIRQ0(void) interrupt 0

{

EX0=0;

count++;

EX0=1;

}

void EIRQ1(void) interrupt 2

{

EX1=0;

count1++;

EX1=1;

}

(6)、PID控制:

#include

#include

int P,I,D;

extern int sudu_lilun;

typedef struct PID //定义结构体

{

int SetPoint; //目标

long SumError; //误差

double Proportion; //比例系数

double Integral; //积分系数

double Derivative; //微分系数

int LastError;

int PrevError;

}PID;

static PID sPID;

static PID *sptr = &sPID;

void IncPIDInit()

{

sptr->SumError = 0;

sptr->LastError =0; //Error[-1]

sptr->PrevError =0; //Error[-2]

sptr->Proportion =0.5; //比例系数

sptr->Integral =0.3; //积分系数

sptr->Derivative = 0.3; //微分系数

sptr->SetPoint =sudu_lilun;

}

int IncPIDCalc(int NextPoint)

{

register int iError, iIncpid; //当前的误差值

iError = sptr->SetPoint - NextPoint; //计算增加量

iIncpid = sptr->Proportion * iError //E[k]项

- sptr->Integral * sptr->LastError //E[k-1]项

+ sptr->Derivative * sptr->PrevError; //E[k-2]项

//存储当前误差以便后面计算

sptr->PrevError = sptr->LastError;

sptr->LastError = iError;

//返回增量值

return(iIncpid);

}

(7)、main函数:

#include

#include

#include

#include

#include

#include

#include

sbit P10=P1^2; //确定电机转向

int num_key[5];

int PWM,PWM1,count,count1,dir,sudu_lilun,start,count20ms_flag; double dis_count;

int PWM_PID;

void init();

void main()

{

init();

while(1)

{

PWM_duty();

if(P10==1)

dir=0;

else

dir=1;

keyscan();

sudu_lilun=num_key[0]*10-num_key[1]*10+num_key[2]-num_key[3]; display_lilun(sudu_lilun);

if(num_key[4]==1)

start=1;

display(dis_count,dir);

if(start>=1&&count20ms_flag==1)

{

count20ms_flag=0;

IncPIDInit();

PWM_PID=IncPIDCalc(dis_count);

PWM=PWM+PWM_PID*2;

}

}

}

void init() //定时器、外部中断初始化 {

TMOD=0x01 ;

TH0=0xd8;

TL0=0xf0;

IT0=1;

EX0=1;

IT1=1;

EX1=1;

TH1=PWM ;

TL1=0xff ;

EA=1;

ET0=1;

ET1=1;

TR0=1 ;

}

3、程序实现效果:


相关内容

  • 智能车电磁组技术报告
  • 第八届全国大学生"飞思卡尔"杯 智能汽车竞赛 技 术报 告 目 录 摘 要 ...................................................................................................... ...

  • 西部赛区-光电组-成都理工大学工程技术学院-战狼队技术报告
  • 第九届全国大学生"飞思卡尔"杯 智能汽车竞赛 技术报 告 学校:成都理工大学工程技术学院 队伍名称:战狼队 参赛队员:黄喜恒 王攀 张冲 带队教师:杨斌朱里红 关于技术报告和研究论文使用授权的说明本人完全了解第九届"飞思卡尔"杯全国大学生智能汽车邀请赛关于保留 ...

  • 飞思卡尔_第十届_摄像头技术报告
  • 第十届"飞思卡尔"杯全国大学生 智能汽车竞赛 技 术 报 告 学 校:安徽科技学院 队伍名称:摄像头一队 参赛队员:.... 带队教师: .... - 1 - 关于技术报告和研究论文使用授权的说明 本人完全了解第八届"飞思卡尔"杯全国大学生智能汽车竞赛关保留. ...

  • 51系列单片机闭环温度控制实验报告
  • 成 绩: 重庆邮电大学 自动化学院综合实验报告 题 目:51系列单片机闭环温度控制 学生姓名:蒋运和 班 级:0841004 学 号:2010213316 同组人员:李海涛 陈超 完成时间:2013年12月 一.实验名称: 51系列单片机闭环温度控制实验 --基于Protuse 仿真实验平台实现 基 ...

  • BLDC直流无刷电机驱动
  • 目 录 第1章 无刷直流电机驱动实验指导···············································································2 1.1 1.2 1.3 1.4 1.5 概述··························· ...

  • 直流电机闭环调速
  • 第1章 前言 1.1 课题的研究意义 现代化的工业生产过程中,几乎无处不使用电力传动装置,尤其是在石油.化工.电力.冶金.轻工.核能等工业生产中对电动机的控制更是起着举足轻重的作用.因此调速系统成为当今电力拖动自动控制系统中应用最广泛的一种系统.随着生产工艺.产品质量要求不断提高和产量的增长,使得越 ...

  • 实验一 单容水箱对象特性的测试
  • 实验一.单容水箱对象特性的测试 一. 实验目的 1.了解本实验装置的结构与组成,掌握压力变送器的使用方法. 2.掌握实验装置的基本操作与变送器仪表的调整方法. 3.了解单容水箱的自衡特性掌握单容水箱的数学模型及其阶跃响应曲线. 4.实测单容水箱液位的阶跃响应曲线,用相关的方法分别确定它们的参数. 二 ...

  • 柴油机数字式电子调速器
  • 第25卷第6期 华 中 理 工 大 学 学 报 V ol. 25 N o. 61997年 6月 J. Huazhong U niv. of Sci. &T ech. Jun. 1997 柴油机数字式电子调速器 段晖辉 高世伦 金寿吉(船舶和海洋工程系) 摘 要 提出了一种采用M CS-809 ...

  • 13年电子设计竞赛报告
  • 2013年C题 简易旋转倒立摆及控制装置 (本科组) 本系统以stm32F103RBT6单片机为控制核心,通过步进电机带动旋转臂,再通过转轴带动摆杆来实现摆杆的运动. 简易旋转倒立摆及控制装置 摘要:本装置以stm32FRBT6103单片机为控制核心,用配套的24V直流电源模块给驱动模块供电来驱动步 ...