温度控制的PID算法的C语言程序

合集下载

温度控制的PID算法及C程序实现

温度控制的PID算法及C程序实现

本文档如对你有帮助,请帮忙下载支持!温度控制与PID 算法温度控制与PID 算法j 较为复杂,下面结合实际浅显易懂的阐述一下 PID 控制理论,将温度控制及PID 算法作一个简单的描述。

1.温度控制的框图asgstiB这是一个典型的闭环控制系统,用于控制加热温区的温度( PV )保持在恒定的温度 设定值(SV )。

系统通过温度采集单元反馈回来的实时温度信号( PV )获取偏差值(EV ),偏差值经过 PID 调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近 于零。

例如,当某一时刻炉内过PCB 板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。

其调节过程如下:温度控制的功率输出采用脉宽调制的方法。

固态继电器电压U ouT 。

当SSR 的触发角触发时,电源电压U AN 通过SSR 的输出端加到发热管的两 端;当SSR 的触发角没有触发信号时,SSR 关断。

因此,发热管两端的平均电压为U d = (t/T )* U AN =K* U AN其中K= t/T ,为一个周期T 中,SSR 触发导通的比率,称为负载电压系数或是占空比, K的变化率在0- 1之间。

一般是周期 T 固定不便,调节t,当t 在0-T 的范围内变化时, 发热管的电压即在 0- U AN 之间变化,这种调节方法称为定频调宽法。

下面将要描述的 PID调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K 。

