936焊台用AVR模糊PID恒温控制,图
搞了个焊台自己用放大用LM324比较差··不过温度还是可以稳定,用M8 AD10位 pwm10位温度范围为200-500精确度1度··
因为程序的原因加上要慢慢整定所以每次升温到设定值前15度就开始整定··
有个缺点就是PID控制恒温时的那几度温度升的很慢··
设置部分还没写好
自己的思路是直接用那个可变电阻做设置
AD转换采样可变电阻来设定温度
设置一按键为温度设定
当按了那按键后可变电阻设定温度有效
没按的话不管你怎么转都不能调节温度
那部分写完后整个代码,发出来大家一起参考
发觉问题还很多的。。希望大家多提下意见,小弟初学的
还有如果要改的话可以不改那电路的引一条采样跟控制线出来直接连上M8也可以的
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_287927.jpg
(原文件名:12.jpg)
点击此处下载 ourdev_288542.txt(文件大小:8K) (原文件名:936.txt)
这是源代码
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_288523.jpg
(原文件名:2.jpg)
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_288524.jpg
(原文件名:3.jpg) 是用可控硅做开关控制的,还是用MOS管的。
我的936坏了 都扔家里好长时间了
有详细的自制资料吗 我程序还没写完··设定温度的还没写··以后吧··到时我全部整理下 原先的应该是双向可控硅吧? 标记下。 【1楼】 lanshuitianxia
是双向可控硅,片子资料明天传上
你用万用表量一下,如果电阻很小,判定他坏
还有那个1701也可能坏 不敢苟同,电路滤波不好,还有,运放越多,波形越不好,不过,好在你的电路要求不高 程序用查表做PID模糊的方法不错,不过要调整表格,得比较麻烦 记号 PID调整速度慢的话可以适当加大比例系数吧。 标记 标记 观注,看看PID到底怎么摆弄。 关切中,我也想改造我936。 程序用查表做PID模糊的方法不错,不过要调整表格,得比较麻烦
9楼的兄弟
你仔细看下程序
我是用宏指令的
所以要调表格还是比较容易的
#define NB -3
#define NM -2
#define NS -1
#define ZO 0
#define PS 1
#define PM 2
#define PB 3 不敢苟同,电路滤波不好,还有,运放越多,波形越不好,不过,好在你的电路要求不高
8楼你说对了··用LM324精度很差的·用差动放大是为了做一点点温度补偿。他之前的电路就用了一个放大器放大·但是对于这焊台已经够了
本来可以用LCL7650+OP07但我没那IC,加上他本来就是用LM324的所以就图个方便了
不过你想做好点的话可以用MAX6675的集放大 AD转换
温度补偿一体··价格好像要30多 const unsigned char seg_table={0x40,0x79,0x24,0x30,0x19,0x90,0x80,0x78,0x00,0x10,0x08,0x81,0x44,0x21,0x04,0x8c};
---------------------------------
这个表如何算得? 楼主用什么测温度的? 16楼的兄弟,可能你没有完全理解我的意思了,我在9楼说的是调整表格比较麻烦,不是说你修改麻烦,而是说要得出比较准确的表格得做很多实验才能得出好的表!,当然你那个实验要求不高,所以表格应该好做点,因为,你的实验对象是固定了的。 模糊控制,难点就难在做表格,这是我个人觉得的。也是花的时间最多的一个地方。不一定是对的哦,呵呵 关注,.. 我一直都想做一个,可惜一直都没有找到那个传感器的资料 看了源程序,似乎有许多错误。
怀疑这个程序无法正常工作。起码无法控制住温度。 温度传感器是哪个型号?? 24喽你说程序有点问题?你先调试看下吧!反正我自己就是这样用的。有很多我没删我是直接用/**/把其他没用的都屏蔽掉了的··目的是我这样就能知道我以前写的程序是什么··也算是做笔记吧。。
至于采样可能不大准确··但是实际上还是能用的?你自己试试吧··
25喽这是用热电偶··本想用MAX6675但是用了话要重新写程序了·· const unsigned char seg_table={0x40,0x79,0x24,0x30,0x19,0x90,0x80,0x78,0x00,0x10,0x08,0x81,0x44,0x21,0x04,0x8c};
---------------------------------
这个表如何算得?
18楼
没办法啊··本来B段是接PB1的但是PB1要用作PWM
没办法就只能把B段改接PB7喽
结果就要改段码表··
怎么算?用电脑自带的计算器算啊 怪了,烙铁的发热丝一般都是交流供电的,楼主用PWM控制双向可控硅,控制得了吗?
可控硅导通后,即使关掉触发端,也不关不了哇,要等到过零才能关 jihao 那个我不大清楚了··我也很菜的·那个是可控硅,但是它是用三级管控制可控硅的··而那三级管是高电平就导通低电平就关吧··具体我也没去看··反正能用·是它本身带的 top 点击此处下载 ourdev_292594.txt(文件大小:9K) (原文件名:936.txt)
今天随便写了下··
INT0就设置温度,按一下进入设置,按第2就退出。。
ADC1就采集温度设置那个大可调电阻就是调温度的·温度保存还没弄打算EEPROM保存 记号....... 有没有温度采样值/曲线? 你要采样曲线?有热电偶软件··热电偶对照软件点击此处下载 ourdev_292672.rar(文件大小:218K) (原文件名:热电偶.热电阻对照查询程序V1.0.exe(226.rar) C51实现PID算法
关于PID的算法实现,很多书上都讲了。
但是,最近真正要用PID算法的时候,发现书上的代码在我们51上来实现还不是那么容易的事情。简单的说来,就是不能直接调用。仔细分析你可以发现,教材上的、网上现行的PID实现的C语言代码几乎都是用浮点型的数据来做的,可以想象,如果我们的计算使用浮点数据,那我们的51单片机来运行的话会有多痛苦。
所以,本人自己琢磨着弄了一个整型变量来实现了PID算法,由于是用整型数来做的,所以也不是很精确,但是对于很多的使用场合,这个精度也够了。关于系数和采样电压全部是放大10倍处理的。所以精度不是很高,但是也不是那么低,大部分的场合都够用了。实在觉得精度不够,可以再放大10倍或者100倍处理,但是要注意不超出整个数据类型的范围就可以了。
本人做的是带死区控制的PID算法。
具体的参考代码参见下面:
显示被隐藏内容
typedef struct PIDValue
{
uint32 Ek_Uint32; //差值保存,给定和反馈的差值
uint8 EkFlag_Uint8; //符号,1则对应的Ek为负数,0为对应的Ek为正数
uint8 KP_Uint8;
uint8 KI_Uint8;
uint8 KD_Uint8;
uint8 B_Uint8; //死区电压
uint8 KP; //显示修改的时候用
uint8 KI; //
uint8 KD; //
uint8 B; //
uint16 Uk_Uint16; //上一时刻的控制电压
}PIDValueStr;
PIDValueStr xdata PID;
/*******************************
**PID = Uk + (KP*E(k) - KI*E(k-1) + KD*E(k-2));
********************************/
void PIDProcess(void)
{
uint32 idata Temp; //
uint32 idata PostSum; //正数和
uint32 idata NegSum; //负数和
Temp = 0;
Temp = 0;
Temp = 0;
PostSum = 0;
NegSum = 0;
if( ADPool.Value_Uint16 > ADPool.Value_Uint16 ) //给定大于反馈,则EK为正数
{
Temp = ADPool.Value_Uint16 - ADPool.Value_Uint16; //计算Ek
if( Temp > PID.B_Uint8 )
{
//数值移位
PID.Ek_Uint32 = PID.Ek_Uint32;
PID.Ek_Uint32 = PID.Ek_Uint32;
PID.Ek_Uint32 = Temp;
//符号移位
PID.EkFlag_Uint8 = PID.EkFlag_Uint8;
PID.EkFlag_Uint8 = PID.EkFlag_Uint8;
PID.EkFlag_Uint8 = 0; //当前EK为正数
Temp = (uint32)PID.KP_Uint8 * PID.Ek_Uint32; // KP*EK0
Temp = (uint32)PID.KI_Uint8 * PID.Ek_Uint32; // KI*EK1
Temp = (uint32)PID.KD_Uint8 * PID.Ek_Uint32; // KD*EK2
}
}
else //反馈大于给定
{
Temp = ADPool.Value_Uint16 - ADPool.Value_Uint16; //计算Ek
if( Temp > PID.B_Uint8 )
{
//数值移位
PID.Ek_Uint32 = PID.Ek_Uint32;
PID.Ek_Uint32 = PID.Ek_Uint32;
PID.Ek_Uint32 = Temp;
//符号移位
PID.EkFlag_Uint8 = PID.EkFlag_Uint8;
PID.EkFlag_Uint8 = PID.EkFlag_Uint8;
PID.EkFlag_Uint8 = 1; //当前EK为负数
Temp = (uint32)PID.KP_Uint8 * PID.Ek_Uint32; // KP*EK0
Temp = (uint32)PID.KI_Uint8 * PID.Ek_Uint32; // KI*EK1
Temp = (uint32)PID.KD_Uint8 * PID.Ek_Uint32; // KD*EK2
}
}
/*以下部分代码是讲所有的正数项叠加,负数项叠加*/
if(PID.EkFlag_Uint8==0)
{
PostSum += Temp; //正数和
}
else
{
NegSum += Temp; //负数和
} // KP*EK0
if(PID.EkFlag_Uint8!=0)
{
PostSum += Temp; //正数和
}
else
{
NegSum += Temp; //负数和
} // - kI * EK1
if(PID.EkFlag_Uint8==0)
{
PostSum += Temp; //正数和
}
else
{
NegSum += Temp; //负数和
} // KD * EK2
PostSum += (uint32)PID.Uk_Uint16; //
if( PostSum > NegSum ) // 是否控制量为正数
{
Temp = PostSum - NegSum;
if( Temp < (uint32)ADPool.Value_Uint16 ) //小于限幅值则为计算值输出
{
PID.Uk_Uint16 = (uint16)Temp;
}
else
{
PID.Uk_Uint16 = ADPool.Value_Uint16; //否则为限幅值输出
}
}
else //控制量输出为负数,则输出0
{
PID.Uk_Uint16 = 0;
}
}
///
Option Explicit
Dim EK1 As Single, EK2 As Single
Dim U As Single
Dim Uk As Single, Uk1 As Single, A As Single, B As Single, C As
Single, Ek As Single
Dim Ti As Integer, Td As Integer, Kp As Integer
Dim SP As Single, PV As Single
Private Sub Timer1_Timer()
Ti = Val(Text1) '读取积分时间值
Td = Val(Text2) '读取微分时间值
Kp = Val(Text3) '读取比例值
SP = Val(Text4) '设定值
Text5.Text = Slider1.Value
PV = Val(Text5) '模拟的反馈值
If Ti = 0 Then
A = Kp * (1 + Td)
Else
A = Kp * (1 + 1 / Ti + Td)
End If
B = Kp * (1 + 2 * Td)
C = Kp * Td
Ek = SP - PV
Uk = Uk1 + A * Ek - B * EK1 + C * EK2
If Int(Uk) <= 0 Then Uk = 0 '对输出进行调理,实际使用时灵活掌握。
If Int(Uk) > 1000 Then Uk = 1000
Uk1 = Uk
EK2 = EK1
EK1 = Ek
Text6.Text = Uk '输出显示
End Sub 点击此处下载 ourdev_292673.zip(文件大小:194K) (原文件名:PID算法演示程序.zip)
点击此处下载 ourdev_292674.pdf(文件大小:569K) (原文件名:基本PID控制.pdf)
点击此处下载 ourdev_292675.rar(文件大小:141K) (原文件名:基于模糊规则的非线性系统建模方法 [文档在线提供].rar)
点击此处下载 ourdev_292676.PDF(文件大小:103K) (原文件名:一种基于Fuzzy_PID的参数自整定恒温控制系统.PDF)
点击此处下载 ourdev_292677.rar(文件大小:362K) (原文件名:一个温控PID调节的程序.rar)
点击此处下载 ourdev_292678.doc(文件大小:42K) (原文件名:数字pid控制.doc)
点击此处下载 ourdev_292679.rar(文件大小:383K) (原文件名:数字 PID及其改进算法.rar) PID算法解析2007-08-17 17:59 在过程控制中,按偏差的比例(P)、积分(I)和微分(D)进行控制的PID控制器(亦称PID调节器)是应用最为广泛的一种自动控制器。它具有原理简单,易于实现,适用面广,控制参数相互独立,参数的选定比较简单等优点;而且在理论上可以证明,对于过程控制的典型对象──“一阶滞后+纯滞后”与“二阶滞后+纯滞后”的控制对象,PID控制器是一种最优控制。PID调节规律是连续系统动态品质校正的一种有效方法,它的参数整定方式简便,结构改变灵活(PI、PD、…)。
参数的选择:
①比例系数P对系统性能的影响:比例系数加大,使系统的动作灵敏,速度加快,稳态误差减小;P偏大,振荡次数加多,调节时间加长;P太大时,系统会趋于不稳定;P太小,又会使系统的动作缓慢。P可以选负数,这主要是由执行机构、传感器以及控制对象的特性决定的。如果P的符号选择不当对象测量值就会离控制目标的设定值越来越远,如果出现这样的情况P的符号就一定要取反。同时要注意的是,力控的策略控制器的PID控制块的P参数是PID控制中的增益。
②积分控制I对系统性能的影响:积分作用使系统的稳定性下降,I小(积分作用强)会使系统不稳定,但能消除稳态误差,提高系统的控制精度。
③微分控制D对系统性能的影响:微分作用可以改善动态特性,D偏大时,超调量较大,调节时间较短;D偏小时,超调量也较大,调节时间也较长;只有D合适,才能使超调量较小,减短调节时间。
比例(P)控制
比例控制是一种最简单的控制方式。其控制器的输出与输入误差信号成比例关系。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
积分(I)控制
在积分控制中,控制器的输出与输入误差信号的积分成正比关系。对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
微分(D)控制
在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。 自动控制系统在克服误差的调节过程中可能会 出现振荡甚至失稳。其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。这就是说,在控制器中仅引入“比例”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在调节过程中的动态特性。
5、PID控制器的参数整定
PID控制器的参数整定是控制系统设计的核心内容。它是根据被控过程的特性确定PID控制器的比例系数、积分时间和微分时间的大小。PID控制器参数整定的方法很多,概括起来有两大类:一是理论计算整定法。它主要是依据系统的数学模型,经过理论计算确定控制器参数。这种方法所得到的计算数据未必可以直接用,还必须通过工程实际进行调整和修改。二是工程整定方法,它主要依赖工程经验,直接在控制系统的试验中进行,且方法简单、易于掌握,在工程实际中被广泛采用。PID控制器参数的工程整定方法,主要有临界比例法、反应曲线法和衰减法。三种方法各有其特点,其共同点都是通过试验,然后按照工程经验公式对控制器参数进行整定。但无论采用哪一种方法所得到的控制器参数,都需要在实际运行中进行最后调整与完善。现在一般采用的是临界比例法。利用该方法进行PID控制器参数的整定步骤如下:(1)首先预选择一个足够短的采样周期让系统工作;(2)仅加入比例控制环节,直到系统对输入的阶跃响应出现临界振荡 <-- adcode -->
,记下这时的比例放大系数和临界振荡周期;(3)在一定的控制度下通过公式计算得到PID控制器的参数。
PID参数的设定:是靠经验及工艺的熟悉,参考测量值跟踪与设定值曲线,从而调整P\I\D的大小。
PID控制器参数的工程整定,各种调节系统中P.I.D参数经验数据以下可参照:
温度T: P=20~60%,T=180~600s,D=3-180s
压力P: P=30~70%,T=24~180s,
液位L: P=20~80%,T=60~300s,
流量L: P=40~100%,T=6~60s。
书上的常用口诀:
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再把微分加
曲线振荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢。微分时间应加长
理想曲线两个波,前高后低4比1
一看二调多分析,调节质量不会低 比较典型的PID算法控制程序源代码|
日期:2007-08-26 点击: 94 作者: 来源: 字体:[ 大 中 小 ]
比较典型的PID处理程序
来源:21ICbbs作者:lookuper
/*====================================================================================================这是一个比较典型的PID处理程序,在使用单片机作为控制cpu时,请稍作简化,具体的PID参数必须由具体对象通过实验确定。由于单片机的处理速度和ram资源的限制,一般不采用浮点数运算,而将所有参数全部用整数,运算
到最后再除以一个2的N次方数据(相当于移位),作类似定点数运算,可大大提高运算速度,根据控制精度的不同要求,当精度要求很高时,注意保留移位引起的“余数”,做好余数补偿。这个程序只是一般常用pid算法的基本架构,没有包含输入输出处理部分。
=====================================================================================================*/
#include
#include
/*====================================================================================================
PIDFunction
ThePID(比例、积分、微分)functionisusedinmainly
controlapplications.PIDCalcperformsoneiterationofthePID
algorithm.
WhilethePIDfunctionworks,mainisjustadummyprogramshowing
atypicalusage.
=====================================================================================================*/
typedefstructPID{
doubleSetPoint;//设定目标Desired
doubleProportion;//比例常数ProportionalConst
doubleIntegral;//积分常数IntegralConst
doubleDerivative;//微分常数DerivativeConst
doubleLastError;//Error[-1]
doublePrevError;//Error[-2]
doubleSumError;//SumsofErrors
}PID;
/*====================================================================================================
PID计算部分
=====================================================================================================*/
doublePIDCalc(PID*pp,doubleNextPoint)
{
doubledError,
Error;
Error=pp->SetPoint-NextPoint;//偏差
pp->SumError=Error;//积分
dError=pp->LastError-pp->PrevError;//当前微分
pp->PrevError=pp->LastError;
pp->LastError=Error;
return(pp->Proportion*Error//比例项
pp->Integral*pp->SumError//积分项
pp->Derivative*dError//微分项
);
}
/*====================================================================================================
InitializePIDStructure
=====================================================================================================*/
voidPIDInit(PID*pp)
{
memset(pp,0,sizeof(PID));
}
/*====================================================================================================
MainProgram
=====================================================================================================*
doublesensor(void)//DummySensorFunction
{
return100.0;
}
voidactuator(doublerDelta)//DummyActuatorFunction
{}
voidmain(void)
{
PIDsPID;//PIDControlStructure
doublerOut;//PIDResponse(Output)
doublerIn;//PIDFeedback(Input)
PIDInit(&sPID);//InitializeStructure
sPID.Proportion=0.5;//SetPIDCoefficients
sPID.Integral=0.5;
sPID.Derivative=0.0;
sPID.SetPoint=100.0;//SetPIDSetpoint
for(;;){//MockUpofPIDProcessing
rIn=sensor();//ReadInput
rOut=PIDCalc(&sPID,rIn);//PerformPIDInteration
actuator(rOut);//EffectNeededChanges
} 单片机模糊PID自整定控制算法的实现及仿真2008年01月04日 星期五 下午 05:13
单片机模糊PID自整定控制算法的实现及仿真
引言
由于液压伺服系统的固有特性(如死区、泄漏、阻尼系数的时变性以及负载干扰的存在),系统往往会呈现典型的不确定性和非线性特性。这类系统一般 很难精确描述控制对象的传递函数或状态方程,而常规的PID控制又难以取得良好的控制效果。另外,单一的模糊控制虽不需要精确的数学模型,但是却极易在平 衡点附近产生小振幅振荡,从而使整个控制系统不能拥有良好的动态品质。
本文针对这两种控制的优缺点并结合模糊控制技术,探讨了液压伺服系统的模糊自整定PID控制方法,同时利用MATLAB软件提供的 Simulink和Fuzzy工具箱对液压伺服调节系统的模糊自整定PID控制系统进行仿真,并与常规PID控制进行 了比较。此外,本文还尝试将控制系统通过单片机的数字化处理,并在电液伺服实验台上进行了测试,测试证明:该方法能使系统的结构简单化,操作灵活化,并可 增强可靠性和适应性,提高控制精度和鲁棒性,特别容易实现非线性化控制。
1 模糊PID自整定控制器的设计
本控制系统主要完成数据采集、速度显示和速度控制等功能。其中智能模糊控制由单片机完成,并采用规则自整定PID控制算法进行过程控制。整个系 统的核心是模糊控制器,AT89C51单片机是控制器的主体模块。电液伺服系统输出的速度信号经传感器和A/D转换之后进入单片机,单片机则根据输入的各 种命令,并通过模糊控制算法计算控制量,然后将输出信号通过D/A转换送给液压伺服系统,从而控制系统的速度。该模糊控制器的硬件框图如图1所示。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292680.png
(原文件名:1.png)
模糊控制器的主程序包括初始化、键盘管理及控制模块和显示模块的调用等。温度信号的采集、标度变换、控制算法以及速度显示等功能的实现可由各子 程序完成。软件的主要流程是:利用AT89C51单片机调A/D转换、标度转换模块以得到速度的反馈信号,然后根据偏差和偏差的变化率计算输入量,再由模 糊PID自整定控制算法得出输出控制量。启动、停止可通过键盘并利用外部中断产生,有按键输入则调用中断服务程序。该程序的流程图如图2所示。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292681.png
(原文件名:2.png)
2 模糊控制器算法研究
采用模糊PID自整定控制的目的是使控制器能够根据实际情况调整比例系数Kp、积分系数Ki和微分系数Kd,以达到调节作用的实时最优。该电液伺服系统的Fuzzy自整定PID控制系统结构如图3所示。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292682.png
(原文件名:3.png)
为了简化运算和满足实时性要求,即该调节系统的基本控制仍为PID控制,但使PID调节参数由模糊自整定控制器根据偏差e和偏差变化率ec进行自动调整,同时把模糊自整定控制器的模糊部分按Kp、Ki和Kd分成3部分,分别由相应的子推理器来实现。
2.1 输入值的模糊化
模糊自整定PID控制器是在fuzzy集的论域中进行讨论和计算的,因而首先要将输入变量变换到相应的论域,并将输人数据转换成合适的语言值, 也就是要对输入量进行模糊化。结合本液压伺服系统的特性,这里选择模糊变量的模糊集隶属函数为正态分布,具体分布如图4所示。根据该规则可把实际误差e、 误差变化率ec(de/dt)对应的语言变量E、EC表示成模糊量。E、EC的基本论域为[-6,+6],将其离散成13个等级即[-6,-5,-4,- 3,-2,-1,0,+1,+2,+3,+4,+5,+6]。考虑到控制的精度要求,本设计将[-6,+6]分为负大、负中、负小 、零、正小、正中、正大等7个语言变量,然后由e、ec隶属函数根据最大值法得出相应的模糊变量。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292683.png
(原文件名:4.png)
2.2 模糊控制规则表的建立
(1) Kp控制规则设计
在PID控制器中,Kp值的选取决定于系统的响应速度。增大Kp能提高响应速度,减小稳态误差;但是,Kp值过大会产生较大的超调,甚至使系统 不稳定减小Kp可以减小超调,提高稳定性,但Kp过小会减慢响应速度,延长调节时间。因此,调节初期应适当取较大的Kp值以提高响应速度,而在调节中期, Kp则取较小值,以使系统具有较小的超调并保证一定的响应速度;而在调节过程后期再将Kp值调到较大值来减小静差,提高控制精度。Kp的控制规则如表1所 列。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292684.png
(原文件名:5.png)
(2) Ki控制规则设计
在系统控制中,积分控制主要是用来消除系统的稳态误差。由于某些原因(如饱和非线性等),积分过程有可能在调节过程的初期产生积分饱和,从而引 起调节过程的较大超调。因此,在调节过程的初期,为防止积分饱和,其积分作用应当弱一些,甚至可以取零;而在调节中期,为了避免影响稳定性,其积分作用应 该比较适中;最后在过程的后期,则应增强积分作用,以减小调节静差。依据以上分析,制定的Ki控制规则表如表2所列。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292685.png
(原文件名:6.png)
(3) Kd控制规则设计
微分环节的调整主要是针对大惯性过程引入的,微分环节系数的作用在于改变系统的动态特性。系统的微分环节系数能反映信号变化的趋势,并能在偏差 信号变化太大之前,在系统中引入一个有效的早期修正信号,从而加快响应速度,减少调整时间,消除振荡.最终改变系统的动态性能。因此,Kd值的选取对调节 动态特性影响很大。Kd值过大,调节过程制动就会超前,致使调节时间过长;Kd值过小,调节过程制动就会落后,从而导致超调增加。根据实际过程经验,在调 节初期,应加大微分作用,这样可得到较小甚至避免超调;而在中期,由于调节特性对Kd值的变化比较敏感,因此,Kd值应适当小一些并应保持固定不变;然后 在调节后期,Kd值应减小,以减小被控过程的制动作用,进而补偿在调节过程初期由于Kd值较大所造成的调节过程的时间延长。依据以上分析,制定的Kd控制 规则表如表3所列。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292686.png
(原文件名:7.png)
2.3 逆模糊化处理及输出量的计算
对经过模糊控制规则表求得的Kp、Ki、Kd采用重心法进行逆模糊化处理(重心法在此就不做详细介绍)的公式如下:
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292687.png
(原文件名:8.png)
式中,u(k)为k采样周期时的输出,e(k)为k采样周期时的偏差,T为采样周期,通过输出u(k)乘以相应的比例因子Ku就可得出精确的输出量u。其公式如下:
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292688.png
(原文件名:9.png)
3 实验结果分析
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292689.png
(原文件名:10.png)
常规PID控制时通过调节 PID三个参数,就可以得到系统比较理想的响应图,控制效果的优良与参数的调整有很大的关系,也能提高快速性。但三个参数的调整非常繁琐。而且,如果系统 环境不断变化,则参数又必须进行重新调整,往往达不到最优。而采用模糊PID控制后,通过模糊控制器对PID进行非线性的参数整定,可使系统无论是快速性 方面还是稳定性方面都达到比较好的效果。
笔者将上述PID控制及模糊PID控制分别进行了仿真试验,实验分别在单独模糊PID控制情况下和模糊PID控制两种情况下进行。并在在线运 行过程中通过逻辑规则的结果处理、查表和运算完成了对PID参数的在线自矫正。系统的偏差绝对值以及偏差的变化绝对值的取值范围可根据实际经验分别确定为 [-0.1 cm/s,0.1 cm/s】和[-0.06 cm/s2,0.06 cm/s2],以而确定相对控制效果较好时Kp、Ki、Kd的取值范围为Kp[-0.3,0.3]、Ki[-0.06,0.06]、Kd[-3,3]。
传统PID和模糊PID实验所得的曲线分别如图5及图6所示。从图中可以发现,采用模糊控制策略整定PID参数相对于普通PID控制策略,其系统的稳态性得到了较大的改善,响应时间大大减少,超调量也得到了一定的改善。
4 结束语
实验证明:该单片机模糊PID自整定控制器对于电液伺服控制系统具有较好的效果。实践中可以根据工程控制的具体情况及对超调量、稳定性、响应速度的不同要求,来调整模糊PID控制器三个参数的取值范围,从而得到不同的控制精度和控制效果。
总之,本文研究的模糊PID控制器具有以下一些特点:
(1) 算法简单实用,本质上不依赖于系统的数字模型;
(2) 可充分利用单片机的软件资源,可靠性高,开发速度快;
(3) 克服了传统PID控制器操作的困难,提高了系统的智能化程度;
(4) 模糊PID控制器棒性好,具有专家控制器的特点,并可推广应用于其它工作领域。 记号 昨天去工具店看有焊台的手柄部份卖,看来可以自做一个带温度显的焊台! 不用买手柄··你买个936的··质量马马糊糊就行了·那东西关键是加热芯,哪天坏了··买个白光芯来,当初我买了60多··现在不用了吧
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292895.jpg
(原文件名:20080525105.jpg)
后面加了个ISP下载口,方便改程序
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_292896.jpg
(原文件名:20080525106.jpg) MARK 不错留念 很棒的工作! 网速不好,图都看不到,改天网速好了再来看
楼主PID玩得不错嘛,记得自动控制原理和计算机控制里讲过 先记号,以后再看 mark kankan 强烈要求站长发条裤子! 支持研究PID 支持研究PID 都是强人额。。。学习 楼主:你好,我有几个问题请教一下,你这边通过模糊规则表得到KP,KI,KD,那些都是模糊量,你怎么可以直接用增量公式计算UK的。
不断自增前一次的输出是什么意思?楼主请帮忙解答 这个搞得如何了,我正想改我的936,楼主完成了没有呀 上次那个很多缺陷·
改用普通PID吧!效果比以前好点点,
/*******************************
project :A/D转换数码管显示
chip type : atmega8
clock frequency:内部RC(INT) 8MHz
Author :周远峰
********************************/
#include "iom8v.h"
#include "macros.h"
#define osccal 0x7d
unsigned int adc_rel; //处理后世界转换结果
unsigned long adc_rl; //A/D转换结
unsigned int tmp; //设置的温度参数
unsigned char adc_mux; //A/D通道
unsigned int ww; //闪时间
unsigned int kk;
unsigned char k1; //显示
unsigned int k11;
unsigned char key1; //按键标志
unsigned char led_buff={0,0,0};//显示缓存
signed int error0; //当前偏差
signed int error1; //上次偏差
signed int error2; //上上次偏差
signed int Kp; //比例常数
signed int Ki; //积分常数
signed int Kd; //微分常数
signed int kk1; //当前控制输出
signed int kk2; //上次控制输出
#pragma data:code
//设置数据区位程序储存器
const unsigned char seg_table={0x40,0x79,0x24,0x30,0x19,0x90,0x80,0x78,0x00,0x10,0x08,0x81,0x44,0x21,0x04,0x8c,0xff};
#pragma data:data
//设置数据区回到数据储存器
/*********************************************************
延时函数
*********************************************************/
void delay_us(int time) //微秒级延时
{
do
time--;
while (time>1);
}
void delay_ms(unsigned int time)//毫秒级延时
{
while (time!=0)
{
delay_us(1000);
time--;
}
}
/************************************************************
中断显示初始化
TIMER2 initialize - prescale:1024
WGM: Normal
desired value: 10mSec
actual value:9.984mSec (0.2%)
*************************************************************/
void timer2_init(void)
{
TCCR2= 0x00; //stop
ASSR = 0x00; //set async mode
TCNT2= 0xB2; //setup
OCR2 = 0x4E;
TCCR2= 0x07; //start
DDRB = 0xff;//PC口为推挽1输出
PORTB= 0xff; //PC口内部上拉
DDRD|= 0xf0;
PORTD &= 0x1f;//关闭LED
}
/***********************************************
中断显示
*************************************************/
#pragma interrupt_handler timer2_ovf_isr:5
void timer2_ovf_isr(void)
{
unsigned char i;
TCNT2 = 0xB2; //reload counter value
if (k1==0)
{
for(i=0;i<3;i++)
{
PORTB= led_buff;
PORTD |= (1<<(i+5));//待显示的位置1
delay_ms(1);
PORTD &= 0x1f; //关闭LED
}
}
}
void shanshuo(void)
{
if(k11<ww)
{
k11++;
k1 = 0;
}
else
{
if (kk<ww)
{
kk++;
k1 = 1;
}
else
{
k11 = 0;
kk= 0;
}
}
}
//Watchdog initialize
// prescale: 2048K
void watchdog_init(void)
{
WDR (); //this prevents a timeout on enabling
WDTCR |= (1<<WDCE) | (1<<WDE);/* 30-Oct-2006 Umesh*/
WDTCR= 0x0F; //WATCHDOG ENABLED - dont forget to issue WDRs
}
/************************************************************
PWM初始化,OC1A口输出
*************************************************************/
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x00; //setup
OCR1A= 200;
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);//输出低电平
TCCR1B = (1<<CS11)|(1<<CS10); //
}
/*****************************************************
PID初始化
******************************************************/
void pidcalc_init(void)
{
Kp = 45;
Ki = 3;
Kd = 1;
kk1 = 0; //当前
kk2 = 0;
error0 = 0;
error1 = 0;
error2 = 0;
}
/*******************************************************
PID函数
********************************************************/
void pidcalc(void)
{
signed long KPP;
signed long KII;
signed long KDD;
signed int i;
signed char j;
if (key1==0) //设置温度时PID不工作
{
error0=tmp-adc_rel;
if (100<adc_rel) //比设定低一定值时开始PID
{
if((tmp+20)>adc_rel)
{
KPP =Kp*(error0-error1);
KII =Ki*error0;
KDD = Kd*(error0-(2*error1)+error2);
kk1 =KPP+KII+KDD+kk2;
if (kk1<0x3ef)
{
if (kk1>0) OCR1A=kk1;
else { OCR1A=0; }
}
else {OCR1A = 0x3ff;}
}
else {OCR1A = 0;}
}
else{OCR1A = 0x3ff;}
kk2=kk1;
error2 = error1;
error1 = error0;
}
else {}
}
/***********************************************
ADC初始化
************************************************/
void adc_init(void)
{
DDRC = 0;
PORTC = 0;
ADCSRA = 0;
ADMUX = (1<<REFS1)|(1<<REFS0)|(adc_mux&0x0f); //选择内部2.56V为基准AREF外加滤波电容
ACSR = (1<<ACD); //关闭模拟比较器
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//128分频
}
/*********************************************
ADC中断处理函数
**********************************************/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
static unsigned i;
adc_rl+=ADC&0x3ff;
ADMUX = (1<<REFS1)|(1<<REFS0)|(adc_mux&0x0f); //选择内部2.56V位基准
ADCSRA |= (1<<ADSC); //启动AD转换
if (i<1023)
i++;
else
{
adc_rel = adc_rl/1024;
adc_rel = adc_rel*3/5;
i=0;
adc_rl= 0;
}
}
/******************************************************
ADC数据转压缩BCD
******************************************************/
void ADCtoBCD(unsigned int temp)
{
unsigned char i;
for (i=0;i<3;i++)
{
led_buff=seg_table;/*temp%10求余数‘假设一个数是234那么234/10=23余4也就是查找4的段码*/
temp=temp/10;// 234/10=23因为不处理小数实际就等于右移了
}
}
/**************************************************************
温度设置
**************************************************************/
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
unsigned char i;
delay_ms(500);//external interupt on INT0
i=PIND&0x04;
if(i==0x04)
return;
else
{
if(key1==1)
{
tmp=adc_rel;
EEPROM_conwrite ();
adc_mux = 0;
key1 = 0;
k1 = 0;
ww = 0;
}
else
{
ww=600;
adc_mux = 1;
key1 = 1;
OCR1A = 0;
}
}
}
/********************************************************
子程序名: EEPROM_write
功 能: 写一字节数据到片内指定地址单元
输入参数: /
输出参数: /
描 述: /
********************************************************/
void EEPROM_write(unsigned int uAddr,unsigned char uData)
{
EEAR= uAddr; //写操作的16位地址寄存器
EEDR= uData; //写数据到数据寄存器
EECR |= (1<<EEMWE); //允许EEPROM操作
EECR |= (1<<EEWE); //开始写操作
while (EECR & (1<<EEWE)) //等待写操作完成
;
}
/********************************************************
子程序名: EEPROM_read
功 能: 从片内指定地址单元读一字节数据
输入参数: /
输出参数: /
描 述: /
********************************************************/
unsigned char EEPROM_read(unsigned int uAddr)
{
while (EECR & (1<<EEWE)) //等待前一次写操作完成
;
EEAR=uAddr; //写操作的16位地址寄存器
EECR |= (1<<EERE); //开始读操作
return EEDR; //输出读出的数据
}
/********************************************************
子程序名: EEPROM_conwrite
功 能: 写
输入参数: /
输出参数: /
描 述: /
********************************************************/
void EEPROM_conwrite (void)
{
unsigned char j,k;
unsigned int i;
i = tmp;
j = (unsigned char)i;
k = (unsigned char)(i>>8);
EEPROM_write (10,j);
EEPROM_write (11,k);
}
/********************************************************
子程序名: EEPROM_conread
功 能: 写
输入参数: /
输出参数: /
描 述: /
********************************************************/
void EEPROM_conread(void)
{
unsigned char j,k;
unsigned int i;
j=EEPROM_read (10);
k=EEPROM_read (11);
i= (unsigned int)j;
i |= (unsigned int)(k<<8);
tmp= i;
}
/********************************************************
子程序名: init_init
功 能: 初始化
输入参数: /
输出参数: /
描 述: /
********************************************************/
void init_init(void)
{
DDRD=0xff;
PORTD = 0xf0;
k1 = 0;
kk = 0;
adc_rel = 0;
OSCCAL= osccal;
adc_mux = 0;
tmp = 0;
TIMSK = 0x40; //timer interrupt sources
MCUCR = (1<<ISC01)|(1<<ISC00);
GICR = (1<<INT0);
}
/***************************************************************
主程序
***************************************************************/
void main(void)
{
unsigned int adc_old;
init_init();
EEPROM_conread();
watchdog_init();
adc_init();
timer1_init();
timer2_init();
pidcalc_init();
SEI();
adc_old=0;
while(1)
{
if(adc_old!=adc_rel)//ADC更新完毕就执行数据处理
{
adc_old=adc_rel;
pidcalc();
}
WDR ();
shanshuo();
ADCtoBCD(adc_old);
}
} jh 楼主有没有做好的板子,想买一块,改我的焊台。 现在的版本稳定吗?
我也想改我的焊台. 很稳定了!唯一不足的是运算放大有点误差了!软件方面没问题了!就前端放大,改时最好买温度补偿的运算放大。
59楼,没办法哦!我是直接在他本身的板上改的,没做好的板子 楼主能不能把你的这个资料(电路图和程序)整理一下呀,看了半天没有看到啥电路图呢,我准备也学你改造我的936来了,呵呵 to 【61楼】 153290557 周远峰
楼主给个建议,买什么运放代换好呢? 99se打开
点击此处下载 ourdev_312702.rar(文件大小:4K) (原文件名:936原理图.rar) 楼主能做一批成品出来吗,相信很多人都需要 mark. 支持一下 楼主辛苦了!
不知道这个PID用在我现在正在做的即热式电热水器项目效果如何呢? 原调温电路位器的电路要改动吗. 设置部分还没做吗? 改用OP07单运放三个.用正负5V电源供电,效果会否好点.要改程序吗. 顶LZ。 顶!!! 支持楼主 楼主,有没有考虑不用PID算法?PID算法在控制大滞后负载时效果并不是很理想。而大林算法是能很好的解决该问题。 好贴就顶! 很不错,值得研究! mark 楼主,调节温度应该用编码开关,更好。 请教楼主的模糊pid中
PID调节参数由模糊自整定控制器根据偏差e和偏差变化率ec进行自动调整,这个按什么规律得出的,程序中用这句实现的
i=7*(3+error0)+(3+j);
另外
输出u(k)乘以相应的比例因子Ku就可得出输出量u,这个Ku是通过大量实验得出来的吗,谢谢了 mark 不得不顶啊!好贴 顶,好贴 强烈建议作为开源项目,烙铁都用的着,有能好好搞搞PID..等控制 想搞个 AC/DC,M48主控 PWN,电流控制; 1602显示。 有没人有兴趣做?
硬件部分设计我完成。
软件部分就要懂 模糊控制 的朋友搞,
我也可以写但不会用模糊控制。 to: 153290557 周远峰
KDD = Kd*(error0-(2*error1)+error2);
kk1 =KPP+KII+KDD+kk2;
这些数值的计算结果,会不会产生溢出? 顶顶,我记得有开源焊台的分坛,看来也是因为攻击,没了
希望早日重建 楼主,好啊。我最近在做一个地暖温控器,里面用到pid控制,但是我对这个很不理解。你能教教我吗?我的qq41964409谢谢 有参考价格 mark 焊台布需要PID控制吧,pid 升温速度太慢了,用开环查表控制就ok啦,我做过一款高频的焊台,从0度升到350度 时间是5s
PID根本达不到这个时间要求。
还有一个问题想请教下各位:
最近发现市场上有一款焊台 加热和温度采样共两条线 ,一直想不明白他是咋接的 那个大哥知道说明下啊 。
在高焊台的,可以加我qq大家一起研究下。
目前本人一直在搞高频焊台这块 .. ###焊台布需要PID控制吧,pid 升温速度太慢了,用开环查表控制就ok啦,我做过一款高频的焊台,从0度升到350度 时间是5s
PID根本达不到这个时间要求。
还有一个问题想请教下各位:
最近发现市场上有一款焊台 加热和温度采样共两条线 ,一直想不明白他是咋接的 那个大哥知道说明下啊 。
在高焊台的,可以加我qq大家一起研究下。
目前本人一直在搞高频焊台这块 ######################################
直接在线测量烙铁发热丝的电阻,对应算出温度,直流烙铁好办,交流的不好办 期待着被amok开源
这个可是大家都能用的上的东东 ###焊台布需要PID控制吧,pid 升温速度太慢了,用开环查表控制就ok啦,我做过一款高频的焊台,从0度升到350度 时间是5s
PID根本达不到这个时间要求。
还有一个问题想请教下各位:
最近发现市场上有一款焊台 加热和温度采样共两条线 ,一直想不明白他是咋接的 那个大哥知道说明下啊 。
在高焊台的,可以加我qq大家一起研究下。
目前本人一直在搞高频焊台这块 ######################################
直接在线测量烙铁发热丝的电阻,对应算出温度,直流烙铁好办,交流的不好办
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
94楼的兄弟:我看了下 那个焊台是交流加热的,我估计他是打一时间差的方式来采集温度的。就是说加热的时候不采集。不加热的时候就采集温度。貌似双向线那样。
不过这样子,我就不知道硬件上咋处理较好,还是跟普通一样?运放处理,ad采样? 不知道这样会不会有交流干扰 因为不加热时间都很短的。
困惑中。。。。。 mark 两线的是串联热电偶。 MARK 我们用的焊台加温确实很快,照上面说的就不是PID 这是个好帖子,楼主不仅公布了成果,还整理了配套的资料,还引导了后面的价值很高的回复。
非常可惜,从2008-09-13,22:04:43 到 2009-02-20,00:23:13 之间有半年的回复帖子被黑掉了。不知道里面有多少经典的回复啊。