自己大学专业就是学自动化的,现在干嵌入式开发,太久了把本科学的东西都还给老师了,惭愧。项目需要用到PID算法,现在重新温习下。

关于PID的原理、公式及怎么理解PID控制过程的文章一大堆就不再赘述了,推荐这篇文章:https://zhuanlan.zhihu.com/p/39573490

一、本篇文章的目的是编程实现模拟加热系统的温度控制。 先给出PID公式:

其中: P[t], I[t], D[t]分别表示t时刻P(比例)、I(积分)、D(微分)的值

E[t]为目标值和t时刻采样值的偏差

T为采样时间间隔

为微分低通滤波时间常数

Kp、Ki、Kd分别为比例、积分、微分系数

OUT[t]为t时刻PID的输出值

假设目标值是S,t时刻的采样值是M[t],那么

推导:

因此微分项也可以表示为:

系统框图:

关于PID离散化的公式是怎么推导出来的,参考文章:https://blog.csdn.net/qq_27158179/article/details/82912600

二、Python代码实现:

# coding=gbk
from math import pi
from matplotlib import pyplot as plt
from PIL import Image,ImageDraw
import numpy as npDEFAULT_PID_KP = 4.0
DEFAULT_PID_KI = 0.5
DEFAULT_PID_KD = 0.25
DEFAULT_PID_TAU = 0.02PID_OUT_LIM_MIN = -240.0 #PID输出最小值限制
PID_OUT_LIM_MAX = 240.0  #PID输出最大值限制PID_LIM_MIN_INT = -5.0  #PID积分值最小限制
PID_LIM_MAX_INT = 5     #PID积分值最大限制SAMPLE_TIME = 0.01SET_TEMP = 60   #目标温度class PidController(object):#定义属于类的成员,每个实例都共享该变量Kp = DEFAULT_PID_KPKi = DEFAULT_PID_KIKd = DEFAULT_PID_KD# kp为比例系数,ki为积分系数,kd为微分系数, smp_t为采样间隔单位秒def __init__(self, kp, ki, kd, smp_t):self.__integrator = 0.0self.__prevError = 0.0self.__prevMeasurement = 0.0   # 加__ 表示私有变量,只能内部成员才能访问self.__differentiator = 0.0self.__out = 0.0self.Kp = kpself.Ki = kiself.Kd = kdself.T = smp_tself.tau = DEFAULT_PID_TAUself.limMaxInt = PID_LIM_MAX_INTself.limMinInt = PID_LIM_MIN_INTself.limMaxOut = PID_OUT_LIM_MAXself.limMinOut = PID_OUT_LIM_MINdef PidController_Update(self, setpoint, measurement):error = setpoint - measurement  # 计算目标值和实际检测值的差值#print(setpoint, measurement)proportional = self.Kp * error  # 计算比例Pself.__integrator = self.__integrator + 0.5 * self.Ki * self.T * (error + self.__prevError) # 计算积分Iif self.__integrator > self.limMaxInt:self.__integrator = self.limMaxInt;elif self.__integrator < self.limMinInt:self.__integrator = self.limMinInt;#计算微分Dself.__differentiator = -(2.0 * self.Kd * (measurement - self.__prevMeasurement) + (2.0 * self.tau - self.T) * self.__differentiator) / (2.0 * self.tau + self.T);#计算PID输出self.__out = proportional + self.__integrator + self.__differentiatorif self.__out > self.limMaxOut:self.__out = self.limMaxOutelif self.__out < self.limMinOut:self.__out = self.limMinOutself.__prevError = errorself.__prevMeasurement = measurement#print('P = ', round(proportional,6), '\t', 'I = ', round(self.__integrator,6), '\t', 'D = ', round(self.__differentiator,6))def PidController_GetPidOut(self):return self.__out#模拟加热系统
def Calc_Measurement(pwm, preMeasurement):alpha = 0.02m = (SAMPLE_TIME * pwm + preMeasurement) / (1.0 + alpha * SAMPLE_TIME) - SAMPLE_TIME * 0.2 #SAMPLE_TIME * 0.2为散热部分return mdef PID_Run(kp, ki, kd):t_array = []    #保存时间轴的值m_array = []    #保存经过PID控制后系统输出值o_array = []    #保存PID控制量的值h_array = []    #保存固定PID输入量对应系统输出值w_array = []    #保存PID控制量对应的PWM值pid_ctrl = PidController(kp, ki, kd, SAMPLE_TIME)t = 0.0preMeasurement = 0.0set_point = SET_TEMP #目标值tmp = 0.0pwm = 0    # 0% 到 100%while t < 10.0:t_array.append(t)pid_out = pid_ctrl.PidController_GetPidOut()#用pid out来计算应该加热的pwmpwm = int(pid_out+0.5)  #取整if pwm >= 100:pwm = 100elif pwm <= 0:pwm = 0#用pwm控制加热系统,模拟重新获取温度值newMeasurement = Calc_Measurement(pwm, preMeasurement)pid_ctrl.PidController_Update(set_point, newMeasurement)preMeasurement = newMeasurementprint('%0.6f\t%0.6f\t%0.6f' % (t, newMeasurement, pid_ctrl.PidController_GetPidOut()))t = t + SAMPLE_TIMEpid_out = pid_ctrl.PidController_GetPidOut() #重新计算后的pid outo_array.append(pid_out)m_array.append(newMeasurement)w_array.append(pwm)#给定固定的pwm=100%输入,看看Calc_Measurement函数的曲线out = Calc_Measurement(100, tmp)h_array.append(out)tmp = outfig, axs = plt.subplots(2,2)plt.suptitle('Kp=%0.2f,Ki=%0.2f,Kd=%0.2f' % (pid_ctrl.Kp, pid_ctrl.Ki, pid_ctrl.Kd))fig.subplots_adjust(hspace=0.5, wspace=0.5) #设置子图间距axs[0,0].set_title('measurement')axs[0,0].grid(True)axs[0,0].plot(t_array, m_array, c='b', linewidth=2)axs[0,1].set_title('PID out')axs[0,1].grid(True)axs[0,1].plot(t_array, o_array, c='r', linewidth=2)axs[1,0].set_title('PWM')axs[1,0].grid(True)axs[1,0].plot(t_array, w_array, c='m', linewidth=2)axs[1,1].set_title('heat simulate')axs[1,1].grid(True)axs[1,1].plot(t_array, h_array, c='k', linewidth=2)plt.show()#plt.savefig('figure.png', dpi=200) #保存就不能show,否则图片没东西#plt.pause(1)plt.close()if __name__ == '__main__':Kp = DEFAULT_PID_KPKi = DEFAULT_PID_KIKd = DEFAULT_PID_KDPID_Run(Kp, Ki, Kd)'''Kp_step = 0.5Ki_step = 0.1Kd_step = 0.08#Kp变化for i in range(10):PID_Run(Kp, Ki, Kd)Kp = Kp + Kp_step#Ki变化Kp = DEFAULT_PID_KPfor i in range(10):PID_Run(Kp, Ki, Kd)Ki = Ki + Ki_step#Kd变化Ki = DEFAULT_PID_KIfor i in range(10):PID_Run(Kp, Ki, Kd)Kd = Kd + Kd_step'''

