关于PID控制的倒立摆程序与程序解析

关于PID控制的倒立摆程序与程序解析,第1张

include "stc12.h"

#include <intrins.h>

#include"pid.h"

typedef unsigned charuint8

typedef unsigned int uint16

typedef unsigned long intuint32

/*********************************函数声明******************

结构体设定

***********************************************************/

typedef struct PIDValue

{

uint32 Ek_Uint32[3] //差值保存,给定和反馈的差值

uint8 EkFlag_Uint8[3]//差值标志位符号,1则对应的为负数,0为对应的为正数

uint8 KP_Uint8 //比例系数

uint8 KI_Uint8 //积分系数

uint8 KD_Uint8 //塌饥微分显示

uint16 Uk_Uint16 //上一时刻的控制电压

uint16 RK_Uint16 //设定值

uint16 CK_Uint16 //实际值

uint8 Vaule_Flag //输出的值正负标志位,0为正,1为负

}PIDValueStr

PIDValueStr PID //定义一个结P构体

uint16out // 加热输出(PID运算后的输出值)

/***********************************************************************************

增量型PID算式:PID :Uk=KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)]

函数入口: RK(设定值),CK(实际值),KP,KI,KD PID比例参数吵伍

函数出口: U(K)

PID运算函数

**************************************************************************************/

uint16 PID_Calc(uint16 PIDinput)

{

uint32 Temp[3] //中间临时变量

uint32 PostSum //正数和

uint32 NegSum //负数和

Temp[0] = 0 //给储存中间临时变量赋初值

Temp[1] = 0

Temp[2] = 0

PostSum = 0 //给存储所有的正数变量赋升衫或初值

NegSum = 0 //给存储所有的负值变量赋初值

PID.RK_Uint16=180 //设定值为180

PID.CK_Uint16=PIDinput //输入值

if( PID.RK_Uint16 >PID.CK_Uint16 ) //如果设定值大于实际值,就是当前的值比设定值小

{

if( PID.RK_Uint16 - PID.CK_Uint16 >10 )//计算偏差是否大于 piancha=10 ( 这里的10由 piancha 来设定大小,根据实际情况设定)

//if( PID.RK_Uint16 - PID.CK_Uint16 >piancha )

{ //如果偏差大于 piancha=10 不在设定的PID调控范围之内就全速加热

out = 100 //偏差大于piancha=10为上限幅值输出(全速加热)

// PID.Uk_Uint16 = full_speed //全速时的加热值,更具实际情况可自由设定 这里full_speed=100;

}

else //如果偏差小于 piancha=10 再调节的范围内就计算储存起来

{ //下面就是PID算法

Temp[0] = PID.RK_Uint16 - PID.CK_Uint16 // 计算出当前偏差值E(k)

PID.EkFlag_Uint8[1]=0 //E(k)为正数 的标志位 0为正,1为负

//数值移位

PID.Ek_Uint32[2] = PID.Ek_Uint32[1] //存储E(k-2)

PID.Ek_Uint32[1] = PID.Ek_Uint32[0] //储存E(k-1)

PID.Ek_Uint32[0] = Temp[0] //存储E(k)

/****************************************************************************************/

if( PID.Ek_Uint32[0] >PID.Ek_Uint32[1] )//E(k)>E(k-1) 为正数

{

Temp[0]=PID.Ek_Uint32[0] - PID.Ek_Uint32[1] //E(k)-E(k-1) 保存

PID.EkFlag_Uint8[0]=0 // 设定标志位 0为正,1为负

}

else //E(k)<E(k-1)

{

Temp[0]=PID.Ek_Uint32[1] - PID.Ek_Uint32[0] //E(k)-E(k-1)为负数

PID.EkFlag_Uint8[0]=1

}

/*****************************************************************************************/

Temp[2]=PID.Ek_Uint32[1]*2 // 2E(k-1)

if( (PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])>Temp[2] ) //E(k-2)+E(k)>2E(k-1)

{

Temp[2]=(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])-Temp[2] //E(k-2)+E(k)-2E(k-1)为正数

PID.EkFlag_Uint8[2]=0

}

else //E(k-2)+E(k)-2E(k-1)为负数

{

Temp[2]=Temp[2]-(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2]) //2E(k-1)-(E(k-2)+E(k))

PID.EkFlag_Uint8[2]=1

}