甌汕血Ikinl 曲汀 備錢(哉0.1/ 1A『'、、A____ 5^50 工 /it TTVI PID 调节鼬 固憲继电器勻岌恿習 X ?n -Tr-Zn 4f t 沮LEV)*冲端出易度 A 崭1出功率SSR 的输出端为脉宽可调的2.温度控制的两个阶段本文档如对你有帮助,请帮忙下载支持! 本文档如对你有帮助,请帮忙下载支持!温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后, 并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后, 温区的温度仍然有一定程度的上升。

c语言pid算法

c语言pid算法

c语言pid算法PID(Proportional-Integral-Derivative)控制器是一种非常常见且有效的控制系统算法,主要用于调节一个过程或者系统的输出,使其尽可能接近期望的设定值。

PID控制器的名字来源于它的三个主要组成部分:比例(Proportional)、积分(Integral)和微分(Derivative)。

在C语言中,一个简单的PID控制器可以如下实现:c复制代码#include<stdio.h>typedef struct {double kp; // 比例系数double ki; // 积分系数double kd; // 微分系数double last_error; // 上一次的误差double integral; // 误差的积分} PIDController;double calculatePID(PIDController* pid, double setpoint, double actual_value, double dt) {double error = setpoint - actual_value;// Proportional termdouble pout = pid->kp * error;// Integral termpid->integral += error * dt;double iout = pid->ki * pid->integral;// Derivative termdouble derivative = (error - pid->last_error) / dt;double dout = pid->kd * derivative;// Save error for next timepid->last_error = error;// Return total outputreturn pout + iout + dout;}int main() {PIDController pid;pid.kp = 1.0;pid.ki = 0.1;pid.kd = 0.01;st_error = 0;pid.integral = 0;double setpoint = 100.0; // 目标值double actual_value = 0.0; // 实际值double dt = 0.1; // 时间间隔for (int i = 0; i < 100; i++) {double output = calculatePID(&pid, setpoint, actual_value, dt);actual_value += output * dt; // 更新实际值printf("Setpoint: %f, Actual Value: %f, Output: %f\n", setpoint, actual_value, output);}return0;}在这个示例中,我们定义了一个PIDController结构体,它包含了PID控制器的所有参数。

pid算法温度控制c语言程序

pid算法温度控制c语言程序

pid算法温度控制c语言程序PID算法是一种常用的温度控制算法,广泛应用于各种温度控制系统中。

在C语言中,我们可以通过编写程序来实现PID算法的温度控制功能。

我们需要了解PID算法的基本原理。

PID算法是通过对系统的反馈信号进行不断调整,使得系统的输出达到期望值。

PID算法由三个部分组成:比例控制、积分控制和微分控制。

比例控制根据反馈信号与期望值的差异来调整输出;积分控制根据反馈信号与期望值的累积差异来调整输出;微分控制根据反馈信号的变化率来调整输出。

在C语言中,我们可以使用变量来表示系统的输入、输出和期望值。

以下是一个简单的示例代码:```c#include <stdio.h>// 定义PID参数float Kp = 1.0; // 比例系数float Ki = 0.5; // 积分系数float Kd = 0.2; // 微分系数// 定义系统变量float setpoint = 25.0; // 期望值float input = 0.0; // 输入值float output = 0.0; // 输出值// 定义误差变量float error = 0.0; // 当前误差float last_error = 0.0; // 上一次误差float integral = 0.0; // 累积误差// PID算法函数float pid_algorithm(float setpoint, float input) {// 计算误差error = setpoint - input;// 计算比例控制float proportional = Kp * error;// 计算积分控制integral += error;float integral_control = Ki * integral;// 计算微分控制float derivative = Kd * (error - last_error); // 计算输出output = proportional + integral_control + derivative;// 更新误差last_error = error;return output;}int main(){// 模拟温度传感器的输入input = 23.5;// 调用PID算法函数output = pid_algorithm(setpoint, input);// 打印输出结果printf("Output: %.2f\n", output);return 0;}```在上述代码中,我们首先定义了PID算法的参数和系统变量。

PID控制C代码

PID控制C代码

PID控制当今的自动控制技术都是基于反馈的概念。

反馈理论的要素包括三个部分:测量、比较和执行。

测量关心的变量,与期望值相比较,用这个误差纠正调节控制系统的响应。

这个理论和应用自动控制的关键是,做出正确的测量和比较后,如何才能更好地纠正系统。

比例控制(P):比例控制是最常用的控制手段之一,比方说我们控制一个加热器的恒温100度,当开始加热时,离目标温度相差比较远,这时我们通常会加大加热,使温度快速上升,当温度超过100度时,我们则关闭输出,通常我们会使用这样一个函数e(t) = SP –y(t);u(t) = e(t)*PSP——设定值、e(t)——误差值、y(t)——反馈值、u(t)——输出值、P——比例系数滞后性不是很大的控制对象使用比例控制方式就可以满足控制要求,但很多被控对象中因为有滞后性。

也就是如果设定温度是200度,当采用比例方式控制时,如果P选择比较大,则会出现当温度达到200度输出为0后,温度仍然会止不住的向上爬升,比方说升至230度,当温度超过200度太多后又开始回落,尽管这时输出开始出力加热,但温度仍然会向下跌落一定的温度才会止跌回升,比方说降至170度,最后整个系统会稳定在一定的范围内进行振荡。

如果这个振荡的幅度是允许的比方说家用电器的控制,那则可以选用比例控制.比例积分控制(PI):积分的存在是针对比例控制要不就是有差值要不就是振荡的这种特点提出的改进,它常与比例一块进行控制,也就是PI控制。

其公式有很多种,但大多差别不大,标准公式如下:u(t) = Kp*e(t) + Ki∑e(t) +u0u(t)——输出、Kp——比例放大系数、Ki——积分放大系数、e(t)——误差、u0——控制量基准值(基础偏差)大家可以看到积分项是一个历史误差的累积值,如果光用比例控制时,我们知道要不就是达不到设定值要不就是振荡,在使用了积分项后就可以解决达不到设定值的静态误差问题,比方说一个控制中使用了PI控制后,如果存在静态误差,输出始终达不到设定值,这时积分项的误差累积值会越来越大,这个累积值乘上Ki后会在输出的比重中越占越多,使输出u(t)越来越大,最终达到消除静态误差的目的。

温度控制的PID算法与C程序实现

温度控制的PID算法与C程序实现

温度控制的PID算法与C程序实现PID (Proportional-Integral-Derivative) 是一种经典的反馈控制算法,被广泛应用于温度控制中。

在温度控制中,PID算法可以根据实际温度与设定温度之间的差异来调整控制器的输出,以达到稳定的温度控制。

下面将介绍PID算法的原理及其在C程序中的实现。

PID算法是通过对三个控制参数的不同组合调整,来实现对控制系统的精确控制。

这三个参数分别是比例项(P),积分项(I)和微分项(D)。

比例项(P)是根据实际温度与设定温度的差异计算出来的,并且与这个差异成比例。

比例项主要用于对系统的快速响应进行调整。

如果比例项过大,可能会导致系统产生震荡,如果比例项过小,则可能导致控制系统响应迟缓。

积分项(I)用于校正持续的误差,通过对误差的积分来进行控制系统的调整。

积分项主要用于对系统的稳定性进行调整。

如果积分项过大,可能会导致系统产生超调和振荡,如果积分项过小,则可能导致系统无法快速地消除误差。

微分项(D)用于预测系统未来变化的趋势,并根据这个趋势来进行控制系统的调整。

微分项主要用于对系统的响应速度进行调整。

如果微分项过大,可能会导致系统产生过度的抖动,如果微分项过小,则可能导致系统响应迟缓。

PID算法的输出是三个控制参数的加权和,即 control = P * error + I * integral + D * derivative。

其中,error为实际温度与设定温度的差异,integral为误差的累积和,derivative为误差的变化率。

下面是一个使用PID算法实现温度控制的C程序的示例:```c#include <stdio.h>//PID参数float Kp = 0.5;float Ki = 0.2;float Kd = 0.1;//温度设定值float setpoint = 50.0;//初始化float errorSum = 0;float lastError = 0;//计算PID控制量float calculateOutput(float currentTemperature) float error = setpoint - currentTemperature; errorSum += error;//计算PID控制量float proportional = Kp * error;float integral = Ki * errorSum;float derivative = Kd * (error - lastError);float output = proportional + integral + derivative; lastError = error;return output;int mai//模拟当前温度float currentTemperature = 40.0;//模拟控制循环while (1)//获取温度传感器读数// float currentTemperature = readTemperature(;//计算PID控制量float controlOutput = calculateOutput(currentTemperature); //执行控制动作,例如根据控制量控制加热器或冷却器// executeControlAction(controlOutput);//模拟温度变化currentTemperature += 0.5;//输出当前温度和控制量printf("Current temperature: %.2f, Control output: %.2f\n", currentTemperature, controlOutput);}return 0;```上述C程序中,首先定义了PID参数Kp、Ki和Kd,以及温度设定值setpoint。

PID控制C代码

PID控制C代码

PID控制当今的自动控制技术都是基于反馈的概念。

反馈理论的要素包括三个部分:测量、比较和执行。

测量关心的变量,与期望值相比较,用这个误差纠正调节控制系统的响应。

这个理论和应用自动控制的关键是,做出正确的测量和比较后,如何才能更好地纠正系统。

比例控制(P):比例控制是最常用的控制手段之一,比方说我们控制一个加热器的恒温100度,当开始加热时,离目标温度相差比较远,这时我们通常会加大加热,使温度快速上升,当温度超过100度时,我们则关闭输出,通常我们会使用这样一个函数e(t) = SP – y(t);u(t) = e(t)*PSP——设定值、e(t)——误差值、y(t)——反馈值、u(t)——输出值、P——比例系数滞后性不是很大的控制对象使用比例控制方式就可以满足控制要求,但很多被控对象中因为有滞后性。

也就是如果设定温度是200度,当采用比例方式控制时,如果P选择比较大,则会出现当温度达到200度输出为0后,温度仍然会止不住的向上爬升,比方说升至230度,当温度超过200度太多后又开始回落,尽管这时输出开始出力加热,但温度仍然会向下跌落一定的温度才会止跌回升,比方说降至170度,最后整个系统会稳定在一定的范围内进行振荡。

如果这个振荡的幅度是允许的比方说家用电器的控制,那则可以选用比例控制.比例积分控制(PI):积分的存在是针对比例控制要不就是有差值要不就是振荡的这种特点提出的改进,它常与比例一块进行控制,也就是PI控制。

其公式有很多种,但大多差别不大,标准公式如下:u(t) = Kp*e(t) + Ki∑e(t) +u0u(t)——输出、Kp——比例放大系数、Ki——积分放大系数、e(t)——误差、u0——控制量基准值(基础偏差)大家可以看到积分项是一个历史误差的累积值,如果光用比例控制时,我们知道要不就是达不到设定值要不就是振荡,在使用了积分项后就可以解决达不到设定值的静态误差问题,比方说一个控制中使用了PI控制后,如果存在静态误差,输出始终达不到设定值,这时积分项的误差累积值会越来越大,这个累积值乘上Ki后会在输出的比重中越占越多,使输出u(t)越来越大,最终达到消除静态误差的目的。

PID控制C代码

PID控制C代码

PID控制当今的自动控制技术都是基于反馈的概念。

反馈理论的要素包括三个部分:测量、比较和执行。

测量关心的变量,与期望值相比较,用这个误差纠正调节控制系统的响应。

这个理论和应用自动控制的关键是,做出正确的测量和比较后,如何才能更好地纠正系统。

比例控制(P):比例控制是最常用的控制手段之一,比方说我们控制一个加热器的恒温100度,当开始加热时,离目标温度相差比较远,这时我们通常会加大加热,使温度快速上升,当温度超过100度时,我们则关闭输出,通常我们会使用这样一个函数e(t)=SP —y(t);u(t)=e(t)*PSP设定值、e(t)――误差值、y(t)――反馈值、u(t)――输出值、P――比例系数滞后性不是很大的控制对象使用比例控制方式就可以满足控制要求,但很多被控对象中因为有滞后性。

也就是如果设定温度是200度,当采用比例方式控制时,如果P选择比较大,则会出现当温度达到200度输出为0后,温度仍然会止不住的向上爬升,比方说升至230度,当温度超过200度太多后又开始回落,尽管这时输出开始出力加热,但温度仍然会向下跌落一定的温度才会止跌回升,比方说降至170度,最后整个系统会稳定在一定的范围内进行振荡。

如果这个振荡的幅度是允许的比方说家用电器的控制,那则可以选用比例控制比例积分控制(PI):积分的存在是针对比例控制要不就是有差值要不就是振荡的这种特点提出的改进,它常与比例一块进行控制,也就是PI控制。

其公式有很多种,但大多差别不大,标准公式如下:u(t)=Kp*e(t)+Ki 刀e(t)+u0u(t)――输出、Kp比例放大系数、Ki――积分放大系数、e(t)――误差、u0――控制量基准值(基础偏差) 大家可以看到积分项是一个历史误差的累积值,如果光用比例控制时,我们知道要不就是达不到设定值要不就是振荡,在使用了积分项后就可以解决达不到设定值的静态误差问题,比方说一个控制中使用了PI控制后,如果存在静态误差,输出始终达不到设定值,这时积分项的误差累积值会越来越大,这个累积值乘上Ki后会在输出的比重中越占越多,使输出u(t)越来越大,最终达到消除静态误差的目的。

最全PID控制算法的C语言实现

最全PID控制算法的C语言实现

最全PID控制算法的C语言实现PID控制算法是一种在控制系统中常用的反馈控制算法,用于根据实际测量值来调节输出来实现对系统状态的控制。

PID算法包含三个控制参数:比例常数(Kp)、积分常数(Ki)和微分常数(Kd)。

这三个参数分别调节了比例控制、积分控制和微分控制的比例,用于实现不同的控制效果。

下面是一个最全的PID控制算法的C语言实现示例:```c#include <stdio.h>//定义PID控制算法的参数float Kp = 1.0; // 比例常数float Ki = 0.5; // 积分常数float Kd = 0.2; // 微分常数//定义全局变量用于记录控制过程中的误差与累积误差float error = 0.0;float lastError = 0.0;float integral = 0.0;//定义PID控制函数float pidControl(float target, float current, float dt)//计算误差error = target - current;//计算累积误差integral += error * dt;//计算微分误差float derivative = (error - lastError) / dt;//计算PID输出float output = Kp * error + Ki * integral + Kd * derivative; //更新上一次误差lastError = error;return output;int mai//模拟控制过程float target = 100.0; // 目标值float current = 0.0; // 当前值float dt = 0.1; // 控制周期for(int i = 0; i < 100; i++)//调用PID控制函数float output = pidControl(target, current, dt);//更新当前值,模拟实际过程中的测量误差current += output * dt + 0.2;printf("Target: %.2f, Current: %.2f, Output: %.2f\n", target, current, output);}return 0;```上述代码通过定义全局变量来记录控制过程中的误差与累积误差,并在PID控制函数中进行计算和更新。

温度控制的PID算法与C程序实现

温度控制的PID算法与C程序实现

温度控制与PID算法温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。

1.温度控制的框图这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。

系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。

例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。

其调节过程如下:温度控制的功率输出采用脉宽调制的方法。

固态继电器SSR的输出端为脉宽可调的电压U OUT 。

当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。

因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。

一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。

下面将要描述的PID调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。

2.温度控制的两个阶段温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。

另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。

这给温度的控制带来了困难。

因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。

PID控制算法的C语言实现精修订

PID控制算法的C语言实现精修订

PID控制算法的C语言实现精修订一、算法的实现步骤1.初始化PID参数:设定比例系数Kp、积分系数Ki和微分系数Kd的初值。

一般情况下,可以根据系统的特性进行经验调整。

2.设置控制目标:设定系统需要达到的目标值。

3.读取当前系统的测量值:使用传感器或其他设备获取当前系统的实际测量值。

4.计算系统误差:将目标值减去实际测量值,得到系统的误差。

5.计算PID控制量:将控制量设为比例项、积分项和微分项的和。

比例项为误差乘以比例系数Kp,积分项为误差的累积乘以积分系数Ki,微分项为误差变化率乘以微分系数Kd。

6.更新PID参数:根据实际情况,可调整PID参数的值。

一般情况下,可以使用经验调整方法,如试探法或模拟法。

7.输出控制量:将PID控制量作为输出,在系统中执行相应的控制操作,如调节电机的转速或改变阀门的开度。

8.循环执行以上步骤,直到系统达到控制目标或终止算法。

二、参数调整方法1.经验调整法:根据系统的特性和控制要求,选择合适的PID参数初值,通过实验或仿真来逐步调整参数,使系统达到最佳控制效果。

2. Ziegler-Nichols法则:利用开环试验的响应特性,通过确定系统的临界增益和周期,计算出PID参数。

该方法相对简单,但对系统的稳定性要求较高。

3.自整定法:利用系统的模型参数,结合在线参数调整技术,通过试错调整来获取最佳PID参数。

方法复杂度较高,但能够适应系统动态性变化较大的情况。

4.基于优化算法的自适应调整法:利用遗传算法、粒子群算法等优化算法,通过迭代计算获得最佳PID参数。

该方法不需要系统模型,但需要大量的计算和优化算法的实现。

三、实际应用案例假设有一个加热器,需要将温度控制在一个设定值范围内。

可以使用PID控制算法实现温度的稳定控制。

1.初始化PID参数:设定比例系数Kp=1,积分系数Ki=0.5和微分系数Kd=0.22.设置控制目标:设定温度控制的目标范围为35℃到40℃。

3.读取当前系统的温度值:使用温度传感器读取当前系统的实际温度值。

温度控制的PID算法的C语言程序

温度控制的PID算法的C语言程序

温度控制的PID算法的C语⾔程序结合⼯程实践选题相关的⼀套源代码,根据其编程语⾔或项⽬特点,分析其在源代码⽬录结构、⽂件名/类名/函数名/变量名等命名、接⼝定义规范和单元测试组织形式等⽅⾯的做法和特点;我的⼯程实践是《服务器风扇转速智能控制》主要任务是开发⼀个应⽤,根据服务器内的版卡的功耗和温度,智能的调控服务器的风扇转速。

主要涉及风扇转速智能控制算法设计,linux系统下的应⽤开发,服务器风扇控制编成,板卡温度读取编成技术。

编程语⾔是c语⾔或者汇编语⾔。

这次我选择的源代码是基于pid算法的温度控制系统。

因为是编写的是底层的函数库,要求程序速度快,空间⼩,因此代码较为简短,⽬录结构⽐较简单,只有两个⽂件。

⽂件名⽐较简单。

由于没有使⽤⾯向对象语⾔,所以不存在类名。

函数名和变量名都是符合c语⾔变量与函数命名规范。

普通变量使⽤⼩写英⽂单词,较长单词使⽤缩写,多个单词⽤下划线相连。

常量使⽤⼤写。

函数名英⽂单词⾸字母⼤写。

变量名和函数名直观可以拼读,从名字可以⼤致知晓变量与函数作⽤。

接⼝定义要求简洁明了,能⽤传地址就不传值。

尽量数据耦合减少控制耦合。

单元测试组织形式,由于本程序是由⼀个函数调⽤其他函数组织⽽成,单元测试从最⼩的每个函数开始测试,从底向上进⾏测试。

列举哪些做法符合代码规范和风格⼀般要求;程序中有清晰的注释程序头部有程序整体的说明每个函数都有注释和说明函数的功能代码中有适当的注释说明代码段的功能标识符命名要尽量能直观的反映该标识符的功能标识符都⽤英⽂不⽤汉语拼⾳列举哪些做法有悖于“代码的简洁、清晰、⽆歧义”的基本原则,及如何进⼀步优化改进;在该源码中缩进并不是很规范有⼀部分变量没有注释说明其功能改进:缩进的宽度为四个字符,使⽤tab或者四个空格两者之⼀凡函数 if while for do-while switch 都要使⽤缩进总结同类编程语⾔或项⽬在代码规范和风格的⼀般要求。

c类语⾔或者项⽬在代码规范和风格中⼀般对于以下七个⽅⾯有要求:1) 空⾏定义变量或者函数后就要空⾏,两个相对独⽴的程序块、变量说明之后必须要加空⾏。

