-
编码器输出的
A
向脉冲接到单片机的外部中断<
/p>
INT0
,
B
向
脉冲接到
I/O
端口
P1.0
。当系统工作时,首先要把
INT0
设置成下降
沿触发,
并开相应中断。当有有效脉冲触发中断时,进行中断处理程序,判别
B
脉冲是高电平还是低电平,若是高电平则编码器正转,加
1
计数;
若是低电平则编码
器反转,减
1
计数。
基于
51
单
片机的直流电机
PID
闭环调速系统原理详解与程序
(2013-08-04 01:18:15)
转
载
标签:
51
单
片
机<
/p>
直
流
电
机
pid
pcf8591
▼
分类:
单片机
基于
51
单片机的直流电机
PID<
/p>
闭环调速系统
1.
电机转速反馈:
原理:
利用光电编码器作为转速的反
馈元件,设电机转一周光电编码器
发送
N
个
PWM
波形,利用
测周法
测量电机转速。
具
体实现:
将定时器
0
设置在
计数模式
,
用来统计一定的时间
< br>T
内接受到
的脉冲个数
M
个,而定时器
0
置在
计时模式
,用来计时
T
时间。则如果<
/p>
T
时
间接受到
M
个
PWM
波形,
而电机转一圈发出
N
个
PWM
波形,
则根据测周法原
理,电机的实际的转速
为:
real_speed=M/
(
N
*T
)
,单位转
/
秒。若将定时器
1
置在
计数模式<
/p>
,则
PWM
波形应该由
< br>P3^3
脚输入。
代码实现:
//
定时器
0
初始化,用来定时
10m
s
void Init_Timer0(void)
{
TMOD |= 0x01; //
< br>使用模式
1
,
16
位定时器
,且工作在计时模式
TH0=(65536-10000)/256;
//
定时
10ms
TL0=(65536-10000)%6;
EA=1; //
总中断打开
ET0=1;
//
定时器中断打开
TR0=1;
//
定时器开关打开
}
//
计
数器
1
初始化,用来统计定时器
1
p>
计时
250ms
内
PWM
波形个数
void
Init_Timer1(void)
{
TMOD |=
0x50; //
使用计数模式
1
,
16
位计数器模式
TH1=0x00; //
给定初值,由
0
往上计数
TL1=0x00;
EA=1;
//
总中断打开
ET1=1;
//
定时器中断打开
TR1=1;
//
定时器开关打开
}
//
定时器
0
的中断服务子函数,
主要完成脉冲个数的读取,
实际转速的计算和
PID
控制以及控制结
//
果输出等工作
void Timer0_isr(void) interrupt 1
{
unsigned char count;
TH0=(65536-10000)/256;
//
重新赋值
10ms
TL0=(65536-10000)%6;
count++;
if
(count==25) //
如果达到
250ms
,则计算一次转速并进行一次控制运算
{
count=0;//
清零以便于定时下一个
250ms
TR1=0;//
关闭定时器
1
p>
,统计脉冲个数
real_speed
=(256*TH1+TL1)*4/N;//250ms
内脉冲个数并由此计算转速<
/p>
TH1=0x00; /
/
计数器
1
清零,重新开始计数
TL1=0x00;
TR1=1;
OUT=contr_PID();/
/
进入
PID
控制
,
PID
控制子函数代码在后面
给出
write_add(0x40,OUT);
//
进行
DA
转换,将数字量转换为模
拟量,后面会介绍到
}
}
控制:
P
ID
的基本原理在这里不作具体讲解,这里主要给出
PID
p>
算法的实现,通过调
节结构体中比例常数(
Proportion
)
、积分常数(
Integral
)
、微分常数
(
p>
Derivative
)使得转速控制达到想要的精度。
试凑法:
注意这里参数调节采用实验
凑试法,试凑法也有其规律,下面
做出讲解:
实验凑试法是通过闭环运行或模拟,
观察系统的输出结果,
然后根据各参
数对系统的影响,反复凑
试参数,直至出现满意的响应,从而确定
PID
控制
参数。
实验凑试法
的整定步骤为
先比例,再积分,最后微分
。
(
1<
/p>
)整定比例控制
将比例控制作用由小变到大,观察各次响应,直至得到反应快、超调小
的响应曲
线。
(
2
)
整定积分环节
若在比例控制下稳态误差不能满足要求,需加入积分控制。
先将步骤(
1
< br>)中选择的比例系数减小为原来的
50
~
80
%,再将积分时间
置一个较大值,观测响应曲线。
然后减小积分时间,加大积分作用,并相应
调整比例系数,反复试凑至得到较满意的响应
,确定比例和积分的参数。
(
3
p>
)整定微分环节
< br>若经过步骤
(
2
)
,
PI
控制只能消除稳态误差,
而动态过程不能令人满意,
则应加入微分控制,构成
PID
控制。
先置微分时间
TD=0
,
逐渐加大<
/p>
TD
,
同时相应地改变比例系数和积分时
间,
反复试凑至获得满意的控制效果和
PID
< br>控制参数。
代码实现
unsigned int
Proportion=8;//
比例常数
Proportional Const
unsigned int
Integral=3;//
积分常数
Integral
Const
unsigned int
Derivative=1;//
微分常数
Derivative Const
unsigned int
LastError=0;//Error[-1]
unsigned int
PrevError=0;//Error[-2]
unsigned int
Error=0;//Error[0]
int
Out=0;//outcome
int
contr_PID()
{
Error=expc_speed-
real_speed;//
计算偏差
//
进行增量式
PID
p>
计算
Out=Out+
Proportion*(Error-LastError)+
Integral*Error+
Derivative*(Error+PrevError-2*
LastError);
//
进行误差更新
PrevError=LastError;
LastError=Error;
//
上下限幅处理
if(Out<0)
Out=0;//
驱动电机的电压不可能小于零,故当输出小于零时,输出应该
值为零
if(Out>255)
Out=255;/
/DA
转换为
8
位,最大数值为
255
,故当大于
255
时,限制为
255
return Out;
}
3.
电机驱动:
原理:
直流有刷电机既可以用
模拟电压驱动
,又可以用
PWM
驱动
.
p>
如果用
PWM
驱
动
时,
刚刚
PID
后的输出可以直接对应
到
PWM
高电平持续的时间,
PWM<
/p>
周期为
T
,
则低
电平对应为
T-Out
即可,
这个实现
比较简单。
这里介绍利用
DA
将数字量
Out
转化为模拟电压驱动电机的方法。
模拟电压驱动实现:
将数字量转化为模拟量的最常用方法就
是使用
DA
转换。在
一般的使用中我比
较喜欢的一款芯片是
PCF8591
。它内部集成了
4
路
8
位
AD
转换
和
1
路
8
位
DA
< br>转换,与单片机之间使用
IIC
通信方式。由于
IIC
通信只需要
SDA
和
SCL
两根信号线,因此很省
IO
口,并且一个芯片
AD
,
DA
都有了,很方便。具
体的
PCF8591
资料请参考其
datasheet
,
这里直接给出其封装好的
IIC
通信代码,
使用直接就可以了。
这里面其他的函数不用
管,
因为它们最终在两个函数中被调
用,即
write_add()
和
read_add()
中。前者实现
DA
转换,有两个参数,第一个<
/p>
参数是控制
DA
转换对应寄存器地址,<
/p>
取
0x40
,
第
二个是要转换的数据,即返回
的
OUT
,使用时直接一句代码:
write_add(0x40,OUT)
就能将数字信号转换为模
拟电压信号。后者实现
AD
转换,只有一个参数,就是选择
AD
转换的<
/p>
4
个通道,
通过宏定义可以定义出其四个
通道:
#define AD_IN0 0x40
#define AD_IN1 0x41
#define
AD_IN2 0x42
#define AD_IN3 0x43
使用时只需要一句代码:
dat=read_add(AD_IN2)
p>
就能实现将第二个通道的模拟信
号转换为数字信号。
代码实现:
//PCF8591.h
#define uchar unsigned
char
//
延时
< br>4us
void delay(void);
//iic
初始化
void init(void);
// iic
开始信号
void start(void)
// iic
停止信号
void stop(void)
// iic
应答
相当于一个智能的延时函数
void
respons(void)
//
iic
读一个字节数据
uchar
read_byte(void)
//iic
写一字节数据
void write_byte(uchar date)
;
//
控制
DA
转换
void write_add(uchar
control,uchar date);
//
控制
AD
转换
uchar read_add(uchar
control)
//PCF8591.c
#include
#include
#define
PCF8591 0x90
//
默认为写,如果为读,则为
0x91
sbit SDA=P2^0;
sbit SCL=P2^1;
//
延时
4us
void delay(void)
{
unsigned
char i;
for(i=1;i>0;i--);
}
//
iic
初始化
void init()
{
SDA=1;
delay();
SCL=1;
delay();
}
//
iic
开始信号
void
start()
{
SDA=1;
delay();
SCL=1;
delay();
SDA=0;
delay();
}
// iic
停止信号
-
-
-
-
-
-
-
-
-
上一篇:新托福TPO19阅读原文及译文(一)
下一篇:用51单片机做小车的控制