这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【fyaocn的智能车DIY的进程贴】

共20条 2/2 1 2 跳转至
助工
2015-10-27 17:00:16     打赏
11楼

5.2.PID调试

——基本原理

P就是比例作用,简单说就是输入偏差乘以一个系数。
I就是积分,简单说就是将输入偏差进行积分运算。
D就是微分,简单说就是将输入偏差进行微分运算
PID基本公式
PID调节器参数整定过程通俗讲就是先把系统调为纯比例作用,逐步增强比例作用让系统振荡,记录下比例作用和振荡周期,然后这个比例作用乘以0.6,积分作用适当延长 KP=0.6 Km
KD= KP×π/4ω
KI= KP×ω/π
公式中KP为比例控制参数;KD为积分控制参数;KI为微分控制参数;Km为系统开始振荡是的比例值;ω为极坐标下振荡时的频率

——具体分析

**************************************************************************/平衡PD调节

int balance(float Angle,float Gyro)

balance=35*Bias+Gyro*0.125;//=== 这是平衡调节的PD控制公式

P的系数是35D的系数是0.125

这个数据测试时后是比较合适的,调整D的系数0.125过大,就会不断摇摆,不容易稳定。调整P的系数35过小,就使平衡容易受扰动,容易失稳。

具体在下一个静止调节中说明。

**************************************************************************/速度PI调节

int velocity(int encoder_left,int encoder_right)

Encoder_Least =(Encoder_Left+Encoder_Right)-0;

Encoder *= 0.8;

Encoder += Encoder_Least*0.2;

这是速度调节的PI控制公式,这个是综合左右编码器的数值来调节运动的速度,这几个系数均小于1,而且系数和0.8+0.2=1。综合是闭环控制,使速度偏差逐步减小,达到减速稳定的作用。调节这些数据超过1,立刻失稳。本实验在标准数值范围内微调,变化不明显,运行保持稳定。OK

**************************************************************************/转向PD调节

int turn(int encoder_left,int encoder_right,float gyro)

Turn_Bias=Encoder_Left-Encoder_Right;

Turn_Bias_Integral+=Turn_Bias;

Turn_Bias_Integral-=Turn_Target;

Turn=Turn_Bias_Integral*2+gyro/12;

这是转向调节的PD控制公式:通过获得左右两个电动机编码器的编码数据获得转向偏差初值Turn_Bias,结合遥控的目标值Turn_Target,经过和z轴旋传感器角度采集值经量化取得最终的转向控制值Turn,用于转向控制。

本公式中turn均是取1作为控制系数,调节各个组成部分的比例,可以改变调整的强度。如给

Turn_Bias_Integral-=Turn_Target 改为

Turn_Bias_Integral-=2*Turn_Target,就可以使调节更灵敏,幅度更大,当然也更不好控制。因为有限幅的语句,所以能保证稳定调节。测试OK。




助工
2015-10-27 17:00:52     打赏
12楼

5.2 PID调节补充试验和分析

在上一个试验中,在采集运动传感器数据并通过串口上传时发现,程序编译运行正常,但是很快平衡小车失稳的情况。经过反复测试发现,在void TIM1_UP_TIM16_IRQHandler(void)  的终端例程中使用printf语句时,但传送1组数据时没有问题,小车可以保持平衡,在传送2组数据时,小车就不容易保持平衡,在稳定中小车不能保持静止,始终左右摇摆,超过3个数据,无法保持平衡。

经分析程序正确,那么是在时序上发生问题了,在串口通讯完成后,小车的姿态继续变化,使采样值经过计算后的补偿量不能保持稳定,如传送2组数据时,就不断摆动。这个可以用2种方法解决:或者提高采样频率,使采样的数据变化更小,或者调整PID控制的系数,使调节能力更强。因为C语言程序不能直接判断采样printf到底占用了多少机器周期,因为和波特率也有关联,所以不容易更进一步分析。不过可以反映出在自动控制时,对于器件选择时机器周期和主频也是一个不可以忽视的问题。



助工
2015-10-28 11:15:44     打赏
13楼