温度控制的PID算法的C语言程序

温度控制的PID算法的C语言程序

基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。

用keil C语言来实现PID的控制。

超低温漂移高精度运算放大器0P07将温度一电压信号进行放大,便于A/D进行转换,以提高温度采集电路的可靠性。

模拟电路硬件部分见图2。

图2 ?温度电压转换电路电控制执行电路的设计??? 由输出来控制电炉,电炉可以近似建立为具有滞后性质的一阶惯性环节数学模型。

其传递函数形式为:??? 可控硅可以认为是线形环节实现对水温的控制。

单片机输出与电炉功率分别属于弱电与强电部分,需要进行隔离处理,这里采用光耦元件TLP521 在控制部分进行光电隔离,此外采用变压器隔离实现弱强电的电源隔离。

??? 单片机PWM 输出电平为0 时,光耦元件导通,从而使三极管形成有效偏置而导通,通过整流桥的电压经过集电极电阻以及射集反向偏压,有7V 左右的电压加在双向可控硅控制端,从而使可控硅导通,交流通路形成,电阻炉工作;反之单片机输出电平为0 时,光耦元件不能导通,三极管不能形成有效偏置而截止,可控硅控制端电压几乎为零,可控硅截止从而截断交流通路,电炉停止工作。

此外,还有越限报警,当温度低于下限时发光二极管亮;高上限时蜂鸣器叫。

