51PID算法程序
时间:10-02
整理:3721RD
点击:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit a=P0^0;
sbit led=P1^5;
sbit b=P0^1;
sbit en=P1^0;
sbit key1=P2^0;
sbit key2=P2^1;
uint num,nums;
uint std_speed[5]={10,30,90,110,128}; //存放期望速度脉冲数
float PID_M_Kp =3,PID_M_Ki = 0.7,PID_M_Kd =0.5; //定义 Kp、Ki、Kd 三个参数
uint PID_m_add ; //PID 的增量输出
struct
{
uint current_error; //当前差值
uint last_error; //上次差值
uint prev_error; //上上次差值
}PID_M; //定义一个名为 PID_M 的结构体
void delay(uint n)
{
uchar i,j;
for(i=0;i<n;i++)
for(j=0;j<110;j++);
}
void pwm23_duty(uint t) //将增量值输出传给电机执行
{
uchar i,j;
j=1;
for(i=0;i<t;i++)
a=1;
for(i=0;i<j;i++)
a=0;
}
void Motor_ctl(uint i)
{
uint P,I,D; //定义局部变量
PID_M.prev_error=PID_M.last_error; //更新每次的差值
PID_M.last_error=PID_M.current_error; //更新每次的差值
PID_M.current_error=std_speed[i]-nums; //更新每次的差值
P=PID_M_Kp*(PID_M.current_error-PID_M.last_error); //比例 P 输出公式
I=PID_M_Ki* PID_M.current_error; //积分 I 输出公式
D=PID_M_Kd*(PID_M.current_error-2*PID_M.last_error+PID_M.prev_error); //微分 D 输出公式
PID_m_add=P+I+D+PID_m_add; //电机的 PID 增量值输出
if(PID_m_add>100)PID_m_add=100; //限制电机的最大速度
if(PID_m_add<1)PID_m_add=0; //限制电机的最小速度
pwm23_duty(PID_m_add); //将增量值输出传给电机执行
}
void main()
{
en=1;
b=0;
EA=1;
EX0=0;
IT0=0;
ET0=1;
TR0=1;
nums=0;
TMOD=0x01;
TH0=(65536-45872)/256; //定时器T0的高8位设置初值,每50ms产生一次中断
TL0=(65536-45872)%256; //定时器T0的低8位设置初值,每50ms产生一次中断
PID_m_add=10;
while(1)
{
pwm23_duty(10);
if(key1==0)
{
delay(5);
if(key1==0)
{
while(1)
{
led=0;
Motor_ctl(0);
}
}
}
if(key2==0)
{
delay(5);
if(key2==0)
{
while(1)
{
led=0;
Motor_ctl(1);
}
}
}
}
}
void time0() interrupt 1
{
TH0=(65536-45872)/256; //定时器T0的高8位设置初值,每50ms产生一次中断
TL0=(65536-45872)%256; //定时器T0的低8位设置初值,每50ms产生一次中断
nums=num;
num=0;
}
void it0() interrupt 0
{
num++;
led=1;
delay(100);
}
求大神帮忙看下为啥不好使啊?
理论上应该可行啊
我用槽型光耦计数,一圈记20个。
希望大家帮帮忙
#define uint unsigned int
#define uchar unsigned char
sbit a=P0^0;
sbit led=P1^5;
sbit b=P0^1;
sbit en=P1^0;
sbit key1=P2^0;
sbit key2=P2^1;
uint num,nums;
uint std_speed[5]={10,30,90,110,128}; //存放期望速度脉冲数
float PID_M_Kp =3,PID_M_Ki = 0.7,PID_M_Kd =0.5; //定义 Kp、Ki、Kd 三个参数
uint PID_m_add ; //PID 的增量输出
struct
{
uint current_error; //当前差值
uint last_error; //上次差值
uint prev_error; //上上次差值
}PID_M; //定义一个名为 PID_M 的结构体
void delay(uint n)
{
uchar i,j;
for(i=0;i<n;i++)
for(j=0;j<110;j++);
}
void pwm23_duty(uint t) //将增量值输出传给电机执行
{
uchar i,j;
j=1;
for(i=0;i<t;i++)
a=1;
for(i=0;i<j;i++)
a=0;
}
void Motor_ctl(uint i)
{
uint P,I,D; //定义局部变量
PID_M.prev_error=PID_M.last_error; //更新每次的差值
PID_M.last_error=PID_M.current_error; //更新每次的差值
PID_M.current_error=std_speed[i]-nums; //更新每次的差值
P=PID_M_Kp*(PID_M.current_error-PID_M.last_error); //比例 P 输出公式
I=PID_M_Ki* PID_M.current_error; //积分 I 输出公式
D=PID_M_Kd*(PID_M.current_error-2*PID_M.last_error+PID_M.prev_error); //微分 D 输出公式
PID_m_add=P+I+D+PID_m_add; //电机的 PID 增量值输出
if(PID_m_add>100)PID_m_add=100; //限制电机的最大速度
if(PID_m_add<1)PID_m_add=0; //限制电机的最小速度
pwm23_duty(PID_m_add); //将增量值输出传给电机执行
}
void main()
{
en=1;
b=0;
EA=1;
EX0=0;
IT0=0;
ET0=1;
TR0=1;
nums=0;
TMOD=0x01;
TH0=(65536-45872)/256; //定时器T0的高8位设置初值,每50ms产生一次中断
TL0=(65536-45872)%256; //定时器T0的低8位设置初值,每50ms产生一次中断
PID_m_add=10;
while(1)
{
pwm23_duty(10);
if(key1==0)
{
delay(5);
if(key1==0)
{
while(1)
{
led=0;
Motor_ctl(0);
}
}
}
if(key2==0)
{
delay(5);
if(key2==0)
{
while(1)
{
led=0;
Motor_ctl(1);
}
}
}
}
}
void time0() interrupt 1
{
TH0=(65536-45872)/256; //定时器T0的高8位设置初值,每50ms产生一次中断
TL0=(65536-45872)%256; //定时器T0的低8位设置初值,每50ms产生一次中断
nums=num;
num=0;
}
void it0() interrupt 0
{
num++;
led=1;
delay(100);
}
求大神帮忙看下为啥不好使啊?
理论上应该可行啊
我用槽型光耦计数,一圈记20个。
希望大家帮帮忙
有点意思.。
很有价值啊!值得借鉴啊!
学习了。
好好学习一下,谢谢
小编试过了么?可行不
非常有点不错的啊
给好资料点个赞啊
有点狠腻害的样子啊
pid还是不错的啊
好算法啊,支持的啊
给pid算法点个赞了,