平衡小车制作——PID

平衡小车制作——PID,第1张

位置闭环控制就是根据编码器的脉冲累加测量电机的位置信息,得到控制偏差,然后通过对偏差的比例、微分、积分进行控制,使得偏差趋于零

c语言的实现

P用于提高相应速度,I用于减小静差,D用中桥于抑制震荡

速度闭环控制是根据单位时间获取的脉冲数测量电机速度信息,对目标值进行比较

理论分析

直立环使用PD控制

在调试直立环,要在定时器中断服务函数屏蔽速度换和转向环

首先估计kp的取值范围,陪我们设置7200代表占空比百分百

设定kp值为7200,那么小车在10°就会满转

确定参数的镇培含御笑原则是:kp一直增加,出现大幅度低频抖动

kd一直增加,直至出现高频抖动

确定了pd的最大数,×0.6就是需要的参数

我们对速度进行低通滤波

一般可以把ki的值设置为kp/200

kp最大值=7200/(160*50%)

//P1.1(T0):Count They Distance

//P0.4:Tx

//P0.5:Rx

#include <C8051F310.h>历尘谈 //SFR declarations

#include <stdio.h>//Standard I/O definition file

#include <math.h>//Math library file

#include <Intrins.h>

#include <absacc.h>

unsigned int j,i

char a=0

unsigned int t=0

//sbit led=P0^2

//P0.0(PWM0):给定左轮速度.

sbit vls=P0^4//P0.4(GPIO):给定左轮方向.

sbit vlf=P0^6//P0.6(T0) :反馈左轮速度.

sbit dlf=P1^0//P1.0(GPIO):反馈左轮方向.

//P0.2(PWM0):给定右轮速度.

sbit vrs=P0^5//P0.5(GPIO):给定右轮方向.

sbit vrf=P0^7//P0.7(T0) :反馈右轮速度.

sbit drf=P1^1//P1.1(GPIO):反馈右轮方向.

int ol//左轮给定值

int len

int len_1,len_2

int lyn_1,lyn_2

int vl1,vl2//反馈左轮速度值(取样周期内的方波数)

int lfz//运算后赋给PWM的值

int lyn,lynn

int lun=0,lun_1=0//偏差校正值 即校正PWM输出

int lunp,luni,lund//PID 校正值

int or//右轮给定值

int ren

int ren_1,ren_2

int ryn_1,ryn_2

int vr1,vr2/肢碰/反馈右轮速度值(取样周期内的方波数兄昌)

int rfz//运算后赋给PWM的值

int ryn,rynn

int run=0,run_1=0//偏差校正值 即校正PWM输出

int runp,runi,rund//PID 校正值

float kp=2.0//比例系数1.8

float kd=0.2//微分系数0.4

float lki//积分系数

void pio_init(void)

void sys_init(void)

void t01_init(void)

void TIME3_INT(void)

void PID(void)

void interrupt_init(void)

void delay(unsigned int x)

void pwm1_1(void)

void main(void)

{

PCA0MD &= ~0x40//关闭

pio_init()//P11为测距输入端

sys_init()

t01_init()

pwm1_1()

TIME3_INT()

interrupt_init()

vls=1vrs=0

while(1)

{

ol=50

or=50

delay(1000)

ol=100

or=100

delay(1000)

ol=-50

or=50

delay(1000)

}

}

void PID(void)

{

/****************左轮PID调节******************/

if(dlf==1)

{

lyn=(vl2*256+vl1)//dlf是左轮反馈方向,0表示向前 vl=TL0

}

else

{

lyn=-(vl2*256+vl1)//dlf=1表示是向后退,速度应该为负值

}

len=ol-lyn//误差=给定速度-反馈速度(取样周期内的方波数)

if(abs(len)<8)//30

{

lki=1.4//ki值的确定1.4

}

else

{

lki=0.05//积分系数:如果 | 给定值-反馈值 | 太大

} //则就可以不引入积分,或者引入的很小0.05

lunp=kp*(len-len_1)//比例校正

luni=lki*len//积分校正

lund=kd*(len-2*len_1+len_2)//微分校正

lun=lunp+luni+lund+lun_1//总校正

/*************新旧数据更新*************************/

len_2=len_1

len_1=len//len:当前取样周期内出现的速度偏差len_1:上次取样周期内出现的速度偏差

lun_1=lun//lun:当前取样周期内得出的PWM校正值lun_1:上次取样周期内得出的PWM校正值

/*************新旧数据更新*************************/

if(lun>255)

{

lun=255//正速度

}

if(lun<-255)

{

lun=-255//负速度

}

if(lun<0)

{

vls=1

PCA0CPH0=-lun

}

if(lun>=0)

{

vls=0

PCA0CPH0=lun

}

/****************右轮PID调节******************/

if(drf==0)

{

ryn=(vr2*256+vr1)//drf是右轮反馈方向,0表示向前 vl=TL0

}

else

{

ryn=-(vr2*256+vr1)//dlf=1表示是向后退,速度应该为负值

}

ren=or-ryn//误差=给定速度-反馈速度(取样周期内的方波数)

if(abs(ren)<8)//30

{

lki=1.4//ki值的确定1.4

}

else

{

lki=0.05//积分系数:如果 | 给定值-反馈值 | 太大

} //则就可以不引入积分,或者引入的很小0.05

runp=kp*(ren-ren_1)//比例校正

runi=lki*ren//积分校正

rund=kd*(ren-2*ren_1+ren_2)//微分校正

run=runp+runi+rund+run_1//总校正

/*************新旧数据更新*************************/

ren_2=ren_1

ren_1=ren//len:当前取样周期内出现的速度偏差len_1:上次取样周期内出现的速度偏差

run_1=run//lun:当前取样周期内得出的PWM校正值lun_1:上次取样周期内得出的PWM校正值

/*************新旧数据更新*************************/

if(run>255)

{

run=255//正速度

}

if(run<-255)

{

run=-255//负速度

}

if(run<0)

{

vrs=1

PCA0CPH1=-run

}

if(run>=0)

{

vrs=0

PCA0CPH1=run

}

//因为这里的PCA0CPH0越大,对应的电机速度越小,所以要255来减一下

}