控制执行部分的硬件电路如下:图3? 控制执行部分电路3 键盘及显示的设计??? 键盘采用软件查询和外部中断相结合的方法来,低电平有效。

图3 中按键AN1,AN2,AN3,AN4, AN5的功能定义如表1所示。

??? 按键AN3与相连,采用外部中断方式,并且优先级定为最高;按键AN5和AN4分别与和相连,采用软件查询的方式;AN1则为硬件复位键,与R、C构成复位电路。

??????????????????? 表1 按键功能按键键名功能AN1 复位键使系统复位AN2 运行键使系统开始数据采集AN3??? 功能转换键按键按下(D1亮)时,显示温度设定值;按键升起(D1不亮)时,显示前温度值AN4 加一键设定温度渐次加一AN5 减一键设定温度渐次减一??? 显示采用3位共阳LED静态显示方式,显示内容有温度值的十位、个位及小数点后一位,这样可以只用(RXD)口来输出显示数据,从而节省了单片机端口资源,在口和(TXD)的控制下通过74LS164来实现3位静态显示。

温度控制的PID算法 及C程序实现

温度控制的PID算法 及C程序实现

温度控制与PID算法温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。

1.温度控制的框图这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。

系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。

例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。

其调节过程如下:温度控制的功率输出采用脉宽调制的方法。

固态继电器SSR的输出端为脉宽可调的电压U OUT 。

当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。

因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。

一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。

下面将要描述的PID 调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。

2.温度控制的两个阶段温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。

另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。

这给温度的控制带来了困难。

因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。

pid控制温度实例 c语言

pid控制温度实例 c语言

pid控制温度实例 c语言以下是一个简单的PID温度控制器的C语言实现示例:```c#include <stdio.h>// PID参数结构体typedef struct {double Kp; // 比例系数double Ki; // 积分系数double Kd; // 微分系数double integral; // 积分项double pre_error; // 上一次误差} PID_t;// PID温度控制器函数double pid_temperature_control(PID_t *pid, double setpoint, double actual_temperature) {double error = setpoint - actual_temperature; // 计算误差pid->integral += error; // 计算积分项double derivative = error - pid->pre_error; // 计算微分项double output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; // 计算输出值pid->pre_error = error; // 保存上一次误差值return output;}int main() {PID_t pid = {1.0, 0.5, 0.1, 0.0, 0.0}; // PID参数初始化 double setpoint = 100.0; // 设定温度值double actual_temperature = 0.0; // 实际温度值double output = 0.0; // 输出值int i;for (i = 0; i < 100; i++) { // 模拟控制过程,迭代100次 output = pid_temperature_control(&pid, setpoint, actual_temperature); // 计算输出值printf("Time: %d, Setpoint: %f, ActualTemperature: %f, Output: %f\n", i, setpoint,actual_temperature, output); // 输出结果actual_temperature += output * 0.1; // 根据输出值调整实际温度值,模拟控制过程}return 0;}```在上面的示例中,我们首先定义了一个PID参数结构体,其中包含了比例系数、积分系数、微分系数、积分项和上一次误差等参数。

温度控制的PID算法-及C程序实现

温度控制的PID算法-及C程序实现

温度控制的PID算法-及C程序实现温度控制与PID算法温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。

1.温度控制的框图这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。

系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。

例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。

其调节过程如下:温度控制的功率输出采用脉宽调制的方法。

固态继电器SSR的输出端为脉宽可调的电压U OUT 。

当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。

因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。

一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。

下面将要描述的PID调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。

2.温度控制的两个阶段温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。

另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。

这给温度的控制带来了困难。

因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。

温度控制的PID算法的C语言程序

温度控制的PID算法的C语言程序

基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。

用keil C语言来实现PID的控制。