/**********************************************************************************************/

Temp[0] = (uint32)PID.KP_Uint8 * Temp[0] // KP*[E(k)-E(k-1)]

Temp[1] = (uint32)PID.KI_Uint8 * PID.Ek_Uint32[0] // KI*E(k)

Temp[2] = (uint32)PID.KD_Uint8 * Temp[2] // KD*[E(k-2)+E(k)-2E(k-1)]

/************************以下部分代码是讲所有的正数项叠加,负数项叠加**************************/

/**************************************KP*[E(k)-E(k-1)]********************************************/

if(PID.EkFlag_Uint8[0]==0)

PostSum += Temp[0] //正数和

else

NegSum += Temp[0]//负数和

/*************************************** KI*E(k)*************************************************/

if(PID.EkFlag_Uint8[1]==0)

PostSum += Temp[1]//正数和

else

//空 *** 作,E(K)>0

/************************************KD*[E(k-2)+E(k)-2E(k-1)]*************************************/

if(PID.EkFlag_Uint8[2]==0)

PostSum += Temp[2]//正数和

else

NegSum += Temp[2] //负数和

/**********************************************U(K)*************************************************/

//PostSum += (uint32)PID.Uk_Uint16

if(PostSum >NegSum ) // 是否控制量为正数

{

out= PostSum - NegSum

PID.Vaule_Flag=0 //PID调节值是正值

}

else //控制量输出为负数

{

out=NegSum-PostSum

PID.Vaule_Flag=1 //PID调节值是负值

}

}

//return out

}

else //如果设定值小于实际值,就是当前的值大于设定值,就不进行PID计算直接输出 0

{

out = 0

}

return out

}

程序使用PID控制算法实现倒立摆的控制。

确定PLC型号和输入/输出设备的参数,并配置PLC的通信参数。

配置PLC的定时器,以确保程序按照固定的时间间隔执行。例如,设置一个10ms的定时器。

编写程序代码,读取倒立摆的角度和角速度传感器的输入信号,兄滑备并计算控制羡毁输出。

根据控制输出信号,控制伺服电机,将倒立摆保持在垂直状态。

下面是一个简单的Omron PLC程序示例,用于控制倒立摆:

// 定义PID控制器参数

float Kp = 1.0

float Ki = 0.1

float Kd = 0.01

// 定义控制误差和积分项

float error = 0

float integral = 0

// 定义控制输出

float control_output = 0

// 定义角度和角速度输入

float angle_input = 0

float velocity_input = 0

// 定义伺服电机输出

float servo_output = 0

// 主程序循环

while (true) {

// 读取角度和角速度输入信号

angle_input = read_angle_sensor()

velocity_input = read_velocity_sensor()

// 计算控制误差和积分项

error = 0 - angle_input

integral += error

// 计算控制输出

control_output = Kp * error + Ki * integral + Kd * velocity_input

// 控制伺服电机

servo_output = control_output

write_servo_output(servo_output)

// 等待定时器到期

wait(10ms)

}

需要注让腔意的是,这只是一个简单的示例程序,实际应用中可能需要进行更多的程序优化和调试,以确保倒立摆的稳定性和可靠性。同时,PLC的型号和程序语言可能会根据实际需求而有所不同,需要根据具体情况进行调整。

用个while循环加两个控件就可以。

首先需要将数值控件的数值类型改为整型(I32,U32,U8,I8均可),判闭然后调整刻度的显示,以及旋转笑冲吵转刻度盘,最后设置鼠标跟随和文本显示即可。

以LabVIEW为平台,结合PID算法,对旋转倒立摆系统设计进行设计研究。在倒立摆旋转过程中,通过编码器将判断位置与角度的相应电碰侍信号反馈给上位机,上位机通过运行程序计算并输出信号进而来控制摆杆的的角度、位置,使倒立摆的摆杆不会下垂。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12352527.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存