#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算法,对旋转倒立摆系统设计进行设计研究。在倒立摆旋转过程中,通过编码器将判断位置与角度的相应电碰侍信号反馈给上位机,上位机通过运行程序计算并输出信号进而来控制摆杆的的角度、位置,使倒立摆的摆杆不会下垂。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)