平衡小车项目解读日志

2016/3/31

1.      关于6050陀螺仪模块问题

2.      今天开始着手平衡小车项目,蓝牙模块不用关心,只要知道可以连接,再判断串口发来的指令即可。

3.      好像比较简单的是使用DMP,通过结合DMP,可以将我们的原始数据转换成四元素输出,再通过四元素算出欧拉角,从而得到yawroll 和 pitch。

4.      因为做的是平衡小车,那么就不需要roll 和 yaw,直接通过pitch即可。

 

 

2016/4/1

1.      昨天卡在一个比较愚蠢的问题上,就是我很少自己配置工程什么的,所以当测试卖家发来的例程的时候,编译不通过,最后发现是要在keil4下打开才可以用,期中涉及的问题我也不想深究,毕竟配置工程什么的不是我学习的重点。

2.      今天总结了一条经验:解决问题,一定要善于使用最简单的方法!不做无用功,也不能浪费宝贵的时间!比如我发现他们的例程下进去,小车根本就不能动,排查问题,肯定是资料问题,我问了卖家以后,他们发了新的资料,成了!工程编译错误,网上百度一下,好像keil4下可以正常使用,那就装一个keil4,成了!这就是最简单的解决问题方法,不要自己死磕,不能转牛角尖。

3.      MPU6050:首先我要做的就是能够使用例程,将MPU获取的数据打印出来,这样便于调试,也便于我接下来的学习;然后深入理解6050的工作方式和通信方式(IIC通信);再学习6050在DMP方法下,输出的数据怎么可以整定成小车的姿态,那么平衡小车中比较关键的内容就结束了!

因为还是写成项目日志比较清楚,所以准备写项目日志,暂停写直至平衡小车项目结束,重新开始学战舰开发板的其他模块。

 

 

2016/4/8

1.      终于度过了学校里的期中考试,可以重新开始项目了。小车的项目虽然比较难理解,但是我还是有很大的兴趣的,因为这是在做实实在在能够拿得出手的项目啊!

2.      继续6050:出现问题,就是平衡小车上没有串口输出,下载都是用stlink,那么这样就不能直观的看到6050读出的数据了。在这之前,我还用了我买的战舰开发板,准备将里面的数据通过串口打印,但是,板子上留出了接口,而且和我买的6050接口有区别,即使一根一根的把排线插上去,也没办法读出来,一直显示错误,这种问题我并不想深究,因为有可能根本就是两个模块的引脚定义不同,在这里,我就当STM32已经通过IIC总线,将想要的数据读取了出来了。

3.      IIC:平衡小车上的原理图说明,PB10为IIC的SCL,PB11为IIC的SDA信号线。

4.      电机的初始化:使用的电机驱动模块是LV8731驱动芯片

5.      平衡小车的电机:现在的PCB上画的对应的引脚如下

 

FR

AT1

AT2

STEP

左边电机

L_FR -> PB15

L_AT1 -> PC6

L_AT2 -> PB0

L_STEP -> PB9

右边电机

R_FR -> PB1

R_AT1 -> PA5

R_AT2 -> PA4

R_STEP -> PA1

 

 

2016/4/10

1.      关于步进电机:昨天晚上把卖家提供的例程进行了修改,由于提供的资料很少,所以只能先从例程开始,我发现,电机的正转反转是通过FR控制,那么电机动起来就要通过STEP的取正再取反的过程,使得电机活动起来。至于AT1和AT2两个引脚是什么我还没有搞明白,等今天晚上回去再研究,观察小车电机的驱动方法,以及PWM控制,这样电机部分就结束了。

2.      我们现在用的电机应该是混合式两相四线步进电机。

3.      LV8731驱动芯片介绍:这个芯片可以用来驱动平衡小车上的两个4线两相步进电机,而且使用这个芯片使得电机的驱动变得更加简单,手册中说明特长为,加入STEP信号、励磁STEP就可以行进。

4.      LV8731端子说明:ATT1(保持通电电流切换端子),ATT2(保持通电电流切换端子),STEP(STEP信号输入端子),FR(CW/CCW信号输入端子)。

5.      ATT1,ATT2:也就是程序中的AT1和AT2两个端口,这两个端子是用来设置VREF输入电压的衰减功能。原来这两个端口只是为了在电机保持通电时,设定较低的输出电流,可以省电,主要是在使用充电电池让小车工作的时候,可以保持较长时间的工作,而不至于电池消耗过快。

6.      那么除了以上两个引脚,我现在还缺FR和STEP两个引脚问题。从我之前的总结,FR用来控制方向,STEP信号用来变换产生电机转动的动力(通俗的讲)。

