本帖最后由 哈哈顺 于 2014-3-4 17:59 编辑
这段时间研究平衡小车,对mpu6050的数据进行分析时,感觉串口一连串的数据看的头痛,下载的示波器又不能用,被逼无奈,就用labview自己制作了一个虚拟示波器,感觉数据变成曲线后更直观,着实觉得labview和arduino功能的强大!
%5Bmedia=x,500,375%5Dhttp://v.youku.com/v_show/id_XNjgwNjc2NjY4.html[/media]
首先,角度的输出我没有用卡尔曼滤波(其实我不会),直接用的是mpu6050自带的dmp,直接得到角度值,这样在下位机方面就很轻松了(其实上位机编程也不难) - #include "Wire.h"
- #include "I2Cdev.h"
- #include "MPU6050_6Axis_MotionApps20.h"
- MPU6050 mpu(0x68);
- bool dmpReady = false; // set true if DMP init was successful
- uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
- uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
- uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
- uint16_t fifoCount; // count of all bytes currently in FIFO
- uint8_t fifoBuffer[64]; // FIFO storage buffer
- Quaternion q; // [w, x, y, z] quaternion container
- VectorFloat gravity; // [x, y, z] gravity vector
- float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
- volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
- void dmpDataReady() {
- mpuInterrupt = true;
- }
- void setup()
- {
- Serial.begin(115200);
- Wire.begin();
- mpu.initialize();
- delay(2);
- devStatus=mpu.dmpInitialize();
- if(devStatus==0)
- {
- mpu.setDMPEnabled(true);
- attachInterrupt(0, dmpDataReady, RISING);
- mpuIntStatus = mpu.getIntStatus();
- dmpReady=true;
- packetSize = mpu.dmpGetFIFOPacketSize();
- }
- }
- void loop()
- {
- float x,y,z;
- if(!dmpReady)
- return;
- if (!mpuInterrupt && fifoCount < packetSize)
- return;
- mpuInterrupt = false;
- mpuIntStatus = mpu.getIntStatus();
- fifoCount = mpu.getFIFOCount();
- if ((mpuIntStatus & 0x10) || fifoCount == 1024)
- {
- mpu.resetFIFO();
- }
- else if (mpuIntStatus & 0x02)
- {
- while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
- mpu.getFIFOBytes(fifoBuffer, packetSize);
- fifoCount -= packetSize;
- mpu.dmpGetQuaternion(&q, fifoBuffer);
- mpu.dmpGetGravity(&gravity, &q);
- mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //从DMP中取出Yaw、Pitch、Roll三个轴的角度,放入数组ypr。单位:弧度
-
- x=(-ypr[2] * 180/M_PI+90)/100.0;
- y=(-ypr[1] * 180/M_PI+90)/100.0;
- z=(-ypr[0] * 180/M_PI+90)/100.0;
- Serial.print(x,4);
- Serial.print(y,4);
- // Serial.print(z,4);
- delay(50);
- }
- }
复制代码
代码中我为什么要将得出的角度值还要加90,然后还除100呢,这个我们可以参考 宜昌城老张大哥的博客(在这要谢谢张大哥,他的博客写的很好):http://www.eefocus.com/zhang700309/blog/11-11/233946_363bf.html
他的采样的是0~5v的电压值,数值位数是固定的(比如1.23V,4位,不要忘了小数点),而我的采样值不仅有负号,而且整数位1~3位,在串口发送之前,我们要怎样处理这样的变动位呢?去掉负号的方法很简单,将角度值加90就可以了,关键是整数位的控制,有以下两方法
方法一:在下位机程序里将接收到mpu6050的数据由数值变成字符,如果整数位为1位,则前加两个00,如果整数位为两位,则前加一个0,然后再传给pc,这样显然很繁琐,给下位机程序编写增加负担,而且由于不同的传感器还要大幅度改下位机的程序,导致没有推广性;
方法二:经过一上午的冥思苦想和实验,我发现:要使整数位数固定,不够前端加0的方法,以我现在的知识很难实现,但是是小数位后的位数的固定就很容易了,用Serial.print(x,4)就可以实现了,所以我把下位机采集的数据除以100,这样就变成张大哥博客里的类型的么,例如:陀螺仪获得x轴的角度为-25.36°,y轴角度为56.35°,加90后除以100后分变为0.6464和1.4635,通过串口发送的形式为0.64641.4635(前6位关于x轴,后6为关于y轴),发送的位数成功固定,接下来就是上位机的事了!
labview程序图:
Labview将字符串的前6位和后6位分离,然后变成数值,跟下位机(arduino)处里数据的顺序相反,你懂得!
最后感谢弘毅老师以及其他访客的无私的分享和教导,开源才能撑起中国梦! |