由于之前写的那篇直立车调试写的不是很直观,所以看了论坛里5,6篇有关于直立车调试的帖子,被吸引了好久,其中夏季在下季同学的文章非常不错,所以我复制了过来,以后可以多看看。
实验目的:按键修改PID各个参数值,通过Nrf24l01无线通讯把修改的数据传递给小车,进行调试,参数内容实时显示在OLED屏上。
PID这个东西还是比较难的。不仅需要理论基础,还需要多年的调试经验,掌握起来比较困难。和我一样的初学者可以看看这个PID通俗易懂.pdf
源程序中涉及到的PID控制主要有直立PD控制、速度PI控制、转向PD控制。
(1)直立PD控制
最上面红圈数值为平衡的角度中值,也就是小车重心,注释已经很清楚了。这一数值要先调好,否则会影响后面参数的调试。我的方法是,看小车平衡时OLED屏上的
angle角度值,会在一个范围变化,取最大值与最小值的中间值。例如:我的小车在359度与2度之间徘徊,所以我取0.5。
下面两个参数分别为直立时P参数和D参数,需要后面调的。我用变量BP和BD代替。
(2)速度PI控制
如果没有速度PI控制,小车会往重心方向加速运行,并倒下。
红圈两个参数分别为速度P参数和I参数,我用变量VP和VI代替。
(3)转向PD控制
如果没有转向PD控制,小车会在原地慢慢的打转。
红圈两个参数分别为转向P参数和D参数,我用变量TP和TD代替。
来看看另一块板子上的按键排布如下
只用到前4个按键:
S1用于BP,BD,VP,VI,TB,TD六个参数的选择键;
S2用于BP,BD,VP,VI,TB,TD六个参数的选择键(相反方向);
S3用于BP,BD,VP,VI,TB,TD六个参数数值增加键;
S4用于BP,BD,VP,VI,TB,TD六个参数数值减少键;
软件修改
(1)修改按键程序key.c和key.h
void KEY_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRH&=0X0000FFFF;
GPIOB->CRH|=0X88880000;//PB12 PB13 PB15 PB15 上拉输入
GPIOB->ODR|=0X0000F000; //PB12 PB13 PB15 PB15 上拉
}
void KEY_Scan (void)
{
if(s1==0)
{
delay_ms(10);
if(s1==0)
{
s1num++;
while(!s1);
if(s1num==7) s1num=0;
}
}
if(s2==0)
{
delay_ms(10);
if(s2==0)
{
s1num--;
while(!s2);
}
}
if(s1num!=0)
{
if(s3==0)
{
delay_ms(10);
if(s3==0)
{
while(!s3);
if(s1num==1) BP+=1;
if(s1num==2) BD+=0.005;
if(s1num==3) VP+=0.5;
if(s1num==4) VI+=0.001;
if(s1num==5) TP+=0.5;
if(s1num==6) TD+=0.002;
}
}
if(s4==0)
{
delay_ms(10);
if(s4==0)
{
while(!s4);
if(s1num==1) BP-=1;
if(s1num==2) BD-=0.005;
if(s1num==3) VP-=0.5;
if(s1num==4) VI-=0.001;
if(s1num==5) TP-=0.5;
if(s1num==6) TD-=0.002;
}
}
}
(2)修改无线通讯程序24l01.c中的void NRF24L01()函数
void NRF24L01(void)
{
u8 mode=1,count;
u8 tmp_buf[33];
if(mode==0)//RX模式
{
RX_Mode();
while(1)
{
if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,则显示出来.
{
key_flag=1;
BP=(tmp_buf[1]*256+tmp_buf[2])/10.0;
BD=(tmp_buf[3]*256+tmp_buf[4])/1000.000;
VP=(tmp_buf[5]*256+tmp_buf[6])/10.0;
VI=(tmp_buf[7]*256+tmp_buf[8])/1000.000;
TP=(tmp_buf[9]*256+tmp_buf[10])/10.0;
TD=(tmp_buf[11]*256+tmp_buf[12])/1000.000;
s1num=tmp_buf[13];
oled_show();
}else break;
};
}else//TX模式
{
TX_Mode();
while(1)
{
if(++count>100)count=0;
tmp_buf[1]=BP*10/256;
tmp_buf[2]=(u16)(BP*10)%256;
tmp_buf[3]=BD*1000/256;
tmp_buf[4]=(u16)(BD*1000)%256;
tmp_buf[5]=VP*10/256;
tmp_buf[6]=(u16)(VP*10)%256;
tmp_buf[7]=VI*1000/256;
tmp_buf[8]=(u16)(VI*1000)%256;
tmp_buf[9]=TP*10/256;
tmp_buf[10]=(u16)(TP*10)%256;
tmp_buf[11]=TD*1000/236;
tmp_buf[12]=(u16)(TD*1000)%256;
tmp_buf[13]=s1num;
if(NRF24L01_TxPacket(tmp_buf)==TX_OK)
{
key_flag=1;
}else
break;
}
}
}
(3)修改显示程序show.c中oled_show()程序
void oled_show(void)
{
OLED_Display_On(); //显示屏打开
//=============显示BP=======================//
OLED_ShowString(00,0,"BP");
OLED_ShowNumber(30,0, BP,3,12);
OLED_ShowString(48,0,".");
OLED_ShowNumber(54,0, (u16)(BP*10)%10,1,12);
if(s1num==0) OLED_ShowString(100,0," ");
if(s1num==1) OLED_ShowString(100,0,"BP");
//=============显示BD=======================//
OLED_ShowString(00,10,"BD");
OLED_ShowNumber(30,10, BD,3,12);
OLED_ShowString(48,10,".");
OLED_ShowNumber(54,10, (u16)(BD*1000)%1000,3,12);
if(s1num==2) OLED_ShowString(100,0,"BD");
//=============显示VP=======================//
OLED_ShowString(00,20,"VP");
OLED_ShowNumber(30,20, VP,3,12);
OLED_ShowString(48,20,".");
OLED_ShowNumber(54,20, (u16)(VP*10)%10,1,12);
if(s1num==3) OLED_ShowString(100,0,"VP");
//=============显示VI=======================//
OLED_ShowString(00,30,"VI");
OLED_ShowNumber(30,30, VI,3,12);
OLED_ShowString(48,30,".");
OLED_ShowNumber(54,30, (u16)(VI*1000)%1000,3,12);
if(s1num==4) OLED_ShowString(100,0,"VI");
//=============显示TP=======================//
OLED_ShowString(00,40,"TP");
OLED_ShowNumber(30,40, TP,3,12);
OLED_ShowString(48,40,".");
OLED_ShowNumber(54,40, (u16)(TP*10)%10,1,12);
if(s1num==5) OLED_ShowString(100,0,"TP");
//=============显示TD=======================//
OLED_ShowString(00,50,"TD");
OLED_ShowNumber(30,50, TD,3,12);
OLED_ShowString(48,50,".");
OLED_ShowNumber(54,50, (u16)(TD*1000)%1000,3,12);
if(s1num==6) OLED_ShowString(100,0,"TD");
if(key_flag==1) OLED_ShowString(100,50,"OK");
//=============刷新=======================//
OLED_Refresh_Gram();
}
观察现象
先看看OLED屏的显示状态
一手要按键,另一只手要拍摄,没有多余的手去扶小车,所以上电直接给源程序中的PID初值。
小车装上测距模块和无线模块,拆下OLED屏(因为只有一个,不够使),装在另一块板子上。
视频不知道怎么了,在自己电脑上播放器播放正常,传到优酷就倒过来了,不太影响效果,就不更改了。
一开始上电,传给小车的是源程序的PID参数值,小车左右摆动大约7cm。按键增加BP值,增加到BP=70,小车左右摆动大约4cm。重启板子,小车PID值恢复到初始状态,小车左右摆动恢复到大约7cm。哈哈,接下来可以尽情的调试PID了。