7.      FR在手册上说明,就是用来控制正转反转的。也就是说,通过这个驱动芯片,我可以直接通过设置FR这个端子(引脚)的电平就可以控制电机的正反转,简直方便!

8.      STEP:由此可以看出,STEP的向上跳变可以使得电机励磁STEP移动,不断的跳变,电机不断的变换相位,如果此时的FR为恒定,那么在STEP不断向上跳变的过程中,电机就会沿着一个方向,以固定的角度(术语为步距角,此电机为1.8度)。其中的ST端子是CHIP有效端子,也就是芯片使能信号。这里的STP信号才是STEP。

9.      发现一个问题,就是两个电机的FR在某一时刻为相反的电平时,连个电机的转动方向才是相同的,这个原因其实很简单,因为两个电机是对称的,那么当一个电机正转时,另一个电机就必须在它对称的方向反转才能都往一个方向转动,就像镜子往一个方向梳头道理一样。

10.  第二个问题,电机驱动的过程中,如果STEP信号跳变的频率过高的话,也就是STEP频繁的高低电平跳变,那么电机会难以正常转动,并发出轰鸣。这个问题的原因:步进电机存在一个空载启动频率,也就是要在这个频率之下,电机才能正常工作,要是想要加速,那么就要有一个从低速到高速变化的过程,才能达到一定的高速运动的目的,一般设置的启动频率 = 2 * (360 / 1.8),也就是转动一周的脉冲数的两倍,针对这个电机是400,单位应该就是Hz。更多的问题可以看看这个博客,我感觉总结的很好!http://blog.sina.com.cn/s/blog_5e1491780100ucid.html

11.  第三个问题,这个问题比较麻烦,两个电机并不能在比较高或者比较低频率的时候,保持两个电机相同的状态,当频率较低的时候,右边电机竟然直接不动了,而左边的电机运作比较正常,这个问题是硬件物理上,到时候可以通过调节PWM波修正,应该也不算大问题。

12.  还遗留了一个问题,就是现在使用驱动芯片,所以驱动步进电机变得很容易很简单,但是关键的,步进电机到底是如何实现转动的?

13.  步进电机的原理:步进电机就是将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。现在可以确定的是,我使用的电机为四线两相电机,也就是说,有AB两相,四线就是分为A、 A-、B、 B-这四根线,此时也就是,只要将这四根线轮流的,按照上图的顺序轮流供电,就可以使得电机进行按照步距角转动动作。详细的可以参照此博客http://blog.csdn.net/djimon/article/details/7290297

14.  至此,电机以及电机驱动部分结束。总结一下,现在项目中使用驱动芯片,这个芯片极大的方便了我们编程,只要我们设置了电机在通电状态下的电流大小,然后设置FR,也就是电机转动方向,通过STEP的向上脉冲驱动电机按照步距角转动即可,电机上的四根线按照时序变化已经不是我们需要关心的东西了,芯片已经帮我们完成,那么我们可以有更多的精力去进行电机的灵活控制,加入PWM波即可设置电机转动的速度。

 

 

 

2016/4/11

1.      今天再次尝试读出6050的数据,因为这是小车的一个重点部分,不能稀里糊涂的就认为已经读出了数据了。

2.      因为我的战舰开发板上,预留了另一种端口模式的6050端口,所以我也不知道这样是不是能用,所以我要是实在不能够通过战舰板子读取数据的话,最不济可以用51单片机去模拟,反正也就是个IIC协议。

3.      MPU6050:首先,通过模块的原理图,可以看到AD0接地,也就是这个模块的物理地址为0x68,如果AD0接高电平,那么地址就是0x69。

4.      现在使用我自己的战舰开发板上的历程,驱动6050,发现我以前买的6050模块竟然是坏的,换了个模块立马就读出来了,明明型号都一样,我自己的就是不能用,没办法只能从小车上拆下来进行调试,也幸好这个可以,也第一次看到了数据。

5.      数据总结:Pitch(绕x轴转动的角度),Roll(绕y轴转动的角度),Yaw(绕z轴转动的角度)这三个是从6050中,通过DMP(数字运动处理)直接读取出来的数据。

注意:!!!!这里对于角度的理解有问题!!!!首先战舰上使用的程序是针对另一种封装的6050,所以读出来的数据顺势的向我认为的方向,让我误解了,通过陀螺仪上的丝印(白色的字或图案),可以看到,我们读出来的数据都是陀螺仪绕着一个轴转动时产生的,就像一根棍子上穿了一个环,那么这个环的转动才是这个轴上变化的数据。那么根据现在小车上使用的6050可以看出,小车前后倒,是绕着X轴,而非Y轴!一开始我以为是Y轴箭头方向才是正方向,是错误的。