//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标Desired Valueunsigned int Proportion; // 比例常数Proportional Constunsigned int Integral; // 积分常数Integral Constunsigned int Derivative; // 微分常数Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/***********************************************************延时子程序,延时时间以12M晶振为准,延时时间为30us×time***********************************************************/void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/*********************************************************** 写一位数据子程序***********************************************************/ void write_bit(unsigned char bitval){EA=0;DQ=0; /*拉低DQ以开始一个写时序*/if(bitval==1){_nop_();DQ=1; /*如要写1,则将总线置高*/}delay(5); /*延时90us供DA18B20采样*/DQ=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/*********************************************************** 写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/*********************************************************** 读一位数据子程序***********************************************************/ unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,开始读时序*/_nop_();_nop_();DQ=1; /*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/*********************************************************** 读一字节数据子程序***********************************************************/ unsigned char read_byte(){unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/*********************************************************** 复位子程序***********************************************************/ unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/}/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/i=0xcc; /*发送设备定位命令*/write_byte(i);i=0x44; /*发送开始转换命令*/write_byte(i);delay(180); /*延时*/do{i=reset(); /*复位*/}while(i!=0);i=0xcc; /*设备定位*/write_byte(i);i=0xbe; /*读出缓冲区容*/write_byte(i);j=read_byte();i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*============================================================================= =======================Initialize PID Structure=============================================================================== ======================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*============================================================================= =======================PID计算部分=============================================================================== ======================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,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); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/pare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}/***************************************************** T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期******************************************************/ void serve_T0() interrupt 1 using 1{if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/ void serve_sio() interrupt 4 using 2{/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]){unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;else_nop_();clk=1;_nop_();}}}/*****************************************************显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/void display(){unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/***********************************************************主程序***********************************************************/main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; // Set PID Setpoint while(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){}if(plus==0){set_temper++;flag=0;}}else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0) {for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5) temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30) {display();count1=0;}pare_temper();}TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1;}}//DS18b20 子程序#include <REG52.H>sbit DQ=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480usDQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;for (i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节void write_byte(char val){byte i;for (i=8;i>0;i--) //一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了PID算法PID算法是本程序中的核心部分。

PID控制算法的C语言实现完整版

PID控制算法的C语言实现完整版

