极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12834|回复: 2

MMA7361三轴加速度计学习笔记

[复制链接]
发表于 2014-11-12 11:29:29 | 显示全部楼层 |阅读模式
本帖最后由 iWhere 于 2014-11-12 11:28 编辑


基础知识参考Randy的帖子http://www.geek-workshop.com/thread-1125-1-1.html


在开始时我只知道它的X_out,Y_out,Z_out会输出模拟量。那么只要把Arduino的模拟量输出端口连接到X_out,Y_out,Z_out就可以了。但是我却不知道它的具体意义。在参考许多他人的的帖子以后。总算弄明白了含义。在论坛查询相关资料的时候,有很多大神都写了怎么去测试。

一般的代码都是这样的
  1. void setup()
  2. {
  3.   Serial.begin(19200); // 19200 bps
  4. }
  5. void loop()
  6. {
  7.       int x,y,z;
  8.       x=analogRead(0);
  9.       y=analogRead(1);
  10.       z=analogRead(2);
  11.       Serial.print("x= ");
  12.       Serial.print(x ,DEC);
  13.       Serial.print(',');
  14.       Serial.print("y= ");
  15.       Serial.print(y ,DEC);
  16.       Serial.print(',');
  17.       Serial.print("z= ");
  18.       Serial.println(z ,DEC);
  19.       delay(100);
  20. }
复制代码



这样把代码下载到Arduino以后通过串口发送过来的数据。但是我却不明白这些数据的真实含义。


然后在论坛看了Malc 大神的翻译贴以后,才明白怎么去处理这些模拟量。主要是里面介绍的第一部分加速度计
附上Malc的帖子http://www.geek-workshop.com/thread-1695-1-1.htm
只是用了一小部分Malc大神的东西。Malc还有好多东西值得学习。



以下我把我的数据处理过程和大家分享一下:
第一部分前面有很多内容:具体可以参考上面的链接,我就把它里面的举例说换成实例




这里的数据就是Malc帖子中三个从MMA7361中得到的10位的ADC值。也就是得到的三个轴的数据:
也就是上图中
Adc_X= 333,
Adc_Y=378,
Adc_Z=124;

这是第一步。
我们通过Arduino 得到MMA7361的模拟量。
接下来我们就要把这个值转换成电压值。
在查询了一定的Arduino文档以后,可以得知大多数的 Arduino都是采用5V作为参考电压,而且是10位的ADC转换。在本例子中我是使用的是Arduino NANO 。
那么在本实例中把模拟量转换成电压值的公式就是

Volt_x=Adc_x*5/1023;
其他两轴只要通过类似的推倒就可以了。

那么对应的调试程序是


  1. #define Ref_Volt 5.0


  2. int Acc_x,Acc_y,Acc_z;//定义三组数据记录加速度计的值
  3. float Acc_x_volt, Acc_y_volt, Acc_z_volt;//定义加速度计电压值

  4. void setup()
  5. {
  6.   Serial.begin(9600);
  7.   Serial.print("acc_x  acc_y   acc_z   ");
  8.   Serial.println();
  9. }

  10. void caculate_volt()//计算出相对应的电压
  11. {
  12.     Acc_x=analogRead(A1);
  13.     Acc_y=analogRead(A2);
  14.     Acc_z=analogRead(A3);
  15.     Acc_x_volt=Acc_x*Ref_Volt/1023;
  16.     Acc_y_volt=Acc_y*Ref_Volt/1023;
  17.     Acc_z_volt=Acc_z*Ref_Volt/1023;
  18.     print_out(Acc_x_volt,Acc_y_volt,Acc_z_volt);
  19.     Serial.println();      
  20. }

  21. void print_out(float a,float b,float c)
  22. {
  23.     Serial.print(a);
  24.     Serial.print("\t");
  25.     Serial.print(b);
  26.     Serial.print("\t");
  27.     Serial.print(c);
  28.     Serial.print("\t");
  29. }

  30. void loop()
  31. {
  32.   caculate_volt();
  33.   delay(200);
  34. }
复制代码


测试得到的对应结果为





这时候我就开始郁闷。因为我发现我的结果和数据手册上说的再不受重力作用下的零参考电压有一定的出入。然后再找了很多资料以后,才发想自己脑袋发蒙了。忘了不同的环境会对测试结果产生影响。



下一步就是计算电压偏移量:在这一步时我纠结了很久,到底是该如何选择零参考电压呢?是使用数据手册上提供的的参考电压,还是其他的呢?(原谅我脑子转不过弯,哈哈!求不黑)

后来我采用通过让各个轴单独受重力,然后计算出其他两个轴不受重力时的零参考电压:

计算以后我得到的各个轴的零参考电压分别为
#define Zero_Acc_x  1.64    //定义X轴0加速度零参考
#define Zero_Acc_y  1.82    //定义Y轴0加速度零参考
#define Zero_Acc_z  1.45    //定义Z轴0加速度零参考

那么对应的公式就是
Acc_x_volt_add=Acc_x_volt-Zero_Acc_x;
也就是ADC输出的值转换成的电压减去零参考电压

