入手一款9轴模块,试验成功,效果不错,完美替换原来的串口6050模块!
本帖最后由 GeekBoy 于 2015-1-26 23:57 编辑各位朋友,大家好,小弟新人,请多多关照。我是打算做平衡小车的,一直想找一款合适的传感器,用来测小车的姿态角度。
之前试过6050的DMP,感觉效果不行。最近网上大家用的比较多的一款串口的6050模块,尝试了一下。有一个很大的问题就是Z轴的漂移问题,当然测量倾角的效果还是很好的,就是方向角有问题,放在那里不动还好,运动起来,就会有累积误差,只能用短时间内的两个角度只差算小车转了多少角度,店主说6050模块没有磁场,不可避免会出现累计误差,虽然理论上说小车的平衡不依赖于方向角,但是方向角一直测不准,对于我这种追求完美的偏执狂来说,总觉得是个遗憾。
好在现在9轴的JY-901模块出来了,据说能解决Z轴漂移的问题。赶紧定了一片。今天刚到手,第一感觉是做工很真的精致,元件布局密度很大,几乎没有空的空间了,据店主说新款的为了保持和原来的串口6050的兼容性,封装和体积都是一样大小的,但是要布下比原来的串口6050模块多一倍的元件,只能采用4层板工艺了。看上去确实比原来的好很多,更精致了。
不过店主并没有公开硬件的方案,个人觉得应该还是MPU6050+磁力计的方案,不知道各位前辈有何高见。
软件不再是原来单一的曲线显示了,现在还加入了仪表盘和三维显示,接上线测试了一下,测到的数据能够很好地跟踪模块姿态的变换,不过刚开始的时候,方向角总是感觉不太准有些误差,后来跟店主请教后,发现是没有校准的问题,昨晚磁场校准以后,果然没有再出现方向不准的问题了。精度确实很好。比DMP好太多了。大家可以看我的测试数据。
可能是磁场传感器都会有零偏误差的原因,而且这个初始误差还不小,足矣影响方向角的测量。陀螺仪的校准比较简单,点了校准按钮以后,等等数据不再变化即可。但是磁场的校准就比较麻烦一些了,在此也跟大家分享一下:点击磁场校准按钮以后,先绕X轴转动360度,再绕Y轴转360度,再绕Z轴转360度,然后再随意转动几下,知道显示的偏移值不再改变为止。原理是这样的:磁场传感器需要检测传感器在当前磁场环境中的最大值和最小值,然后去平均就是该轴的零点误差。因为地磁场是恒定的,比如X轴测到的最大值是700,最小值是-500,但实际上测到的都是地磁场,所以,X轴的零偏就是(700-500)/2=100,也就是说,修正以后,X的最大值是600,最小值是-600,这样两边就一致了。所以磁场校准需要寻找三个轴分别的最大值和最小值,因此需要分别绕三轴转360度。
连电脑测试以后,又马上测试了一下连接arduino,我用的是Arduino Uno R3极客版,个人感觉比原版的Uno R3好用,我的Win8系统现在可以直接用了,原版的UnoR3驱动怎么都装不上,每次都得去找个XP电脑才行。最主要的是极客的价格是原版的1/3,很划算,嘻嘻。。。
JY901对Arduino的支持很好,店主提供了Arduino的库函数,根据说明的方法安装以后,就可以再Arduino的菜单下面看到Demo了。
店主提供了IIC的和串口的Demo,小弟都分别作了测试。先说串口连接,JY901的VCC接5V,GND接GND,JY901的TX接UnoR3的TX->1,JY901的RX线不用接。
注意给UnoR3下载程序的时候,一定要先把TX线断开,然后再下载程序,下载完成后,再接上TX线。因为UnoR3下载程序用的也是这个串口,如果接上JY901以后,JY901会持续给模块发送数据,这样就会干扰UnoR3的程序下载。串口的代码如下:
#include <Wire.h>
#include <JY901.h>
void setup()
{
Serial.begin(9600);
}
void loop()
{
//print received data. Data was received in serialEvent;
Serial.print("Time:20");Serial.print(JY901.stcTime.ucYear);Serial.print("-");Serial.print(JY901.stcTime.ucMonth);Serial.print("-");Serial.print(JY901.stcTime.ucDay);
Serial.print(" ");Serial.print(JY901.stcTime.ucHour);Serial.print(":");Serial.print(JY901.stcTime.ucMinute);Serial.print(":");Serial.println((float)JY901.stcTime.ucSecond+(float)JY901.stcTime.usMiliSecond/1000);
Serial.print("Acc:");Serial.print((float)JY901.stcAcc.a/32768*16);Serial.print(" ");Serial.print((float)JY901.stcAcc.a/32768*16);Serial.print(" ");Serial.println((float)JY901.stcAcc.a/32768*16);
Serial.print("Gyro:");Serial.print((float)JY901.stcGyro.w/32768*2000);Serial.print(" ");Serial.print((float)JY901.stcGyro.w/32768*2000);Serial.print(" ");Serial.println((float)JY901.stcGyro.w/32768*2000);
Serial.print("Angle:");Serial.print((float)JY901.stcAngle.Angle/32768*180);Serial.print(" ");Serial.print((float)JY901.stcAngle.Angle/32768*180);Serial.print(" ");Serial.println((float)JY901.stcAngle.Angle/32768*180);
Serial.print("Mag:");Serial.print(JY901.stcMag.h);Serial.print(" ");Serial.print(JY901.stcMag.h);Serial.print(" ");Serial.println(JY901.stcMag.h);
Serial.print("Pressure:");Serial.print(JY901.stcPress.lPressure);Serial.print(" ");Serial.println((float)JY901.stcPress.lAltitude/100);
Serial.print("DStatus:");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.println(JY901.stcDStatus.sDStatus);
Serial.print("Longitude:");Serial.print(JY901.stcLonLat.lLon/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLon % 10000000)/1e5);Serial.print("m Lattitude:");
Serial.print(JY901.stcLonLat.lLat/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLat % 10000000)/1e5);Serial.println("m");
Serial.print("GPSHeight:");Serial.print((float)JY901.stcGPSV.sGPSHeight/10);Serial.print("m GPSYaw:");Serial.print((float)JY901.stcGPSV.sGPSYaw/10);Serial.print("Deg GPSV:");Serial.print((float)JY901.stcGPSV.lGPSVelocity/1000);Serial.println("km/h");
Serial.println("");
delay(500);
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX.This routine is run between each
time loop() runs, so using delay inside loop can delay
response.Multiple bytes of data may be available.
*/
void serialEvent()
{
while (Serial.available())
{
JY901.CopeSerialData(Serial.read()); //Call JY901 data cope function
}
}
步骤很简单,首先初始化串口,然后在串口中断里面调用JY901的数据处理函数即可。其实大部分都是在打印输出,数据解析都是在库里面完成的。非常简洁明了。测试结果如下:
IIC的接线方法也很简单,接上VCC和GND以后,将JY901的SCL和SDA分别接上UnoR3的SCL和SDA上面即可。
IIC的程序如下:
#include <Wire.h>
#include <JY901.h>
void setup()
{
Serial.begin(9600);
JY901.StartIIC();
}
void loop()
{
//print received data. Data was received in serialEvent;
JY901.GetTime();
Serial.print("Time:20");Serial.print(JY901.stcTime.ucYear);Serial.print("-");Serial.print(JY901.stcTime.ucMonth);Serial.print("-");Serial.print(JY901.stcTime.ucDay);
Serial.print(" ");Serial.print(JY901.stcTime.ucHour);Serial.print(":");Serial.print(JY901.stcTime.ucMinute);Serial.print(":");Serial.println((float)JY901.stcTime.ucSecond+(float)JY901.stcTime.usMiliSecond/1000);
JY901.GetAcc();
Serial.print("Acc:");Serial.print((float)JY901.stcAcc.a/32768*16);Serial.print(" ");Serial.print((float)JY901.stcAcc.a/32768*16);Serial.print(" ");Serial.println((float)JY901.stcAcc.a/32768*16);
JY901.GetGyro();
Serial.print("Gyro:");Serial.print((float)JY901.stcGyro.w/32768*2000);Serial.print(" ");Serial.print((float)JY901.stcGyro.w/32768*2000);Serial.print(" ");Serial.println((float)JY901.stcGyro.w/32768*2000);
JY901.GetAngle();
Serial.print("Angle:");Serial.print((float)JY901.stcAngle.Angle/32768*180);Serial.print(" ");Serial.print((float)JY901.stcAngle.Angle/32768*180);Serial.print(" ");Serial.println((float)JY901.stcAngle.Angle/32768*180);
JY901.GetMag();
Serial.print("Mag:");Serial.print(JY901.stcMag.h);Serial.print(" ");Serial.print(JY901.stcMag.h);Serial.print(" ");Serial.println(JY901.stcMag.h);
JY901.GetPress();
Serial.print("Pressure:");Serial.print(JY901.stcPress.lPressure);Serial.print(" ");Serial.println((float)JY901.stcPress.lAltitude/100);
JY901.GetDStatus();
Serial.print("DStatus:");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus);Serial.print(" ");Serial.println(JY901.stcDStatus.sDStatus);
JY901.GetLonLat();
Serial.print("Longitude:");Serial.print(JY901.stcLonLat.lLon/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLon % 10000000)/1e5);Serial.print("m Lattitude:");
Serial.print(JY901.stcLonLat.lLat/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLat % 10000000)/1e5);Serial.println("m");
JY901.GetGPSV();
Serial.print("GPSHeight:");Serial.print((float)JY901.stcGPSV.sGPSHeight/10);Serial.print("m GPSYaw:");Serial.print((float)JY901.stcGPSV.sGPSYaw/10);Serial.print("Deg GPSV:");Serial.print((float)JY901.stcGPSV.lGPSVelocity/1000);Serial.println("km/h");
Serial.println("");
delay(500);
}
也很简单,初始化串口,然后开始IIC通信,读取需要的数据,再打印输出即可。同样很简洁。
总结一下:个人觉得IIC更好用一些,首先下载程序不用再拔线了,另外数据可以根据需要读取,不像串口是被动接受的,总是会经常进入中断里面去收取数据。浪费CPU的时间。另外空出来的宝贵的串口就可以拿来连接别的设备啦。
附实验所使用的材料清单及TB传送门:
JY901模块:http://item.taobao.com/item.htm?id=43511899945
底板:http://item.taobao.com/item.htm?id=36003529849
Uno R3极客版:http://item.taobao.com/item.htm?id=36173468818
公对母杜邦线:http://item.taobao.com/item.htm?id=36179524617
通过实验觉得这个模块还是很好用的,精度很高,资料也非常齐全,现在希望我的平衡小车能够快点站起来,后续再来和大家分享。 这个传感器模块的数据接口是邮票孔,还要自己做板子引出针脚,
不知价格是多少,想搞一块玩玩,之前想做四轴飞行器,有感觉太烧钱了!所以就没做
年后再想想 买了硬件好久,一直放着,多谢楼主的资料,我试试看 感谢分享~ 图文并茂,很好滴帖子啊~ 潇洒哥 发表于 2015-1-27 10:10 static/image/common/back.gif
这个传感器模块的数据接口是邮票孔,还要自己做板子引出针脚,
不知价格是多少,想搞一块玩玩,之前想做四 ...
是邮票孔的,不过有配的底板,我买的时候老板送底板了,邮票孔比较方便焊接到自己的板子上面,还是不错的。 潇洒哥 发表于 2015-1-27 10:10 static/image/common/back.gif
这个传感器模块的数据接口是邮票孔,还要自己做板子引出针脚,
不知价格是多少,想搞一块玩玩,之前想做四 ...
这个分带气压的和不带气压的,不带气压的是98,带气压的是128.我做的小车,弄气压的没用,就搞了个不带气压的。 lawrencedon 发表于 2015-1-27 12:26 static/image/common/back.gif
感谢分享~ 图文并茂,很好滴帖子啊~
谢谢鼓励! 如果不急的话还是要研究下里面的细节! 请问楼主用过里面的气压计吗,为什么我的气压计数值不变化。基本只测1次 楼主你好,我用IIC通信的时候函数通过不去是什么问题呢会? 我也想入手一块3轴模块,
三轴轴陀螺仪ENC-03MB三轴加速度MMA7361自平衡智能车 姿态传感器
想问问楼主,这个模块怎么样?
小弟不才,还望多指教
顺子 发表于 2015-10-29 17:26 static/image/common/back.gif
我也想入手一块3轴模块,
三轴轴陀螺仪ENC-03MB三轴加速度MMA7361自平衡智能车 姿态传感器
想问问楼主,这 ...
这个模块有点老了 你好楼主,有没有 测试过通过Arduino iic连接多个陀螺仪的情况
页:
[1]