PID控制算法(de)C语言实现一 PID算法原理最近两天在考虑一般控制算法(de)C语言实现问题,发现网络上尚没有一套完整(de)比较体系(de)讲解.于是总结了几天,整理一套思路分享给大家.在工业应用中PID及其衍生算法是应用最广泛(de)算法之一,是当之无愧(de)万能算法,如果能够熟练掌握PID算法(de)设计与实现过程,对于一般(de)研发人员来讲,应该是足够应对一般研发问题了,而难能可贵(de)是,在我所接触(de)控制算法当中,PID控制算法又是最简单,最能体现反馈思想(de)控制算法,可谓经典中(de)经典.经典(de)未必是复杂(de),经典(de)东西常常是简单(de),而且是最简单(de),想想牛顿(de)力学三大定律吧,想想爱因斯坦(de)质能方程吧,何等(de)简单简单(de)不是原始(de),简单(de)也不是落后(de),简单到了美(de)程度.先看看PID算法(de)一般形式:PID(de)流程简单到了不能再简单(de)程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节(de)加和.这里我们规定(在t时刻):1.输入量为rin(t);2.输出量为rout(t);3.偏差量为err(t)=rin(t)-rout(t);pid(de)控制规律为理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下:1.规定这个流程是用来为直流电机调速(de);2.输入量rin(t)为电机转速预定值;3.输出量rout(t)为电机转速实际值;4.执行器为直流电机;5.传感器为光电码盘,假设码盘为10线;6.直流电机采用PWM调速转速用单位转/min表示;不难看出以下结论:1.输入量rin(t)为电机转速预定值(转/min);2. 输出量rout(t)为电机转速实际值(转/min);3.偏差量为预定值和实际值之差(转/min);那么以下几个问题需要弄清楚:1.通过PID环节之后(de)U(t)是什么值呢2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比).3.那么U(t)与PWM之间存在怎样(de)联系呢(见附录1)这篇文章上给出了一种方法,即,每个电压对应一个转速,电压和转速之间呈现线性关系.但是我考虑这种方法(de)前提是把直流电机(de)特性理解为线性了,而实际情况下,直流电机(de)特性绝对不是线性(de),或者说在局部上是趋于线性(de),这就是为什么说PID调速有个范围(de)问题.具体看一下(见附录2)这篇文章就可以了解了.所以在正式进行调速设计之前,需要现有开环系统,测试电机和转速之间(de)特性曲线(或者查阅电机(de)资料说明),然后再进行闭环参数整定.这篇先写到这,下一篇说明连续系统(de)离散化问题.并根据离散化后(de)特点讲述位置型PID和增量型PID(de)用法和C语言实现过程.PID控制算法(de)C语言实现二 PID算法(de)离散化上一节中,我论述了PID算法(de)基本形式,并对其控制过程(de)实现有了一个简要(de)说明,通过上一节(de)总结,基本已经可以明白PID控制(de)过程.这一节中先继续上一节内容补充说明一下.1.说明一下反馈控制(de)原理,通过上一节(de)框图不难看出,PID控制其实是对偏差(de)控制过程;2.如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用.3.积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间(de)差值,积分环节实际上就是偏差累计(de)过程,把累计(de)误差加到原有系统上以抵消系统造成(de)静差.4.而微分信号则反应了偏差信号(de)变化规律,或者说是变化趋势,根据偏差信号(de)变化趋势来进行超前调节,从而增加了系统(de)快速性.好了,关于PID(de)基本说明就补充到这里,下面将对PID连续系统离散化,从而方便在处理器上实现.下面把连续状态(de)公式再贴一下:假设采样间隔为T,则在第K T时刻:偏差err(K)=rin(K)-rout(K);积分环节用加和(de)形式表示,即err(K)+err(K+1)+……;微分环节用斜率(de)形式表示,即[err(K)-err(K-1)]/T;从而形成如下PID离散表示形式:则u(K)可表示成为:至于说Kp、Ki、Kd三个参数(de)具体表达式,我想可以轻松(de)推出了,这里节省时间,不再详细表示了.其实到这里为止,PID(de)基本离散表示形式已经出来了.目前(de)这种表述形式属于位置型PID,另外一种表述方式为增量式PID,由U上述表达式可以轻易得到:那么:这就是离散化PID(de)增量式表示方式,由公式可以看出,增量式(de)表达结果和最近三次(de)偏差有关,这样就大大提高了系统(de)稳定性.需要注意(de)是最终(de)输出结果应该为u(K)+增量调节值;PID(de)离散化过程基本思路就是这样,下面是将离散化(de)公式转换成为C语言,从而实现微控制器(de)控制作用.PID控制算法(de)C语言实现三位置型PID(de)C语言实现上一节中已经抽象出了位置性PID和增量型PID(de)数学表达式,这一节,重点讲解C语言代码(de)实现过程,算法(de)C语言实现过程具有一般性,通过PID算法(de)C语言实现,可以以此类推,设计其它算法(de)C语言实现.第一步:定义PID变量结构体,代码如下:struct _pid{float SetSpeed;例系数Kp(de)作用是加快系统(de)响应速度,提高系统(de)调节精度.Kp越大,系统(de)响应速度越快,系统(de)调节精度越高,但是容易产生超调,甚至会使系统不稳定.Kp取值过小,则会降低调节精度,使响应速度缓慢,从而延长调节时间,是系统静态、动态特性变差;2.积分作用系数Ki(de)作用是消除系统(de)稳态误差.Ki越大,系统(de)静态误差消除(de)越快,但是Ki过大,在响应过程(de)初期会产生积分饱和(de)现象,从而引起响应过程(de)较大超调.若Ki过小,将使系统静态误差难以消除,影响系统(de)调节精度;3.微分系数Kd(de)作用是改善系统(de)动态特性,其作用主要是在响应过程中抑制偏差向任何方向(de)变化,对偏差变化进行提前预报.但是kd过大,会使响应过程提前制动,从而延长调节时间,而且会降低系统(de)抗干扰性.反应系统性能(de)两个参数是系统误差e和误差变化律ec,这点还是好理解(de):首先我们规定一个误差(de)极限值,假设为Mmax;规定一个误差(de)比较大(de)值,假设为Mmid;规定一个误差(de)较小值,假设为Mmin;当abs(e)>Mmax时,说明误差(de)绝对值已经很大了,不论误差变化趋势如何,都应该考虑控制器(de)输入应按最大(或最小)输出,以达到迅速调整误差(de)效果,使误差绝对值以最大(de)速度减小.此时,相当于实施开环控制.当eec>0时,说明误差在朝向误差绝对值增大(de)方向变化,此时,如果abs(e)>Mmid,说明误差也较大,可考虑由控制器实施较强(de)控制作用,以达到扭转误差绝对值向减小(de)方向变化,并迅速减小误差(de)绝对值.此时如果abs(e)<Mmid,说明尽管误差是向绝对值增大(de)方向变化,但是误差绝对值本身并不是很大,可以考虑控制器实施一般(de)控制作用,只需要扭转误差(de)变化趋势,使其向误差绝对值减小(de)方向变化即可.当eerr<0且eerr(k-1)>0或者e=0时,说明误差(de)绝对值向减小(de)方向变化,或者已经达到平衡状态,此时保持控制器输出不变即可.当eerr<0且eerr(k-1)<0时,说明误差处于极限状态.如果此时误差(de)绝对值较大,大于Mmin,可以考虑实施较强控制作用.如果此时误差绝对值较小,可以考虑实施较弱控制作用.当abs(e)<Mmin时,说明误差绝对值很小,此时加入积分,减小静态误差.上面(de)逻辑判断过程,实际上就是对于控制系统(de)一个专家判断过程.(未完待续)PID控制算法(de)C语言实现十模糊算法简介在PID控制算法(de)C语言实现九中,文章已经对模糊PID(de)实质做了一个简要说明.本来打算等到完成毕业设计,工作稳定了再着力完成剩下(de)部分.鉴于网友(de)要求和信任,抽出时间来,对模糊PID做一个较为详细(de)论述,这里我不打算做出仿真程序了,但就基本概念和思路进行一下说明,相信有C语言基础(de)朋友可以通过这些介绍性(de)文字自行实现.这篇文章主要说明一下模糊算法(de)含义和原理.实际上模糊算法属于智能算法,智能算法也可以叫非模型算法,也就是说,当我们对于系统(de)模型认识不是很深刻,或者说客观(de)原因导致我们无法对系统(de)控制模型进行深入研究(de)时候,智能算法常常能够起到不小(de)作用.这点是方便理解(de),如果一个系统(de)模型可以轻易(de)获得,那么就可以根据系统(de)模型进行模型分析,设计出适合系统模型(de)控制器.但是现实世界中,可以说所有(de)系统都是非线性(de),是不可预测(de).但这并不是说我们就无从建立控制器,因为,大部分(de)系统在一定(de)条件和范围内是可以抽象成为线性系统(de).问题(de)关键是,当我们系统设计(de)范围超出了线性(de)范围,我们又该如何处理.显然,智能算法是一条很不错(de)途径.智能算法包含了专家系统、模糊算法、遗传算法、神经网络算法等.其实这其中(de)任何一种算法都可以跟PID去做结合,而选择(de)关键在于,处理(de)实时性能不能得到满足.当我们处理器(de)速度足够快速时,我们可以选择更为复杂(de)、精度更加高(de)算法.但是,控制器(de)处理速度限制了我们算法(de)选择.当然,成本是限制处理器速度最根本(de)原因.这个道理很简单,51单片机和DSP(de)成本肯定大不相同.专家PID和模糊PID是常用(de)两种PID选择方式.其实,模糊PID适应一般(de)控制系统是没有问题.文章接下来将说明模糊算法(de)一些基本常识.模糊算法其实并不模糊.模糊算法其实也是逐次求精(de)过程.这里举个例子说明.我们设计一个倒立摆系统,假如摆针偏差<5°,我们说它(de)偏差比较“小”;摆针偏差在5°和10°之间,我们说它(de)偏差处于“中”(de)状态;当摆针偏差>10°(de)时候,我们说它(de)偏差有点儿“大”了.对于“小”、“中”、“大”这样(de)词汇来讲,他们是精确(de)表述,可问题是如果摆针偏差是3°呢,那么这是一种什么样(de)状态呢.我们可以用“很小”来表述它.如果是7°呢,可以说它是“中”偏“小”.那么如果到了80°呢,它(de)偏差可以说“非常大”.而我们调节(de)过程实际上就是让系统(de)偏差由非常“大”逐渐向非常“小”过度(de)过程.当然,我们系统这个调节过程是快速稳定(de).通过上面(de)说明,可以认识到,其实对于每一种状态都可以划分到大、中、小三个状态当中去,只不过他们隶属(de)程度不太一样,比如6°隶属于小(de)程度可能是,隶属于中(de)程度是,隶属于大(de)程度是0.这里实际上是有一个问题(de),就是这个隶属(de)程度怎么确定这就要求我们去设计一个隶属函数.详细内容可以查阅相关(de)资料,这里没有办法那么详细(de)说明了.(见附录3)这里面有些说明.那么,知道了隶属度(de)问题,就可以根据目前隶属(de)程度来控制电机以多大(de)速度和方向转动了,当然,最终(de)控制量肯定要落实在控制电压上.这点可以很容易(de)想想,我们控制(de)目(de)就是让倒立摆从隶属“大”(de)程度为1(de)状态,调节到隶属“小”(de)程度为1(de)状态.当隶属大多一些(de)时候,我们就加快调节(de)速度,当隶属小多一些(de)时候,我们就减慢调节(de)速度,进行微调.可问题是,大、中、小(de)状态是汉字,怎么用数字表示,进而用程序代码表示呢其实我们可以给大、中、小三个状态设定三个数字来表示,比如大表示用3表示,中用2表示,小用1表示.那么我们完全可以用1+2+3=来表示它,当然这个公式也不一定是这样(de),这个公式(de)设计是系统模糊化和精确化(de)一个过程,读者也可参见相关文献理解.但就这个数字而言,可以说明,目前6°(de)角度偏差处于小和中之间,但是更偏向于中.我们就可以根据这个数字来调节电机(de)转动速度和时间了.当然,这个数字与电机转速(de)对应关系,也需要根据实际情况进行设计和调节.前面一个例子已经基本上说明了模糊算法(de)基本原理了.可是实际上,一个系统(de)限制因素常常不是一个.上面(de)例子中,只有偏差角度成为了系统调节(de)参考因素.而实际系统中,比如PID系统,我们需要调节(de)是比例、积分、微分三个环节,那么这三个环节(de)作用就需要我们认清,也就是说,我们需要根据超调量、调节时间、震荡情况等信息来考虑对这三个环节调节(de)比重,输入量和输出量都不是单一(de),可是其中必然有某种内在(de)逻辑联系.所以这种逻辑联系就成为我们设计工作(de)重点了.下一篇文章将详细分析PID三个变量和系统性能参数之间(de)联系.PID控制算法(de)c语言实现十一(PID系列完结篇)模糊PID(de)参数整定这几天一直在考虑如何能够把这一节(de)内容说清楚,对于PID而言应用并没有多大难度,按照基本(de)算法设计思路和成熟(de)参数整定方法,就算是没有经过特殊训练和培训(de)人,也能够在较短(de)时间内容学会使用PID算法.可问题是,如何能够透彻(de)理解PID算法,从而能够根据实际(de)情况设计出优秀(de)算法呢.通过讲述公式和基本原理肯定是最能说明问题(de),可是这样(de)话怕是犯了“专家”(de)错误了.对于门槛比较低(de)技术人员来讲,依然不能透彻理解.可是说(de)入耳了,能不能透彻说明也是一个问题,所以斟酌了几天,整理了一下思路才开始完成PID系列文章(de)最后一篇.我所说(de)最后一篇不代表PID(de)功能和发展就止步与此,仅仅是说明,透过这一些列(de)文章,基本上已经可以涵盖PID设计(de)要点,至于更深入(de)研究,就交给有需要(de)读者去做.上一节中大致讲述了一下模糊算法.实际上模糊算法(de)很多概念在上一节中并没有深入(de)解释.举(de)例子也只是为了说明模糊算法(de)基本含义,真正(de)模糊算法是不能这么设计(de),当然也不会这么简单.模糊算法(de)核心是模糊规则,如果模糊规则制定(de)出色,那么模糊算法(de)控制效率就高.其实这是智能算法(de)一般特性,规则是系统判断和处理(de)前提.那么就说说PID(de)规则该怎么制定.我们知道,模糊算法(de)本质是对PID(de)三个参数进行智能调节.那么首先要提出(de)问题是如何对PID(de)参数进行调节这个问题其实是参数整定(de)问题,现实当中有很多整定方法.可是我们需要从根本上了解为什么这么整定,才能知道该如何建立数学模型进行分析.那么要回答如何整定参数(de)问题,就需要先明白PID参数(de)作用都是什么对系统有什么影响我们从作用和副作用两个方面说明参数对系统(de)影响.1.比例环节Kp,作用是加快系统(de)响应速度,提高系统(de)调节精度,副作用是会导致超调;2.积分环节Ki,作用是消除稳态误差,副作用是导致积分饱和现象;3.微分环节Kd,作用是改善系统(de)动态性能,副作用是延长系统(de)调节时间.理解了上述问题,那么就可以“辩证施治,对症下药”了.比如说,如果系统响应速度慢,我们就加大Kp(de)取值,如果超调量过大我们就减小Kp(de)取值等等.可是问题这些语言(de)描述该如何用数学形式表达出来呢.我们所知道(de),反馈系统(de)实质就是系统(de)输出量作为反馈量与系统(de)输入量进行作差,从而得到系统(de)误差e,那么这个误差e就能够反应目前系统所处(de)状态.误差e可以表明目前系统(de)输出状态到底偏离要求多少.而误差e(de)变化律ec,表示误差变化(de)速度.这样,我们可以根据这两个量(de)状态来分析三个参数此时应该如何取值,假如e为负方向比较大,ec也为负方向增大状态,此时比例环节要大一些,从而加快调节速度,而积分环节要小一些,甚至不加积分环节,从而防止负方向上出现饱和积分(de)现象.微分环节可以稍加一些,在不影响调节时间(de)情况下,起到改善系统动态性能(de)作用.附录1看到有不少人问到底如何让UK值与PWM占空比值对应,进而实现占空比输出和输出控制电压对应.(注意,我这里讨论(de)前提是输出控制(de)是电压,不是PWM方波.PWM输出后要经过滤波整形再输出控制.)前提条件:输出电压控制电压范围是0-10V.给定、反馈、输出电压采样输入电压范围是0-5V(经过运放).使用单片机AD为10位AD芯片.那么10位AD芯片电压采集得到(de)数据范围就是0-1024.PWM为 8位可调占空比方波,0对应输出占空比为0(de)方波,255对应输出占空比100%(de)方波,127对应输出50%(de)方波.比如当前给定是,反馈电压是1V.(KP,KI,KD等系数略,关于PID算法(de)整数实现我在前文中有论述如何实现).那么经过AD采样1、给定对应为 5122、反馈1V对应为 205假定经过PID计算得到(de)UK为400也就意味着输出电压应当为(400(UPWM峰值电压))/1024那么UK对应(de)PWM占空比是多少呢我们知道,UK=1024对应占空比为100,也就是PWM(de)占空比系数为255.可知,PWM系数 = UK/4;那么400就应当对应系数 400/4=100.也就是输出电压=40010/1024=同时,由于采样精度以及PWM输出占空比精度控制(de)问题,将导致输出电压和期望值不是那么线性,所以,我在项目内加入了输出电压采样(de)控制.采样AD输入为0-5V,所以,对于输出0-10V有一个缩小(de)比例.输出10V则采样值对应为255输出5V则采样之对应127可知,对应AD结果为97采样输出电压值,可以针对性(de)调整一下占空比输出,从而得到误差允许范围内(de)一个控制输出电压.同时,经过一些加速控制(de)手段.可以比较迅速(de)达到控制(de)目(de).下文中(de)UK控制方法是针对增量式PID控制而来做(de).//void PWMProcess(void){uint16 idata temp;uint16 idata UKTemp;temp = 0;UKTemp = 0;if( = 0 ) //判断是否需要改变占空比{ //是否需要改变占空比和你(de)被控系统特性有关= 0;UKTemp = + ;//计算UK控制量//控制量和计算值以及一个开关量有关,我这里(de)开关量是系统需要(de)时候叠加在控制量上(de)一个变量.if(UKTemp>999){UKTemp = 999;}//这里只所以是999封顶而不是1024是因为我(de)系统PWM(de)峰值电压是12V导致.while(1) //如果输出电压和期望电压相差 Delta,则继续调整占空比,直到在误差以内{ADChPro(UPWMADCH); //测量输出电压if( [UPWMADCH] == UKTemp){return;}if( [UPWMADCH] > UKTemp) //如果当前电压大于输出电压,减小占空比{if( ( [UPWMADCH] - UKTemp ) > UDELTA ){temp = [UPWMADCH] - UKTemp; //temp = temp / 2; //下降可以加速下降,所以下降参数加倍if( > temp ){= - temp;else{= 0;}}else{return;}}else //如果当前电压小于输出电压{if( ( UKTemp - [UPWMADCH] ) > UDELTA ){temp = UKTemp - [UPWMADCH];temp = temp / 4; //上升处理不要超调,所以每次只+一半 if( > temp ){+= (temp/2);}else{= 255;}}elsereturn;}}DisPlayVoltage();PWMChangeDuty; //改变占空比Delay(10,10);}}}//附录2直流电机PWM调速系统中控制电压非线性研究引言由于线性放大驱动方式效率和散热问题严重,目前绝大多数直流电动机采用开关驱动方式.开关驱动方式是半导体功率器件工作在开关状态,通过脉宽调制PWM控制电动机电枢电压,实现调速.目前已有许多文献介绍直流电机调速,宋卫国等用89C51单片机实现了直流电机闭环调速;张立勋等用AVR单片机实现了直流电机PWM调速;郭崇军等用C8051实现了无刷直流电机控制;张红娟等用PIC单片机实现了直流电机PWM调速;王晨阳等用DSP实现了无刷直流电机控制.上述文献对实现调速(de)硬件电路和软件流程(de)设计有较详细(de)描述,但没有说明具体(de)调压调速方法,也没有提及占空比与电机端电压平均值之间(de)关系.在李维军等基于单片机用软件实现直流电机PWM调速系统中提到平均速度与占空比并不是严格(de)线性关系,在一般(de)应用中,可以将其近似地看作线性关系.但没有做深入(de)研究.本文通过实验验证,在不带电机情况下,PWM波占空比与控制输出端电压平均值之间呈线性关系;在带电机情况下,占空比与电机端电压平均值满足抛物线方程,能取得精确(de)控制.本文(de)电机闭环调速是运用Matlab拟合(de)关系式通过PID控制算法实现.1 系统硬件设计本系统是基于TX-1C实验板上(de)AT89C52单片机,调速系统(de)硬件原理图如图1所示,主要由AT89C52单片机、555振荡电路、L298驱动电路、光电隔离、霍尔元件测速电路、MAX 232电平转换电路等组成.图1 闭环控制系统示意图2 系统软件设计系统采用模块化设计,软件由1个主程序,3个中断子程序,即外部中断0、外部中断1,定时器0子程序,PID算法子程序,测速子程序及发送数据到串口显示子程序组成,主程序流程图如图2所示.外部中断0通过比较直流电平与锯齿波信号产生PWM波,外部中断1用于对传感器(de)脉冲计数.定时器0用于对计数脉冲定时.测得(de)转速通过串口发送到上位机显示,通过PID模块调整转速到设定值.本实验采用M/T法测速,它是同时测量检测时间和在此检测时间内霍尔传感器所产生(de)转速脉冲信号(de)个数来确定转速.由外部中断1对霍尔传感器脉冲计数,同时起动定时器0,当计数个数到预定值2 000后,关定时器0,可得到计2 000个脉冲(de)计数时间,由式计算出转速:n=60f/K=60N/(KT) (1)式中:n为直流电机(de)转速;K为霍尔传感器转盘上磁钢数;f为脉冲频率;N为脉冲个数;T为采样周期.图2 主程序流程图3 实验结果及原因分析3.1 端电压平均值与转速关系3.1.1 实验结果实验用(de)是永磁稳速直流电机,型号是EG-530YD-2BH,额定转速2 000~4 000 r/min,额定电压12 V.电机在空载(de)情况下,测得(de)数据用Matlab做一次线性拟合,拟合(de)端电压平均值与转速关系曲线如图3(a)所示.相关系数R-square:0.952 1.拟合曲线方程为:y=0.001 852x+0.296 3 (2)由式(2)可知,端电压平均值与转速可近似为线性关系,根椐此关系式,在已测得(de)转速(de)情况下可以计算出当前电压.为了比较分析,同样用Matlab做二次线性拟合,拟合(de)端电压平均值与转速关系曲线如图3(b)所示.相关系数R-square:0.986 7.图3 端电压平均值与转速关系曲线图3.1.2 原因分析比较图3(a)可知,当转速在0~1 500 r/min和4 000~5 000 r/min,端电压平均值与转速间存在(de)非线性,用二次曲拟合如图3(b)所示,拟合相关系数较高.由图3(a)可见,当电机转速为0时电机两端电压平均值约为1.3 V.这是因为电机处于静止状态时,摩擦力为静摩擦力,静摩擦力是非线性(de).随着外力(de)增加而增加,最大值发生在运动前(de)瞬间.电磁转矩为负载制动转矩和空载制动转矩之和,由于本系统不带负载,因此电磁转矩为空载制动转矩.空载制动转矩与转速之间此时是非线性(de).。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

我的题目是:基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。

用keil C语言来实现PID的控制。

最佳答案//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标Desired Valueunsigned int Proportion; // 比例常数Proportional Constunsigned int Integral; // 积分常数Integral Constunsigned int Derivative; // 微分常数Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/***********************************************************延时子程序,延时时间以12M晶振为准,延时时间为30us×time***********************************************************/void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/***********************************************************写一位数据子程序***********************************************************/ void write_bit(unsigned char bitval){EA=0;DQ=0; /*拉低DQ以开始一个写时序*/if(bitval==1){_nop_();DQ=1; /*如要写1,则将总线置高*/}delay(5); /*延时90us供DA18B20采样*/DQ=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/***********************************************************写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/ temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/***********************************************************读一位数据子程序***********************************************************/unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,开始读时序*/_nop_();_nop_();DQ=1; /*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/***********************************************************读一字节数据子程序***********************************************************/unsigned char read_byte(){unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/***********************************************************复位子程序***********************************************************/unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/}/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/i=0xcc; /*发送设备定位命令*/write_byte(i);i=0x44; /*发送开始转换命令*/write_byte(i);delay(180); /*延时*/do{i=reset(); /*复位*/}while(i!=0);i=0xcc; /*设备定位*/write_byte(i);i=0xbe; /*读出缓冲区内容*/write_byte(i);j=read_byte();i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*================================================================== ==================================Initialize PID Structure=================================================================== ==================================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*================================================================== ==================================PID计算部分=================================================================== ==================================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,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); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/compare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}/*****************************************************T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期******************************************************/void serve_T0() interrupt 1 using 1{if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/ void serve_sio() interrupt 4 using 2{/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]){unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;else_nop_();clk=1;_nop_();}}}/*****************************************************显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/void display(){unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/***********************************************************主程序***********************************************************/main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; // Set PID Setpoint while(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){}if(plus==0){set_temper++;flag=0;}}else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5) temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30) {display();count1=0;}compare_temper(); }TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1;}}//DS18b20 子程序#include <REG52.H>sbit DQ=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480usDQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;for (i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节void write_byte(char val){byte i;for (i=8;i>0;i--) //一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了PID算法PID算法是本程序中的核心部分。

相关文档
最新文档