转 C#实现PID控制的模拟测试和曲线绘图
C#实现PID控制的模拟测试和曲线绘图
本文分两部分,一部分是讲PID算法的实现,另一部分是讲如何用动态的曲线绘制出PID运算的结果。
首先,PID算法的理论模型请参考自动控制理论,最早出现的是模拟PID控制,后来计算机成为控制器,由于计算机控制是一种采样控制,需把模拟PID转换成数字PID,就是模拟PID的离散化,两者中间是香浓定理。当然这些和编程是没关系的,我们只需要有个数字模型就能开展后面的工作了。
- private float prakp, praki, prakd, prvalue, err, err_last, err_next, setvalue;
- int MAXLIM, MINLIM;
- //PID valculate
- public float pidvalc()
- {
- err_next = err_last; //前两次的误差
- err_last = err; //前一次的误差
- err = setvalue - prvalue; //现在的误差
- //增量式计算
- prvalue += prakp * ((err - err_last) + praki * err + prakd * (err - 2 * err_last + err_next));
- //输出上下限值
- if (prvalue > MAXLIM)
- prvalue = MAXLIM;
- if (prvalue < MINLIM)
- prvalue = MINLIM;
- return prvalue;
- }
模拟出来的结果是下面这样,出现输出值收敛振荡后稳定下来。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace PIDtest
- {
- class Class1
- {
- private float prakp, praki, prakd, prvalue, err, err_last, err_next, setvalue, deadband;
- int index, UMAX, UMIN, MAXLIM, MINLIM;
- public float Prakp
- {
- set
- {
- prakp = value;
- }
- get
- {
- return prakp;
- }
- }
- public float Praki
- {
- set
- {
- praki = value;
- }
- get
- {
- return praki;
- }
- }
- public float Prakd
- {
- set
- {
- prakd = value;
- }
- get
- {
- return prakd;
- }
- }
- public float Setvalue
- {
- set
- {
- setvalue = value;
- }
- get
- {
- return setvalue;
- }
- }
- public Class1()
- {
- pidinit();
- }
- //PID参数初始化
- public void pidinit()
- {
- prakp = 0;
- praki = 0;
- prakd = 0;
- prvalue = 0;
- err = 0;
- err_last = 0;
- err_next = 0;
- MAXLIM = 800;
- MINLIM = -200;
- UMAX = 310;
- UMIN = -100;
- deadband = 2;
- }
- //PID valculate
- public float pidvalc()
- {
- err_next = err_last;
- err_last = err;
- err = setvalue - prvalue;
- //抗积分饱和
- if (prvalue > UMAX)
- {
- if (err < 0)
- index = 1;
- else
- index = 0;
- }
- else if (prvalue < UMIN)
- {
- if (err > 0)
- index = 1;
- else
- index = 0;
- }
- //积分分离
- else
- {
- if (Math.Abs(err) > 0.8 * setvalue)
- index = 0;
- else
- index = 1;
- }
- //死区
- if (Math.Abs(err) > deadband)
- prvalue += prakp * ((err - err_last) + index * praki * err + prakd * (err - 2 * err_last + err_next));
- else
- prvalue += 0;
- //输出上下限制
- if (prvalue > MAXLIM)
- prvalue = MAXLIM;
- if (prvalue < MINLIM)
- prvalue = MINLIM;
- return prvalue;
- }
- }
- }
- <pre name="code" class="csharp">using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Data;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- namespace WindowsFormsControlLibrary2
- {
- public partial class UserControl1 : UserControl
- {
- public UserControl1()
- {
- InitializeComponent();
- }
- Graphics g;
- //List<float> l = new List<float>();//储存要绘制的数据
- Pen p = new Pen(Color.Green, 1);
- Pen p1 = new Pen(Color.Red, 1);
- //PointF ptfront = new PointF();
- //PointF ptbehond = new PointF();
- private int jiange = 86;//网格间距
- private int pianyi = 2;//绘图两点之间间隔
- private float value1;
- //Random r=new Random ();
- PointF[] data;
- public float Value
- {
- get
- {
- return value1;
- }
- set
- {
- this.value1 = value;
- }
- }
- //获得一个数据
- private void getdata()
- {
- data[data.Length - 1].Y = value1;
- for (int i = 0; i < data.Length - 1; i++)
- data[i].Y = data[i + 1].Y;
- //放数据到LIST
- //if (l.Count >= 80)
- //{
- // l.RemoveAt(0);
- // l.Add(value1 );
- //}
- }
- //初始化数据存放数组
- private void UserControl1_Load_1(object sender, EventArgs e)
- {
- timer1.Enabled = true;
- timer1.Interval = 100;
- //l.Add(0);
- data = new PointF[pictureBox1.Width / pianyi];
- for (int i = 0; i < data.Length; i++)
- data[i].X += pianyi * i;
- /*
- for (int i = 0; i < pictureBox1.Width / pianyi; i++)
- {
- l.Add(r.Next(50));
- }
- */
- }
- private void pictureBox1_Paint_1(object sender, PaintEventArgs e)
- {
- g = e.Graphics;
- //画网格线
- //for (int i = this.pictureBox1.Width; i >= 0; i -= jiange)
- //g.DrawLine(p, i, 0, i, this.pictureBox1.Width);
- //for (int i = this.pictureBox1.Height; i >= 0; i -= jiange)
- //g.DrawLine(p, 0, i, this.pictureBox1.Width , i);
- for (int i = 0; i < pictureBox1.Width; i++)
- if (i % jiange == 0)
- g.DrawLine(p, i, 0, i, this.pictureBox1.Height);
- for (int i = 0; i < pictureBox1.Height; i++)
- if (i % jiange == 0)
- g.DrawLine(p, 0, i, pictureBox1.Width, i);
- //画数据曲线
- // ptbehond.X = 0;
- /*
- for (int i = 0; i < l.Count - 1; i++)
- {
- ptfront.X = ptbehond.X;
- ptfront.Y = l[i];
- ptbehond.X += pianyi;
- ptbehond.Y = l[i + 1];
- g.DrawLine(p1, ptfront, ptbehond);
- }
- */
- g.DrawCurve(p1, data);
- }
- //绘图刷新周期
- private void timer1_Tick_1(object sender, EventArgs e)
- {
- getdata();
- this.pictureBox1.Refresh();
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- namespace PIDtest
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- timer1.Interval = 5;
- timer1.Enabled = true;
- }
- Class1 pid = new Class1();
- //Random r = new Random();
- private void timer1_Tick(object sender, EventArgs e)
- {
- userControl11.Value = pid.pidvalc();
- }
- private void button1_Click(object sender, EventArgs e)
- {
- pid.pidinit();
- pid.Setvalue = float.Parse(textBox1setvalue.Text);
- pid.Prakp = float.Parse(textBox1prakp.Text);
- pid.Praki = float.Parse(textBox2praki.Text);
- pid.Prakd = float.Parse(textBox3prakd.Text);
- }
- }
- }
转 C#实现PID控制的模拟测试和曲线绘图的更多相关文章
- STM32L476应用开发之七:流量的PID控制
在气体分析仪使用过程中,为了力求分析结果的准确性,一般要求通过的气体流量尽可能的稳定.为了保证流量控制的稳定,我们采用PID调节来控制气路阀门的开度. 1.硬件设计 我们采用的流量计为气体质量流量计, ...
- PID控制及整定算法
一.PID控制算法 PID是比例.积分.微分的简称,PID控制的难点不是编程,而是控制器的参数整定.参数整定的关键是正确地理解各参数的物理意义,PID 控制的原理可以用人对炉温的手动控制来理解.阅读本 ...
- Android单元测试与模拟测试详解
测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...
- 两轮自平衡小车双闭环PID控制设计
两轮自平衡小车的研究意义 ...
- 数字式PID控制的应用总结
PID控制是一个二阶线性闭环控制器,通过调整比例.积分和微分三项参数,使得大多数的工业控制系统获得良好的闭环控制性能.PID控制优点:a. 技术成熟,b. 易被人们熟悉和掌握,c. 不需要建立数学模型 ...
- PID控制最通俗的解释与PID参数的整定方法
转自->这里 PID是比例.积分.微分的简称,PID控制的难点不是编程,而是控制器的参数整定.参数整定的关键是正确地理解各参数的物理意义,PID控制的原理可以用人对炉温的手动控制来理解.阅读本文 ...
- 经典PID控制及应用体会总结
经典PID控制及应用体会总结 PID控制原理 PID是一种线性控制器,它根据给定值rin(t)与实际输出值yout(t)构成控制方案: 重点关注相关算法是如何对偏差进行处理的: PID控制器各校正环节 ...
- springboot2.0入门(四)----mock模拟测试+单元测试
一.本节主要记录模拟测试.单元测试: 二.mock 测试 1.1什么是Mock? 在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象 ...
- 四轴飞行器飞行原理与双闭环PID控制
四轴轴飞行器是微型飞行器的其中一种,相对于固定翼飞行器,它的方向控制灵活.抗干扰能力强.飞行稳定,能够携带一定的负载和有悬停功能,因此能够很好地进行空中拍摄.监视.侦查等功能,在军事和民用上具备广泛的 ...
随机推荐
- java.lang.IllegalArgumentException: An invalid domain [.test.com] was specified for this cookie解决方法
当项目中使用单点登录功能时,通常会使用cookie进行信息的保存,这样就可以在多个子域名上存取用户信息. 比如有三个domain分别为test.com,cml.test.com,b.test.com这 ...
- 在pycharm中开发vue
一.在pycharm中开发vue ''' webstorm(vue) pycharm(python) goland(Go语言) idea(java) andrioStuidio(安卓) Php(PHP ...
- ArchLinux 无密码Samba 配置
安装上迅雷后就必须把硬盘挂上去开个Samba,然后边下电影边看,这就是一个Nas了. 开搞! pacman -S samba 安装samba,然后进入/etc/samba/目录 vim smb.con ...
- 论文阅读:Deep Attentive Tracking via Reciprocative Learning
Deep Attentive Tracking via Reciprocative Learning 2018-11-14 13:30:36 Paper: https://arxiv.org/abs/ ...
- 【JS】Js对json的转换
将json字符串转换为json对象的方法.在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键 例如: JSON ...
- codeforce gym/100495/problem/K—Wolf and sheep 两圆求相交面积 与 gym/100495/problem/E—Simple sequence思路简述
之前几乎没写过什么这种几何的计算题.在众多大佬的博客下终于记起来了当时的公式.嘚赶快补计算几何和概率论的坑了... 这题的要求,在对两圆相交的板子略做修改后,很容易实现.这里直接给出代码.重点的部分有 ...
- Windows10家庭版用户无法在计算机管理更改权限的解决办法
问题描述:今天因为动了注册表导致windows登陆界面只剩下一个管理员账号,而平常用的账号不知所踪~这个问题本来很好解决,但是由于在用的笔记本安装的是Windows家庭中文版,无法通过计算机管理在本地 ...
- java泛型使用教程
参考: java 泛型 Java泛型中E.T.K.V等的含义 一.Java泛型中E.T.K.V等的含义 E - Element (在集合中使用,因为集合中存放的是元素) T - Type(Jav ...
- Hibernate注意项
Hibernate实体规则 1.持久化类提供无参数构造 2.成员变量私有,提供getset访问,提供实行 3.持久化类属性,尽量使用包装类型 4.持久化类需要提供oid与数据库中的主键列对应 5.不要 ...
- 【分布式搜索引擎】初识Elasticsearch
一.Elasticsearch是什么? Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎. Elasticsearch是一个实时分布式搜索和分析引擎.它让你以前所未 ...