对应的程序为
  1. #define Ref_Volt 5.0


  2. //与加速度计有光的常量和变量
  3. #define Zero_Acc_x  1.64    //定义X加速度零参考
  4. #define Zero_Acc_y  1.82    //定义Y加速度零参考
  5. #define Zero_Acc_z  1.45    //定义Z加速度零参考

  6. int Acc_x,Acc_y,Acc_z;//定义三组数据记录通过模拟口读入的值
  7. float Acc_x_add,Acc_y_add,Acc_z_add;//定义x,y,z方向上的增量

  8. void setup()
  9. {
  10.   Serial.begin(9600);
  11.   Serial.print("acc_x  acc_y   acc_z   ");
  12.   Serial.println();
  13. }

  14. void caculate_acc_add()//计算偏移量
  15. {
  16.   Acc_x=analogRead(A1);
  17.   Acc_y=analogRead(A2);
  18.   Acc_z=analogRead(A3);
  19.   Acc_x_add=Acc_x*Ref_Volt/1023-Zero_Acc_x;
  20.   Acc_y_add=Acc_y*Ref_Volt/1023-Zero_Acc_y;
  21.   Acc_z_add=Acc_z*Ref_Volt/1023-Zero_Acc_z;
  22.   print_out(Acc_x_add,Acc_y_add,Acc_z_add);
  23.   Serial.println();
  24. }

  25. void print_out(float a,float b,float c)
  26. {
  27.     Serial.print(a);
  28.     Serial.print("\t");
  29.     Serial.print(b);
  30.     Serial.print("\t");
  31.     Serial.print(c);
  32.     Serial.print("\t");
  33. }

  34. void loop()
  35. {
  36.   caculate_acc_add();
  37.   delay(200);
  38. }
复制代码


相对应的结果



通过数据我们可以直观的看到电压的偏移量。



接下来就是第三步:
首先,我们得到的是加速度计的电压偏移量,还不是加速度的大小。但是我们想看到的是加速度的值。这时候我们加入灵敏度这个概念(Sensitvity),单位通常是mV/g.通过查询MMA7361的手册我们会发现两个不同的灵敏度。
如下图



这时候需要根据我们实际需要使用不同的量程从而选择不同的灵敏度。在我调试过程中选择的是1.5g的量程,因此选用800mV/g的灵敏度。
这时候那么对应得转换公式就是
Acc_x_g=Acc_x_add/0.8//由于我们上面得到的偏移量的电压值单位是V,因此是除以0.8而不是800


故对应程序是:在程序中Acc_x_add是利用前面的公式直接得到的

  1. #define Ref_Volt 5.0


  2. //与加速度计有光的常量和变量
  3. #define Zero_Acc_x  1.64    //定义X加速度零参考
  4. #define Zero_Acc_y  1.82    //定义Y加速度零参考
  5. #define Zero_Acc_z  1.45    //定义Z加速度零参考

  6. #define Sensitivity 0.80      //这个可以通过查询相应的手册来找到不同的量程对应不同的灵敏度

  7. int Acc_x,Acc_y,Acc_z;//定义三组数据记录加速度计的值
  8. float Acc_x_g,Acc_y_g,Acc_z_g;//定义三个浮点型变量用来存储加速度

  9. void setup()
  10. {
  11.   Serial.begin(9600);
  12.   Serial.print("acc_x  acc_y   acc_z   ");
  13.   Serial.println();
  14. }

  15. void caculate_acc_gravity()//计算加速度
  16. {
  17.   Acc_x=analogRead(A1);
  18.   Acc_y=analogRead(A2);
  19.   Acc_z=analogRead(A3);
  20.   Acc_x_g=(Acc_x*Ref_Volt/1023-Zero_Acc_x)/Sensitivity;
  21.   Acc_y_g=(Acc_y*Ref_Volt/1023-Zero_Acc_y)/Sensitivity;
  22.   Acc_z_g=(Acc_z*Ref_Volt/1023-Zero_Acc_z)/Sensitivity;
  23.   print_out(Acc_x_g,Acc_y_g,Acc_z_g);
  24.   Serial.println();
  25. }

  26. void print_out(float a,float b,float c)
  27. {
  28.     Serial.print(a);
  29.     Serial.print("\t");
  30.     Serial.print(b);
  31.     Serial.print("\t");
  32.     Serial.print(c);
  33.     Serial.print("\t");
  34. }

  35. void loop()
  36. {
  37.   caculate_acc_gravity();
  38.   delay(200);
  39. }
复制代码

然后通过串口可以得到以下数据

这时候就可以很直观的看到各个轴的加速度。

对于得到的加速度怎么处理。还在学习之中。
目前我也是学到这里。第一次发帖。还需要学习。哈哈!
希望各路大神指导。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-12-28 13:37:43 | 显示全部楼层
{:soso_e179:}
回复 支持 反对

使用道具 举报

发表于 2014-12-30 10:02:45 | 显示全部楼层
{:soso_e179:},我的是BMA220的加速度传感器,不能输出模拟信号,有什么办法能用模拟信号输出呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 17:57 , Processed in 0.051668 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表