5.3.实现平衡小车直立时处于静止状态 

保持直立的PID综合控制的结果,需要依次进行以下

    Balance_Pwm =balance(Angle_Balance,Gyro_Balance);  

           Velocity_Pwm=velocity(Encoder_Left,Encoder_Right);   

                Turn_Pwm    =turn(Encoder_Left,Encoder_Right,Gyro_Turn)

计算,其中:

——Balance_Pwm实现的是balance=35*Bias+Gyro*0.125计算,根据传感器采集的角度偏差和运动偏差进行校正,其中角度偏差的权重大,是静止时主要的调整因素,加速度偏差在运动中保持平衡时需要考虑该参数,该例程返回值是balance,调整参数35是控制平衡能力的主要方法;

——Velocity_Pwm是转换运动中编码器的数值,给最终的调速加权,在静止时,该值基本为0,该程序返回值是Velocity;

——Turn_Pwm是最终综合计算出的调整电机控制值,因为2个电机反装,所以最后的偏差值,一个是加,另一侧要减去,最终返回值是turn

本实验,调整不同的系数观察平衡能力的变化。实验的结果很有意思,

- 参数设为35,表现最优,迅速稳定,而且基本保持在原地不动;

- 参数设为15,表现尚可,可以稳定,但是扰动稍大,就像喝醉酒一样,摇摇摆摆,才能稳定下来;

- 参数设为5,基本不能独自保持平衡,一定要扶稳后放手才能平衡,在阻力大的地毯能平衡,在光滑的桌面,立刻飞车;

- 参数设为70,可以保持平衡,但变成了多动症,即使很小的扰动也要快速左右摆动才可以停下,而且摆动幅度大;

- 参数设为100,这时很难保持平衡,即使保持稳定状态也是反复摆动,基本不能静止。

结论:

这个参数设置很重要,决定了平衡车的平衡性能,可用范围在15-70之间,最优是35。


助工
2015-10-28 13:01:28     打赏
14楼

5.4.实现平衡小车绕八字行走

这个控制主要实现2个要点:

1、保持小车前进状态,同时给右转或左转信号,这是只能保持左转或保持右转唯一信号互斥;

这个在初始置初值时先定右转,

u8 Flag_Qian = 1,Flag_Hou = 0,Flag_Left =0,Flag_Right=1; 

2、在编码器计数到一定数值后重置0并换向,原来左转换右转,右转换左转。

实现语句比较简单,

if (T_count > 480)
{
Flag_Left = !(Flag_Left);
Flag_Right = !(Flag_Left);
T_count=0;
}
T_count++;
具体转向值需要测试,本实验选择480。如果选择数值小,就是不断换向,走成S形。这个数值是大致走成圆形后换向,就形成8字形。

实际实验中发现Flag_Left的类型是unsigned char,用!求反操作好像不能得到理想结果,因为没有合适的调试工具,直接用笨办法,

if (Flag_Left ==1) 

Flag_Left =0;Flag_Right=1}

else if (Flag_Left !=0)

Flag_Left =1;Flag_Right=0}


实验过程中发现换向时小车抖动比较厉害,调整movement=100,减小速度,抖动就不那么明显了。



助工
2015-10-28 16:02:32     打赏
15楼

5.4.实现平衡小车绕八字行走

这个控制主要实现2个要点:

1、保持小车前进状态,同时给右转或左转信号,这是只能保持左转或保持右转唯一信号互斥;

这个在初始置初值时先定右转,

u8 Flag_Qian = 1,Flag_Hou = 0,Flag_Left =0,Flag_Right=1; 


2、在编码器计数到一定数值后重置0并换向,原来左转换右转,右转换左转。


实现语句比较简单,

if (T_count > 480)
{
Flag_Left = !(Flag_Left);
Flag_Right = !(Flag_Left);
T_count=0;
}
T_count++;
具体转向值需要测试,本实验选择480。如果选择数值小,就是不断换向,走成S形。这个数值是大致走成圆形后换向,就形成8字形。

