这是去年参加的单车拉力组代码调试记录,分享给大家
小车的调试日志
2020.11.6
简单的做了一下小车的寻迹,没有加入PID控制,转弯的方法为:检测的一边没有边线,就直接转弯。这种方法只适合固定的赛道和固定的舵机电机的值,不具备智能特性。
发现单片给的底层驱动代码,不能满足实际的要求,之后对底层代码进行了修改,修改的函数为PWM_UpdatePwmDutycycle,在修改之前,他的占空比只能在0-100之间,之后通过修改,使得它的可以调区间变大
2020.11.7
按照逐飞科技的教程,使用python3.7.3,简单的建立了一个模型,只训练了一次。同时将电机的参数传到了上位机上,准备开始调试PID,以及学习python。
2020.11.8
搭建了python+Pycharm的环境,简单的学习使用编译器,开始学习tensorflow的库,争取一个星期学会python+tensorflow。
学习了tensorflow图的概念,简单的使用tensor进行运算。
2020.11.10
开始编写pid控制代码,P:当前误差乘以一个系数因子;I:积分项,某个时段内,所有误差之和乘以一个系数因子;D:微分项,两个误差的差值,即两个误差之间的斜率乘以一个系数因子。
初步建立好了PID的模型,开始对转向环进行调节,整体的效果不是特别理想。计算误差的方法采用对中线进行运算,前后两个点的差值,然后对整条直线的差值进行累加,得到一个误差值,当误差值为零时,认为这个是一条直线;这个误差值为正或者负的时候,对应右弯道和左弯道。但是最后的效果为,直线计算出来的误差特别大,而弯道几乎没有误差,这是刚好相反的结果。之后提出了一下的几种解决方案:
方案一:在计算误差的函数中,使用了三个一样的循环,增加了单片机的负担,做了重复的工作,之后可以考虑改成一个循环运行。
方案二:在计算误差时,最后一次运算的值不在那个数组中,可能会导致出现错误,修改最后的值看情况。
方案三:推到之前的方案,采用计算中线均值的方法,来获得误差,具体还是要看最后的效果。
2020.11.11
今天验证了之前的方案一以及方案二,发现确实存在上述所提到的问题,多个for循环导致延时的情况,最后一次计算的数值不在这个数组里面,尤其是方案二涉及的问题,最整个的误差计算有着非常大的影响,在更改了计算的次数之后,发现得到了我们想要的误差,并且能够很直观的判断出是直线还是弯道。
在这个程序的框架下存在的问题:车在快入弯道的时候,误差会出现一次很强烈的跳变,导致车提前转弯,加上车速过快,直接冲出赛道;还存在的问题,车在快出弯道的时候,会判断成直线,舵机就自己回到直线的情况下,在查看摄像头运行的图像中发现,在车速达到一定的情况下,赛道有很大一部分信息不被采集到,导致判断失误。现在加入新的约束条件,看最后是否可以达到预期的效果值。
晚上结果与隔壁四轮组的讨论,发现了我们小车现在存在的问题:对于我们之前使用的通过差值来计算中线误差,存在很大的问题,我没有给他一个标准的中线来定义小车的位置,使得小车在边线的时候,还是不能察觉自己当前的位置,再者就是过弯道的时候,会出现中线跳变的情况,导致整个误差计算的过程会与实际产生偏离,不能达到实际想要的效果。
结果和他们的讨论,对于图像的处理的改进做出了如下的方案:在屏幕正中间定义一条中线,并且以这条中线为参考基准,之后通过对中线上的点进行加权求和,之后再与标注中线进行比较,通过比较判断当前车的位置。现在先尝试使用中线求和的方法对误差进行计算,放弃之前的计算中线误差的办法。
在尝试这个新的方法中,发现对于直线的效果很好,小车可以判断当前的位置,对车身进行校正。但是对于弯道,随着弯道的出现,上面的中线像素点会丢失,到时算出来的平均误差会偏小,导致判断错误,使得舵机打的角度不够,不能够顺利的过弯,后期仍需要改进。
2020.11.12
今天采用了均值的方法计算中线误差,在之前的基础上进行了改进,之前是中线误差减去中线之后再除以一个系数,这样导致的结果是整个系统对误差的判断不够准确,分的级数不够。现在采用的是中线的误差减去标准中线的值,在这样的情况下,每一点的变化都可以被检测出来,这样可以做到大弯道舵机打大角度,小弯道舵机打小角度。
现在遇到的问题是,由于转弯时中线误差会比较的大,导致还没有到最佳的入弯时机时,舵机就开始打了。对于这个问题,采用的解决办法就是,对整个误差中线上的点加一个加权,使得越靠近车身到的点越有价值,远离车的点价值不大。
PID调试过程中,在只加P比例项的时候(P值为5.5,I和D为0),车最高可以跑到210的占空比,但是车的整体稳定性会下降,左右摇摆会很严重,车子过右弯道的时候比较顺利,左弯道的时候会出现提前入弯的情况,可能是图像处理上的问题。之后开始加入微分项D,在纯D值下,车子运行比较稳定,很少出现左右摇摆的情况,但是过弯角度有点大。最后尝试P值和D值一起加入,正在试验一组比较完美的数据。实际测试过程,会发现加入P值后,即使在D值的作用下,还是会出现车左右摇摆,出弯角度不好等问题。
2020.11.13
今天计算了两个轮胎需要的转速差。
2020.11.14
开始电感的学习使用,初步了解电感的工作方式。采用中间一个、左右各一个的方式排布电感,对电感采集回来的数据进行软件处理,进行软件滤波。在经过归一化处理的电感数据后,之前的毛刺都会被滤掉,得到一个较为稳定的曲线,之后用这个曲线进行误差的计算。
2020.11.15
采用差比和的办法,对电感误差曲线进行拟合,因为采集的电感值是一个类似于正弦波的曲线,所以在进行拟合的时候,不能采用之前的办法进行拟合。通过了解差比和的公式,设置几个固定的参数,通过调节各个参数的值,尽量的去拟合一条波动较小的一条曲线,就现在拟合的曲线来说,上下波动的误差还是较大,在实际的应用中可能会出现舵机摇摆大的问题。之后确定电磁寻迹的方案之后,开始进行电磁寻迹,在这个过程中还要不断的对误差曲线以及电感值得归一化曲线进行进一步的优化拟合。
2020.11.18
记录一下这几天所做的事情。在对电感进行操作的时候,遇到了很多问题,尝试了各种的方法,最终采用的方法为利用左右电感的差值作为误差,之后对这个误差进行PID的操作。整体的这个效果很不错,车子在整个的运行中没有大的摆动,过弯还是很顺利。但是会出现个别弯道过不去的情况,现在初步考虑为pid的值设定不是特别的适合,其次就是电机没有做差速,转弯的角度可能不够。
现在赛道的环岛还是不能过,车在过环岛的时候会有明显的标志,可以作为判断为环岛的标志,后续会加上对环岛的处理,现在进行电机的调速,做差速,使过弯更加的顺滑。
2020.11.20
为了开始训练AI,加入长前瞻电感进行试车,发现在长前瞻的情况下,车的运行结果不是特别理想,经常出现冲出赛道的情况,一方面是由于车速不够快的原因,车子又提前打弯;另一方面是由于对整个误差的处理不是很到位,这一方卖在观察隔壁四轮组的车子舵机之后,发现一个问题,我们的车,即使在中间平衡的状态,我们车的舵机依旧会左右摇摆,而别的组没有,对于这个问题,在观察了我们的波形之后会发现,最后输出的误差是一条类似于正弦波的曲线,所以在中间时刻,它还是一条正弦波,所以舵机会来回震荡。对于这个问题还在尝试新的解决办法,就是左右两个电感进行相加减的运算,因为采集回来的左右电感值相位基本是相同的,所以做减法会使一部分的误差会消掉,从而得到一条更加稳定的曲线。
在今天的调试过程中,电感的运放电路不知道什么原因,输出的电压非常的大,超过了AD采样口的额定电压,会对单片机有一定的损伤,具体是什么原因导致的,目前还没有找出,后续可能还会出现类似的问题,有待排查。
现在以为没有电感采样口,不能进行下去。
2020.11.21
今天调试了电机的PID,观察看各个参数P、I、D对整个系统的影响,通过上位机进行观察,至于后面各个参数的设置以及差速的设置,需要在后续发车的过程中不断总结。
2020.11.22
今天完成了LQ的串口移植,能够通过上位机接收到单片机发出的数据,但是只能发送ASCII码,具体应用时不是特别的方便,整体下来的使用下过不是特别好,目前还没有找到很好的解决办法。
2020.11.24
在运放打板期间,没有进行太多的实际操作,就对整体的方案进行了思考,提出了以下的一个观念:对于电感寻迹,很难做到预判前方很远的赛道情况,这就要求我们对整个车的控制更加的精确,对误差的获取也要更加的精确,否则整个车的运行会十分不稳定,所以对于PID控制,舵机依旧采用PD控制,电机采用PID控制,电机全程一直按照一个速度进行运行,过弯道时,根据舵机打的角度进行运动学分析,然后为了保证顺利的过弯,同时要适当的降低车的速度,所以这里暂时通过前后获得的误差值得差值作为衡量这个的标准,前后相差越大,说明车偏移轨迹的距离就越大,这个时候减低速度。
这段时间还阅读了一些国赛队伍的技术文档,获得了很大的启发,对于电感的寻迹,主要还是采用差比和的方法,尝试不同的差和组合,观察车在顺时针逆时针的运行情况,考察代码的对称性。
2020.12.09
转做单车组,开始的时候调试的是STC8A8K的芯片,之后会使用STC16F系列的芯片,现在还是在调试8A的芯片。外围电路的调试基本完成,蜂鸣器、按键、编码开关、编码器等。
作为单车平衡重要部分的陀螺仪,我们采用的是ICM20602陀螺仪,滤波的算法采用的是卡尔曼滤波,因为IC不带DMP的姿态解析,所以这部分代码是借鉴网上的卡尔曼滤波写的,从最终的效果来看,角速度计部分基本已经完成,可以转化成角度使用,而陀螺仪部分(也就是)角速度这一环还没有调试好,之前本来是调试好的了,后面突然出现了问题,这一部分代码不能使用,后面还会继续调试陀螺仪。
接下来要完成四轮PID代码的移植,转化到单车上去,写一套切换PID的代码。
2020.12.11
今天发现陀螺仪的一个问题,在使用卡尔曼滤波进行滤波解算姿态的时候,随着时间的增加,会发现解算的速度越来越慢,单片机解算出来的姿态与实际的姿态,出现了延时现象,而且随着时间的推移,这个现象越来越明显。初步估计是随着时间的推移,对传感器数据的数据积分越来越大,导致计算量增大,最终与实际有一定的偏差。后面查阅一些资料发现,卡尔曼滤波的计算量,需要MCU有较强的计算能力,所以就目前STC的单片机来看,卡尔曼滤波的方案可能会被摈弃掉。
后续将采用另外一种的方法进行姿态解算,互补融合算法。首先,陀螺仪的噪声基本在低频中,加速度计的噪声大多位于高频中,这两个信号都带有偏转角的信息,所以,现在对这两个分别过高通滤波器和低通滤波器,之后对这两个进行互补融合,首先尝试一阶滤波器,之后看实际的效果,再采用二阶滤波器。
2020.12.14
对于之前卡尔曼滤波,出现的随着时间的推移,计算量越来越大的问题,在参考16级学长的卡尔曼滤波代码之后,找到了问题所在。参数C_t的初始化定义出现了一点问题,在改成float之后,程序整个的运行过程变得正常,解算的效果与实际的效果基本符合。在只解算陀螺仪姿态的时候,解算一次的时间大概在1.3ms左右,加上切换PID之后,控制舵机的解算速度在1.8ms左右,解算速度基本满足要求。
2020.12.15
在进行卡尔曼滤波之后,还是会出现偶然的跳变点,对于单车这种平衡姿态解算要求高的系统,这种大的偶然的跳变可能是危险的,会单片做出错误的判断,可以采用加一个低通滤波器来解决这个问题。
加入低通滤波器,需要对权重系数进行调试,低通滤波器会存在相位滞后的情况,所以要对寻找一个合适的权重参数。
再反观切换PID系统,当出现跳变的时候,此时前后误差会很大,切换到加速度环进行调节,一定作用上对这种跳变情况有缓解作用。
不过还是会尝试经过一个低通滤波器看最后的效果。
2020.12.17
在加入低通滤波器之后,之前出现的偶尔跳变的情况得到了改善,曲线变得更加的平滑,但是会存在相位滞后的情况,后续会根据实际的情况,对滤波的频率进行调整。
2020.12.19
开始写模糊控制算法,在这个过程中,要尽量的较少代码的运行时间,空出更多的时间去做别的事情。
2020.12.25
打了第一版的核心板,发现如下的问题:1.芯片的地没有接上,原因是不能通过铺铜去把所有的地接在一起,必须通过手动连线的方式,让地全部接在一起;2.STC16F芯片是低电平复位,复位引脚悬空,通过万用表测量,是低电平,所以单片机可以下载程序,但是不能正常的工作,因为一直在复位的条件下,通过外接10K电阻与5V电相接,可以工作。
对于其他引脚的测试,引脚都可以置高低电平,可以正常使用。后面根据之前遇到的问题,开始第二版的核心板的制作,并制作第一版的母板。
目前把所有的代码整合到一起,代码的初步架构已经全部完成,在模拟车的运行过程中,符合控制目标。
2020.12.28
单车车模到了之后,开始调车。发现如下几个问题:1.单片机莫名的会跑死,不工作,原因待查明;2.之前没有考虑PWM输出的问题,所以在打板的时候,没有留意这个问题,舵机和电机的PWM输出都用的PWMA,所以不能输出不同的频率,之后要使用PWMA和PWMB分别控制电机和舵机。
对于单片机跑死的原因,后面采用定时器中断来检测。
在调试单车平衡的过程中,车子想跑起来平衡,还是有很多的困难。
2020.12.29
对于昨天出现单片机死机的问题,最后查明是单车车身导电,导致单片机死机。
PWM的问题,目前还没有解决。
近期软件部分所要完成的任务:
1. 确定单车的临界倾斜角度
2. 确定单车的临界行驶速度
3. 将单车舵机的打角和单车的倾角关联起来
4. 验证切换PID的可行性,确定切换的阈值
2020.12.30
在整个陀螺仪姿态解析的过程中,解析出来的是90度的角,但是,这部分的数据,只有在车身阈值角度的范围内是有用的信息,超出这个范围,车身可能就会倾倒,此时再想控制车身平衡,已经无法使其平衡了。所以,就使用阈值范围内的值,其余的值不予讨论。
2021.1.4
制作了第二版的核心板、母板以及各种驱动模块,发现问题如下:
1. 核心板上依旧不能使用USB进行下载,而且复位按键不能使用;
2. 母板上存在一些问题,如部分模块排布过于紧密,不好插模块使用,后期还要调整布局;
3. 电机驱动板不能使用;
4. 运放模块没有验证是否可以使用;
车的整体框架基本已经完成,后期将开始调试代码,验证方案的正确性。
2021.3.1
开学第一天。寒假简单的完成单车代码的编写,采用传统的PID,在舵机的控制中加入了积分项I,目前情况来看,单车平衡跑的距离大概半米左右。由于左边比右边重一些,所以机械平衡还没有调好。之后还要寻求PID三个参数之间的平衡,达到直立的最佳效果。
单车PCB板子以及机械机构还要进一步的优化。
2021.3.10
记录单车直立的第一天,在直立的过程中,发现了很多问题,发现的问题如下:1.车身整体结构左右不是十分对称,车把手位置中间的大螺丝的松紧需要调整,建议是紧一点的,不然车身会存在抖的问题;2.陀螺仪滤波问题,陀螺仪本身采集的数据存在很大的噪声,需要进行互补融合尽量的解算出实际的角度偏差,后面调试的过程中最大的问题是解算出的角度会超过实际值,之后再回到实际值,这个问题需要引起重视,这样会导致舵机打两次角度,会影响平衡;3.PID参数调节过程中,PID三个参数都引入,P稍微大一点30——50,累计误差需要进行限幅度,不然退耦过程时间过长,且建议I给小一点0.05——0.0001,对于参数D是稳定整个系统的关键部分,直接采用陀螺仪采集的角速度值,乘以系数K(0.1左右)进行处理,防止过大影响整个控制,参数D在1——5之间。
总体归结下来,数据的处理很关键,直接影响车是否平衡,之后调节PID参数。
2021.3.18
在之前的代码上进行了优化,采用卡尔曼滤波,对滤波的几个系数进行搭配,主要是噪声协方差(Q_angle)和采样时间(dt),通过搭配这两个参数,是解算出来的数据更加的贴近实际的值并且尽量的减少噪声。同时对整个车身进行配重,适当的增加右边的重量,但是还是会发现左边会比右边重一点,这个问题留到后面的一版板子中进行处理。
在现在的控制系统中,放在1MS中断函数中进行处理,对应的参数为P = 41,I = 0.001,D = 0.2,同时微分项误差的引进为陀螺仪直接采集的加速度值(为经过滤波处理)。在这个控制系统下,可以看到,比之前的控制系统更加的稳定,很少出现在中间平衡位置抖动的情况,并且车可以直立的更加久。
后续进行单车的循迹以及电机闭环,如果运算能力达不到预期的效果,可能会采用伪双核的方案,专门的有一个CPU进行数据的处理,然后发送个决策的CPU,提高整个控制的效率。
2021.3.26
昨天发现引用逐飞的驱动库时,角速度的引入存在问题,导致滤波出来的结果时错误的,这就解释了之前一些不能解释的现象,在解决这个问题之后,车的稳定性得到了很大的提高,可以跑更久的直线。
但是现在又出现了新的问题,就是更换电池盒之后,参数调配一直到不了一个很耦合的状态,PID参数的设置存在问题,整个系统的抗干扰能力不强。
2021.3.29
基本完成车的直立,可以维持较久的平衡。之前没有对积分项进行清零,并且之前使用的微分项存在方向问题,写反了。
后面继续优化参数,增加平衡的抗干扰性。
后续开始循迹调试。
2021.3.30
单车的平衡直立基本完成,总结的经验如下:
1. 在PID的三个参数中,P的作用的是主导整个的系统的左右偏移量,P要足够的大,才能保持单车的直立;I的作用是车的惯性量,建议给小小一点,大了之后会影响车回正的速度,而且要对总的误差进行限幅,最后还要对总的误差进行清零(每次过零点的时候,防止出现车突然倒地的情况);D的作用是阻碍车的运动,减少超调现象的出现。
2. 整个车的机械结构尽量的稳定,每次更改结构之后就要重新更改参数,增加工作量,且之前的参数不具备太大的参考意义。车的整体重心尽量保持一致。
3. 在陀螺仪滤波时,分清楚底层驱动变量。后面才发现之前的一个变量使用错误,导致前面调试了一个错误的方向,参数没有太大的参考意义。
4. 电机尽量的实现闭环,这样会增加发车以及车运行过程中的稳定性。
5. 陀螺仪滤波很重要,这个会直接影响整个系统的正确判断,滤波后的曲线尽量的光滑,没有较大的突变点,在单车的控制系统中,一个较大的突变点就会导致单车倒地。尤其要注意静止时突然出现的方向尖峰,及其致命。
6. 要是滤波算法没有问题的情况下,会存在一套与之较为耦合的参数,所以,滤波参数确定之后,要精细的调节PID参数,先P再I最后D。
蜂鸣器 P43
按键 P42 P41
编码器 DIR=P35 A=P34
拨码开关 P72 P73
ADC P00 P01 P14 P15 P16
无线串口 UART4_TX_P03 UART4_RX_P02 SET_P04_RTS
舵机 P74
电机 P60 P62
ICM20602 (陀螺仪)SCL-P25
SDA-P23
SA0-P24
CS-P26
ISP(显示屏) SCL-P25
SDA-P23
RST-P20
DC-P21(液晶命令位引脚定义)
CS-P22
BL-P27(液晶背光引脚定义)
单车组调试规范
在整个车的框架搭好之后,开始整个的调试,小组三个人,一天三班倒。为了更好的调车,方便交流,采用如下的规则:
1. 调试参数时,需记录下每个参数对应的数值,以及该参数下的效果
2. 组员在使用框架代码时,如果有改动,则需要表明改动的日期、姓名、改动的地方。
3. 如有添加新的代码,则也需要注明编写的时间、姓名、以及简单的介绍一下该函数的大概用途。
4. 在整个代码框架搭好之后,就在这个框架上进行修改,每个人在完成自己工作后,将文件名改成日期+姓名+上午/下午/晚上,下一个人在此代码上继续修改。
5. 每个小组成员,在完成自己当天任务后,写一个简短的日记,记录自己今天所作的事情以及遇到的问题。
程序下载(代码不完整,仅供参考):
16F代码(带DFP).7z
(332.89 KB, 下载次数: 13)
|