void pio_init(void)

{

XBR0=0x00//0000 0001

XBR1=0x72//0111 0010 时能弱上拉 T0T1连接到脚口P06、P07 CEX0、CEX1连接到脚口P00、P01

P0MDIN=0xff//模拟(0)数字(1) 1111 0011

P0MDOUT=0xc3//开漏(0)推挽(1) 1111 1111

P0SKIP=0x3c//0011 1100

P1MDIN=0xff//1111 1111

P1MDOUT=0xfc//

P1SKIP=0x00//1111 1111

}

void sys_init(void) //12MHz

{

OSCICL=0x43

OSCICN=0xc2

CLKSEL=0x00

}

void pwm1_1(void) //PWM的初始化

{

PCA0MD=0x08//PCA时钟为12分频

PCA0CPL0=200//左轮

PCA0CPM0=0x42//设置左轮为8位PWM输出

PCA0CPH0=200

PCA0CPL1=200//平衡校正

PCA0CPM1=0x42//设置为8位PWM输出

PCA0CPH1=200

PCA0CN=0x40//允许PCA工作

}

void t01_init(void)

{

TCON=0x50//计数器1、2允许

TMOD=0x55//定时器1、2采用16位计数功能

CKCON=0x00

TH1=0x00//用于采集左轮的速度

TL1=0x00

TH0=0x00//用于采集右轮的速度

TL0=0x00

}

void TIME3_INT(void)

{

TMR3CN = 0x00//定时器3为16位自动重载

CKCON &= ~0x40

TMR3RLL = 0xff

TMR3RLH = 0xd7

TMR3L = 0xff

TMR3H = 0xd7

TMR3CN |= 0x04

}

void T3_ISR() interrupt 14 //定时器3中断服务程序

{

//led=~led

EA=0

TCON &=~0x50//关闭计数器0、1

vl1=TL0//取左轮速度值

vl2=TH0

vr1=TL1//取右轮速度值

vr2=TH1

TH1=0x00

TL1=0x00

TH0=0x00

TL0=0x00

PID()//PID处理

TMR3CN &=~0x80//清中断标志位

TCON |=0x50//重新开计数器0、1

EA=1

}

void interrupt_init(void)

{ IE=0x80

IP=0x00

EIE1|=0x80

EIP1|=0x80

}

void delay(unsigned int m) //延时程序

{

for(i=0i<2000i++)

{

for(j=0j<mj++){_nop_()_nop_()}

}

}

这些都是自动控制系统所涉及的概念。

1、首先说明,PID调节单元接收与输出的都是电信号;

2、自动控制技术,综合了【给派伍镇定单元橘租】、【调节单元】、【输出与执行单元】、【测量单元】、【反馈单元】等,基本原理是:给定单元提供设定控制目标,调节单元比较给定与反馈信号的差别并进行PID运算(比例、积分、微分)最后输出控制信号,输出与执行单元指用前面的控制信号转换为实际设备的物理量输出,测量单元检测物理量实际值,反馈单元将检测到的信号进行处理转换再反馈到调节单元,如此构成【闭环】自动调节控制系统;

3、物理量-电量的转换是在测量单元完成的,电量-物理量的转换是在输出与执行单元完成的;

4、结合实例就说来话长了,恐怕要给你一篇论文啦,呵呵,即便是要讲清楚PID调节器,也要上千字才行啊。

补充:

各个单元都可以求出【传递函数】,须用到【拉普拉斯变换】的知尘粗识。

传递函数的作用就是从物理事物建立起相应的【数学模型】,然后通过数学手段去分析、研究它。


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存