实际实验中发现Flag_Left的类型是unsigned char,用!求反操作好像不能得到理想结果,因为没有合适的调试工具,直接用笨办法,

if (Flag_Left ==1) 

Flag_Left =0;Flag_Right=1}

else if (Flag_Left !=0)

Flag_Left =1;Flag_Right=0}


实验过程中发现换向时小车抖动比较厉害,调整movement=100,减小速度,抖动就不那么明显了。



助工
2015-10-28 16:04:26     打赏
16楼

5.5.实现小车自主避障

直接例程中选择Mode_Bizhang=1,就进入超声波避障模式。在sys.h中用#define定义为1,可以直接进入避障模式。避障模式是通过Read_Distance()来实现的,

void Read_Distane(void)

{

PAout(2)=1;

delay_us(15);

PAout(2)=0;

if(TIM2CH4_CAPTURE_STA&0X80)//

{

Distance=TIM2CH4_CAPTURE_STA&0X3F;

Distance*=65536; //

Distance+=TIM2CH4_CAPTURE_VAL; //

Distance=Distance*170/1000;

//printf("%d \r\n",Distance);

TIM2CH4_CAPTURE_STA=0; //

}

}

Velocity()程序中,当Distance距离大于500时,设定movement步进加700,这样可以在自平衡的过程中实现避障的运行。

if(Distance<100)

{

Movement+=700 ;

if(1==Flag_Qian)

Movement=700;

}

对比最初的2.5版本,壁障模式运行不了,经过测试,发现是读取距离的失效,主要是反馈时间出了问题,在启动mainRead_Distane()正确反映了读取的距离,而且非常敏感,对于手靠近就可以侦测出来。


但是最后积累到最大值,而且始终不更新,这样distance始终保持大于100的状况,无法跟踪壁障。这个问题又和程序的设置与时序有关系,解决起来要花不少时间,不过再3.5版中有关避障部分程序条理更清晰,因此这个问题没有体现出来。

需要指出的是,侦测的数值应该是毫米,也就是10010厘米,500是半米,那么还是用100更好测,因为用手就好了。

房间比较黑,不大清楚,而且蓝色LED还闪着眩光,效果差点意思。


助工
2015-10-28 21:41:32     打赏
17楼
看起来蛮不错的样子,加油哦

助工
2015-10-29 13:07:20     打赏
18楼

5.6 实现小车利用线性CCD巡线 以及实现体感控制(利用KINECT或者姿态传感器)分析

这组实验没有实现,因为订购时只订了NRF24和超声探头,所以只好围观。不过可以分析下。

5.6.1 CCD巡线在更新的例程里已经很容易地实现了,可以根据地上的线路,通过CCD图像分析判断是否偏离该线,然后控制左右侧的伺服电机来进行闭环控制。可以这么理解,就是平衡小车是在z轴上的闭环控制,通过MPU运动传感器来进行逆向调节;而CCD识别是在y轴的闭环控制,来通过视频采集的图像差delta来进行控制。

这个过程需要调整的是行进速度,视频采样分析周期之间的平衡,控制的系数设定就是比较重要的。

从前面的试验可以看出,这个项目的参数匹配是相当的重要,范例中大神已经都给出了实践值,省了太多的事情。从我对程序修改的过程发现,即使小的修改,也有可能造成小车的不正常工作,即使从逻辑上来看毫无问题。

感谢下原创,这个是真心滴。

5.6.2 关于体感控制,其他盆友都是按照另外的姿态传感器采集姿态,然后转换成前后左右方向控制信号来实现,对小车来说,仍然是通讯控制。

我原来设计了一个体感控制逻辑,就是在平衡车平衡状态时,通过加速度传感器来判断是否是人为给出的推力,然后顺着这个方向和推的力度来同向运动,就好像是感知到了推的动作一样,但是在采集加速度值得设定时,始终没有调试出适合的数值来区分正常的自动平衡和人为的干扰,所以本实验是失败的。不过可以把主要的程序部分列在后面,