三、仿真结果:

说明:程序默认设置参数Kp = 4.0, Ki = 0.5, Kd = 0.25。目标温度是60度。measurement曲线是模拟PID控制后的采样温度值。PID out曲线是PID输出值,PWM为根据PID out计算系统的加热量。通过PWM控制加热功率,比如PWM为100%就是加足马力加热,PWM为0则不加热。heat simulate曲线为固定PWM输入的情况下的加热曲线。

PID学习笔记:模拟加热系统的PID控制相关推荐

  1. “物联网开发实战”学习笔记-(二)手机控制智能电灯

    "物联网开发实战"学习笔记-(二)手机控制智能电灯 如果搭建好硬件平台后,这一次我们的任务主要是调试好智能电灯,并且连接到腾讯云的物联网平台. 腾讯云物联网平台 腾讯物联网平台的优 ...

  2. 四旋翼飞行器控制pid学习笔记

    PID控制学习笔记 --凡事必躬亲,身体而力行,化理论为实践,方得始终. 研究PID,首先应当把PID拆解开来,便是P(比例控制).I(积分控制).D(微分控制), 比例控制P越大,飞行器的动作反应越 ...

  3. Apollo星火计划学习笔记——Control 专项讲解(PID)

    文章目录 1. PID算法介绍 1.1 时间连续与时间离散 1.2 位置式与增量式 1.3 PID算法扩展 2. PID调试方法 3. APOLLO代码介绍 3.1 PID算法 3.2 积分饱和问题 ...

  4. 操作系统学习笔记-2.1.3进程控制

    操作系统学习笔记-2019 王道考研 操作系统-2.1.3进程控制 文章目录 3.进程控制 3.1知识概览 3.2 基本概念 3.2.1什么是进程控制? 3.2.2如何实现进程控制? 3.3进程控制相 ...

  5. 阿里云HaaS100物联网开发板学习笔记(二)硬件控制初步--让小灯闪烁起来

    摘要:无论是哪种开发板,要想开发特定的功能,必先从GPIO开始,HaaS100开发也是一样.如果仅仅利用HaaS100的联网功能,那简直是太浪费了.HaaS100拥有其他开发板所具备的所有的功能,比如 ...

  6. CoppeliaSim学习笔记之差速小车的控制与传感器的驱动

    文章目录 1. 控制篇 2. 传感器篇 2.1 里程计仿真 2.2 TF 发布 2.3 激光雷达仿真 2.4 IMU 仿真   上一章节 CoppeliaSim学习笔记之仿真环境与小车模型的搭建 我们 ...

  7. PID学习笔记-3-正反作用的调节

    PID控制算法-正反作用的调节 正反作用的调节 问题 解决思路 代码实现 正反作用的调节 问题 如果是冰箱等设备,存在随着输出的提升被控量减小的情况下,目前的PID并不适用: 解决思路 因为是调节方向 ...

  8. Cty的Linux学习笔记之查看bash PID

    查看bash PID 当想要查看的进程CPU与内存使用率都很低,结果老师无法在第一行显示是,可以用echo $$查看我们自己的 bash PID 来进行查看,之后再使用top -d 2 -p [PID ...

  9. CC2540开发板学习笔记(六)——AD控制(自带温度计)

    一.实验目的 将采集的内部温度传感器信息通过串口发送到上位机 二.实验过程 1.寄存器配置 ADCCON1(0XB4) ADC控制寄存器1 BIT7:EOC   ADC结束标志位 0:AD转换进行中  ...

  10. S32K系列S32K144学习笔记——模拟SPI

    一用S32K144苦似海,道友,能不用,千万不去用. 本例程基以下如图所示接口操作,MCU为S32K144,开发平台S32DSworkspace 功能描述:模拟SPI,MSIO–>PTD16,M ...

最新文章

  1. mysql 管理端口_MySQL8新增管理端口
  2. 一个工程师对流程管理的思考
  3. Auto.JS 教程
  4. 简单有趣的c语言小程序,一个有趣的小程序
  5. 【线性代数】基础理论归纳
  6. python读音有道-Python实现有道翻译+语音播报
  7. sublime text多文件夹查找关键字
  8. java 垃圾回收入门
  9. Hadoop数据分析实例:P2P借款人信用风险实时监控模型设计
  10. ECharts柱状图图形标签间隔显示
  11. 计算机类外文翻译论文,计算机专业毕业论文 外文翻译.doc
  12. Git的cherry-pick等一些小知识
  13. 关于JPsh极光推送的基本用法和通知介绍
  14. 使用libxl库读取excel文件
  15. 数据结构-图内容总结
  16. 能通过一张照片(2D)得到3D的模型吗?
  17. 博客园——打造不一样的个人博客
  18. JS 倒计时展示小工具
  19. 空间分析方法在计算机上的应用,第4章 GIS空间分析方法.pdf
  20. CubieBoard1【大屏计划】- 霸气平板 - 个人整合帖子【丰富】

热门文章

  1. 大咖访谈丨金星分享2020年直播数据,助农产品如何走上产销快车道
  2. hdu5510Bazinga
  3. 第39级台阶 蓝桥杯
  4. ketchup 消息队列rabbitmq使用
  5. linux wrf 系统_WRF模式学习_从linux安装开始
  6. VIP专区_读书_腾讯网
  7. 文科生学大数据分析吃力吗
  8. thinkphp5 layui分页样式
  9. 小论文之旅(2)——introduction与related work
  10. OC_AddressBook_通讯录