6.      小车使用到的角度:根据小车PCB上画的端口方向,很明显基本只用到了X轴的角度变换。具体是如何,还要继续研究。

7.      现在获得了小车的三个方向的角度数据,接下来就是如何获得欧拉角(由章动角θ、进动角ψ和自转角φ组成)。

8.      其实MPU6050输出的四元数,根本不需要我们关心,因为现在我使用了6050中自带的DMP进行获取数据,所以读出来的就是已经被换算好的欧拉角,这样CPU就有更多的精力做其他的事情。

 

 

2016/4/12

1.      今天配置两个定时器,分别用来为两个电机提供PWM信号,也就是STEP引脚的信号。

2.      其中用到了定时器PWM波输出模式,这个模式,可以通俗的描述出来,就是,在1数到100之间,设置了一个值,在小于这个值得时候一直站着,在大于这个值得时候一直坐着,如此周期往复就出现了PWM波,这个波形也就是给STEP使用,在上面也提到过这个信号,而这个信号也是最好保持50%的占空比使得电机的运动和保持合理分配。

3.      首先看一下我用逻辑分析仪采集到的PWM波

4.      上面一个为左边电机,下面一个为右边电机的STEP引脚,也就是定时器的输出引脚上面的PWM波。

5.      如何将定时器4和2的PWM波输出映射到左边电机的引脚PB9和右边电机的引脚PA1的?简单的说,在《STM32参考手册》中,有有关各个定时器以及其他各个中断与引脚的映射关系,只要对照就可以。需要注意的是,对应的引脚要设置为推挽输出,需要使用相应的引脚就需要初始化相应的通道,使得通道输出到GPIO上,实现PWM的输出。

6.      IIC部分我暂时不准备细细研究这里面的库函数的使用方法,反正这是固定的格式,到后面开发,很多时候都是拿过来用封装得很好的函数,所以现在我只当它可以这样使用,只要理解它的协议以及它的功能即可。

7.      关于6050的寄存器配置:到了一定程度的时候,我就不想再自己琢磨着去一个一个寄存器的配置了,而是怎么能够使用别人提供的例程,进行修改,然后可以把模块使用起来,因为这些寄存器的配置和学习STM32的时候一样,只是以某种方式将每个位代表的值写入到对应的寄存器,那么硬件就可以工作了。

8.      注:对于一些硬件的操作以及芯片内部的配置使用,都是通过配置寄存器实现的,这是我玩了那么多模块以后的感觉,甚至有时候模块现成到根本不用我们关心寄存器的配置,直接可以使用,关键只是怎么用起来,在用起来的基础上再做其他操作。

9.      UART2:用于接收蓝牙模块发送来的命令。

10.  关于中断的优先级问题:根据NVIC_IRQChannelPreemptionPriority 和NVIC_IRQChannelSubPriority可以判断他们的优先级,这是有规则的,具体可以见手册,优先级号越小优先级越高。

11.  中断优先级:定时器2和4作为电机PWM波输出并没有用到中断,所以不存在中断优先级问题,而定时器3的中断优先级要高于串口中断2。

 

TIM2

TIM3

TIM4

UART2

PreemptionPriority

-

0

-

2

SubPriority

-

1

-

0

12.  TIM3: (Period + 1) * (Prescaler+ 1) / 72M = 1ms,定时器3用于产生定时采集MPU6050数据的周期信号,这个信号在20次中断进入后有效,也就是这个周期信号为20ms产生一次,然后让轮询while循环检测到这个标志位,做相应的操作,比如采集数据等。

 

 

 

2016/4/13

1. 6050读出的原始数据问题:通过IIC接口读出6050中的七个数据,那么读出来的数据是怎样的呢?首先设置的角速度量程是+-2000度每秒为 +/- 2000,加速度量程是+-2000度每秒为 +/- 4g,所以灵敏度为:65536/4000=16.4LSB/(°/S) 和灵敏度为:65536/8=8192LSB/g。而且,通过手册,我们可以看到,不管是角度速还是角加速度,都是以两个八位的字节表示一个量,且高位在低字节,比如Gx就是获得了Gx =(data[0] << 8) | data[1]; 这样就获得了一个十六位组成的数据(ADC的精度就是16位)。

2. 关于加速度滤波算法:这里用到的加速度滤波算法是简单的均值滤波,即存储了之前十五个加速度值,然后加上新值,进行平均,就获得新的加速度,但是我认为这种算法十分简陋,最起码也要加权平均算法,对于较新的值分配较大的权值,这样才比较客观。出现这样的情况还有一个原因,就是我们根本无法预知下一个加速度的大小,就无法选择更好的算法了。