void Push_test()
{
// sensing push action and reacted.
if (myabs(Accel_Y)>200)
{

if( Accel_Y>0) Flag_Qian=1;             
else if( Accel_Y<0) Flag_Hou=1;      
 else {};
}
// printf("%f\n",Accel_Y);
}

把Push_test();加在中断执行handler里。

需要注意的是Accel_Y需要在main.h里定义为全局变量,如Gyro_balance一样。



助工
2015-10-29 13:20:58     打赏
19楼

6 小结

这个DIY的活动收获很多,主要是熟悉了STM32F系列的芯片结构,MPU传感器的原理应用,SPP-C蓝牙的原理和使用以及中断调用和时序之间的配合。

不过更重要的是体验的自动控制和程序控制之间的原理构建和实践的关系。

这个活动的小车,提供了一个非常完备的开发和测试平台,不仅在平衡车上时适用的,而且在通过综合多种传感器进行运动控制的方式上都是非常有趣和好用的,资料里提到的飞行器控制就是很好的例子。

不过还是有些体会希望能够分享:

1)这个范例中采用了ARM-CMSIS的中间层控制,但是在整个程序中,除了定时器中断TIM用到了有关定义以外,其他的均是原创的编码过程,读懂理顺还是要不少时间,如果能更多用CMSIS可能更好。而起我觉得如果编了这么多代码,其实完全可以用直接访问,代码量会更省。(未必正确)

2)整个调试和实验的过程,发现工作量最大的不是下载程序,编程,还有和小车玩耍。而是读懂芯片资料和各种参数匹配,换算的理解和测试。多数时候上下调整完发现还是原来的参数准确,性能好,不由地佩服下。

3)整个开发的过程,我理解时序的配合非常重要。在本程序中定时器中断选择了5ms的周期,其他例程占用的时间片都可以很好配合。在调试中,我多次用printf语句进行串口通讯,多次引起工作失败。初步分析是串口通讯速率低,选最大115200,如果通讯数据多时,占用的时间片明显增大,很容易影响平衡采样的周期,如果延伸到下一次定时中断,就会破坏程序运行的完整性。所以,用调试器会避免此问题,这个算是小体会。

4)原创2.5版程序小小的瑕疵是对于第二组编码器访问的代码重复问题,这个在超声壁障的过程中会发生,因为有可能重定义,在若干的代码中都需要定义。后来在3.5版本中用了预定义#ifdef,思路更条理,改善很多。

因为时间有限,还同时进行了android app的开发。还在进行中,安装了android studio,导入源码时发现是用ADT编写的,不少语句不能很好识别。重装Eclipse+SDK,然后开发进行中。




助工
2015-10-30 12:02:16     打赏
20楼

7 手机APP之蓝牙通信开发

因为换操作系统所以android的开发平台拖久了才搞好。用一个蓝牙串口通讯的小程序一样可以控制小车。

如图

这个程序用命令行控制,输入a,则停止小车,输入b,小车前进。

这个要程序小小修改下,

涂黄部分就是控制编码,因为命令行不能输入ASII码的0x00和0x01,所以用0x61代表停,对应小写字符a,用0x62代表停,对应小写字符b。

给个视频


在安卓开发中首先要开放蓝牙访问的权限:



然后,Android提供BluetoothAdapter类蓝牙通信。通过调用创建的对象的静态方法getDefaultAdapter()。

其语法如下

private BluetoothAdapter BA;
BA = BluetoothAdapter.getDefaultAdapter();
为了使用设备的蓝牙,调用下列蓝牙ACTION_REQUEST_ENABLE。其语法如下:
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 0);

启用了蓝牙功能之后,可以通过调用 getBondedDevices()方法来获取配对设备列表。其语法如下:
private SetpairedDevices;
pairedDevices = BA.getBondedDevices();

之后就可以用蓝牙功能了,当然在安卓手机开发中,就是设置常用的textbox,inputbox等button和图形属性就可以了。如果不是需要非常炫的界面,直接在新建工程的样板上增加小工具就好了。



视频地址:http://www.tudou.com/v/LSOZRLJkZo0/&bid=05&rpid=328261405&resourceId=328261405_05_05_99/v.swf

共20条 2/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]