3. 注:记得在消化完以后,改进这个小算法。

 

 

 

2016/4/14

1.       注:关于6050的角速度偏差矫正,还没有很好的掌握,这个偏差好像可以为很多值,但是没有搞懂他们是如何整定的,所以先默认使用0x01

2.       关于角速度:我们在上面做的角速度都是没有转化为真正的角速度的值,只是在6050中读出来的原值,那么如何转化为我们需要的真实角速度的值呢?陀螺仪选的量程是+-2000度每秒,他们每个数值的寄存器都是16位的,对应的满量程数值为65536,65536/4000 = 16.4,我们只要将读到的数据除以16.4,就可以的到实际的角速度值了,但是做乘法比做除法快,所以我们不除16.4,而是乘以16.4的倒数0.0609756097560976。可以写个公式 :真实角速度= (设置量程 / 16位满量程) * 原值。

3.       通过角加速度计算出当前位置与某一个平面的夹角,这个是一个数学上的运算,其实很简单。

4.       在以上获得当前获得的实际陀螺仪显示出来的真实角度和角速度以后,我们如果想把数据直接用的话,是不行的,这终究是不准确的,存在许多误差,这时必须使用滤波算法,将这些不稳定的因素去除,去除融合完的数据,这样运用到小车上才更加稳定可靠。

5.       卡尔曼滤波算法:这个算法的话,我们只要大体的了解他的原理就可以,然后套用他的五条公式,就可以。原理的话,大体上理解是,通过预测,然后通过“可信度”,来计算出当前的比较正确的值,我也难以对这种比较复杂的算法做出分析,时间和能力有限。

6.       老实说,我现在根本就不是在做项目,根本就是阅读理解,解析注释别人现成的程序,这种不是自己敲代码,而是在别人代码上进行理解的工作,个人感觉好像别人在开party,我只能在外面听听动静。我个人还是比较崇尚项目从头开始做的,因为这样知根知底,知道我做了什么,下一步又要做什么。现在我拿着现成的PCB,现成的代码,就是不断的为这个程序加注释,并且删除无用部分,同时对一些简单的算法进行改进。虽然理解了一个模块的工作原理和一个平衡小车的平衡原理,但是往细了研究就不行了,我根本不能读懂别人的代码中关于算法的部分,可读性太差,完全没注释,我要猜测这是什么东西,为什么要用1000000 / sl,头疼,那么我现在就不准备再深入理解他的PID算法,因为算法都是一样的,正好我们也有一门《计算机控制系统》的课在学,到时候再研究研究理论吧。http://www.arduino.cn/thread-12813-1-1.html,这位仁兄的讲解还是很不错的。

7.       关于P和D的参数整定:我现在用的是这个方法来对参数进行整定,这个过程比较消耗时间,所以需要不断的调试这两个参数,直至比较稳定的站立。

 

 

 

项目思考总结:有点没有善始善终的感觉,也可能是今天有点负面情绪,也可能今天该结束了,毕竟平衡小车的平衡原理明白了,就是算法方面的解读出现问题,一个原因是我自己对计算机控制原理的欠缺,虽说学校正在开这门课,但是我还是学的很表面,很理论,并不能很好的运用到实际来,本来还想用Matlab仿真试试,但是但是,我借口还是挺多的。另一个原因就是程序可读性很差,我也第一次有这么深刻的体会,平常强调的代码规范是多么重要,以后我要引起几倍的重视,我也在一些方面做到了代码规范了。

总结一下平衡小车实现的思路:

1)对6050用IIC读取原始数据;

2)同时驱动电机启动;

3)定时开始采样6050中的数据,将数据拿出来滤波、矫正、转化为真实的角度(通过角加速度求得)和角加速度;

4)将角度和角速度通过卡尔曼算法进行融合,获得比较稳定和准确的角度和角加速度;

5)还不算完,要将计算完的角度和角加速度变成相应的PWM波频率,并且要设置速度的上限还有方向,同时还要通过PID算法做负反馈,不断的调整这个PWM波频率,将这个频率给定时器初始化,让定时器的周期频率发生改变,从而达到电机转动速度跟随6050的数据变化而变化的目的;

6)最后在PID算法中,需要不断的调整P和D的参数,调整小车的反应速度和稳定性,这是一个耗时的调试操作。

遗憾的是,我现在不能像以前一样钓鱼可以钓一天,也不能长时间的把精力放在一件事上,这是坏习惯,静不下心,就潜不到深海。

你可能感兴趣的:(stm32,MPU6050,平衡小车,项目日志)