弘毅 发表于 2011-7-28 23:02:17

arduino学习笔记12 - ADXL345加速度传感器实验

前两天我们做了温度传感器实验,大家一定还有印象。今天我们来研究另外一种传感器加速度传感器。

什么是加速度传感器

加速度传感器,作用是测量在加速过程中产生的力。最基本的如咱们平常所熟悉的是重力加速度,大小是1g。

加速度传感器一般用于什么地方

通过测量由重力引起的加速度,你可以计算出设备相对于水平面的倾斜角度。通过分析动态加速度,你可以分析出设备的移动方式。自平衡车中就是使用加速度传感器与陀螺仪进行卡尔曼滤波进行姿态矫正。

本次试验使用的ADXL345数字传感器,通过I2C或者SPI接口直接输出数字信号。在1g的加速度下,输出数值为256.



下面是硬件连接图







下面是002X IDE下的代码#include <Wire.h>//调用arduino自带的I2C库
#include <LiquidCrystal.h>   //调用arduino自带的LiquidCrystal库

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);//设置接口

int ADXAddress = 0xA7>>1;//转换为7位地址
int reading = 0;
int val = 0;
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
double Xg,Yg,Zg;

void setup()
{
lcd.begin(16, 2);//初始化LCD
delay(100);
Wire.begin();//初始化I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.send(Register_2D);
Wire.send(8);
Wire.endTransmission();
}

void loop()
{
Wire.beginTransmission(ADXAddress);
Wire.send(Register_X0);
Wire.send(Register_X1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    X0 = Wire.receive();
    X1 = Wire.receive();
    X1 = X1<<8;
    X_out = X0+X1;
}

Wire.beginTransmission(ADXAddress);
Wire.send(Register_Y0);
Wire.send(Register_Y1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Y0 = Wire.receive();
    Y1 = Wire.receive();
    Y1 = Y1<<8;
    Y_out = Y0+Y1;
}

Wire.beginTransmission(ADXAddress);
Wire.send(Register_Z0);
Wire.send(Register_Z1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Z0 = Wire.receive();
    Z1 = Wire.receive();
    Z1 = Z1<<8;
    Z_out = Z0+Z1;
}

Xg = X_out/256.00;//把输出结果转换为重力加速度g,精确到小数点后2位。
Yg = Y_out/256.00;
Zg = Z_out/256.00;
lcd.clear(); //清屏
lcd.print("X="); //使屏幕显示文字X=
lcd.print(Xg);
lcd.setCursor(8, 0);
lcd.print("Y=");
lcd.print(Yg);
lcd.setCursor(0, 1);
lcd.print("Z=");
lcd.print(Zg);
delay(300);//延时0.3秒,刷新频率这里进行调整

}试验效果如下

http://player.youku.com/player.php/sid/XMzA3ODA2NDQw/v.swf

附件为ADXL345中文手册


1.0以后Arduino语法修改很大,下面的代码是1.0以后的IDE使用的代码。
#include <Wire.h>//调用arduino自带的I2C库
#include <LiquidCrystal.h>   //调用arduino自带的LiquidCrystal库

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);//设置接口

int ADXAddress = 0xA7>>1;//转换为7位地址
int reading = 0;
int val = 0;
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
double Xg,Yg,Zg;

void setup()
{
lcd.begin(16, 2);//初始化LCD
delay(100);
Wire.begin();//初始化I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Register_2D);
Wire.write(8);
Wire.endTransmission();
}

void loop()
{
Wire.beginTransmission(ADXAddress);
Wire.write(Register_X0);
Wire.write(Register_X1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1<<8;
    X_out = X0+X1;
}

Wire.beginTransmission(ADXAddress);
Wire.write(Register_Y0);
Wire.write(Register_Y1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1<<8;
    Y_out = Y0+Y1;
}

Wire.beginTransmission(ADXAddress);
Wire.write(Register_Z0);
Wire.write(Register_Z1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1 = Z1<<8;
    Z_out = Z0+Z1;
}

Xg = X_out/256.00;//把输出结果转换为重力加速度g,精确到小数点后2位。
Yg = Y_out/256.00;
Zg = Z_out/256.00;
lcd.clear(); //清屏
lcd.print("X="); //使屏幕显示文字X=
lcd.print(Xg);
lcd.setCursor(8, 0);
lcd.print("Y=");
lcd.print(Yg);
lcd.setCursor(0, 1);
lcd.print("Z=");
lcd.print(Zg);
delay(300);//延时0.3秒,刷新频率这里进行调整

}

プ汏坏疍 发表于 2011-12-16 10:56:02

弘老师,请教一下,我前两天买的一个ADXL345,板子上面只有三个电容和一个ADXL345。引脚跟你的电路图一模一样。手头只有一个LCD按键(LCD1602 KEYPAD V2.0模块)的板,电路板是买来的时候设置好的了,做不了弘老师的液晶部分,所以自己改了一下程序希望通过串口显示,代码如下:#include <Wire.h>//调用arduino自带的I2C库
#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37

int ADXAddress = 0xA7>>1;//转换为7位地址
int reading = 0;
int val = 0;
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
double Xg,Yg,Zg;

void setup()

{
Serial.begin(9600);
Wire.begin();//初始化I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.send(Register_2D);
Wire.send(8);
Wire.endTransmission();
}

void loop()

{
Wire.beginTransmission(ADXAddress);
Wire.send(Register_X0);
Wire.send(Register_X1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    X0 = Wire.receive();
    X1 = Wire.receive();
    X1 = X1<<8;
    X_out = X0+X1;
}

Wire.beginTransmission(ADXAddress);
Wire.send(Register_Y0);
Wire.send(Register_Y1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Y0 = Wire.receive();
    Y1 = Wire.receive();
    Y1 = Y1<<8;
    Y_out = Y0+Y1;
}
Wire.beginTransmission(ADXAddress);
Wire.send(Register_Z0);
Wire.send(Register_Z1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    Z0 = Wire.receive();
    Z1 = Wire.receive();
    Z1 = Z1<<8;
    Z_out = Z0+Z1;
}
Xg = X_out/256.00;//把输出结果转换为重力加速度g,精确到小数点后2位。
Yg = Y_out/256.00;
Zg = Z_out/256.00;
/*/////////////////////////////////////////
   显示X轴
   /////////////////////////////////////////*/
Serial.print("x=");
Serial.print(Xg,DEC);
Serial.print("g");
Serial.println();
/*///////////////////////////////////////
   显示Y轴
   /////////////////////////////////////////*/
Serial.print("y=");
Serial.print(Yg,DEC);
Serial.print("g");
Serial.println();
/*///////////////////////////////////////
   显示Z轴
   /////////////////////////////////////////*/
Serial.print("z=");
Serial.print(Zg,DEC);
Serial.print("g");
Serial.println();
delay(300);//延时0.3秒,刷新频率这里进行调整
}
但是显示的都是0.0000g,不知道怎么回事?我用了sparkfun上面的程序,用的是ISP通讯。但读到的数据也都是0,0,0.不知道是模块的问题还是程序问题。麻烦帮我看下上面修改后的程序是否可行?请弘老师或者各位高人指点下,谢谢!

mauree 发表于 2011-8-3 15:33:27

请教int ADXAddress = 0xA7>>1;这句是什么意思,>>这个符号不懂

弘毅 发表于 2011-8-3 16:58:45

mauree 发表于 2011-8-3 15:33 static/image/common/back.gif
请教int ADXAddress = 0xA7>>1;这句是什么意思,>>这个符号不懂

>>这个符号的作用是进行位移
其语法是
variable << number_of_bits
variable >> number_of_bits
举个例子
int a = 5;      // 二进制: 0000000000000101
int b = a << 3;   // 二进制: 0000000000101000
int c = b >> 3;   // 二进制: 0000000000000101

0xA7>>1,意思就是把16进制的A7数值,变为二进制代码后,向右移动一位。

草冰落 发表于 2011-8-28 14:22:35

你好,请问一定是256么,为什么我有输出五百多的数值

弘毅 发表于 2011-8-28 17:02:34

草冰落 发表于 2011-8-28 14:22 static/image/common/back.gif
你好,请问一定是256么,为什么我有输出五百多的数值

根据产品手册描述,256输出数值代表1g,500多的数值代表加速度为2g左右。

草冰落 发表于 2011-8-29 16:09:11

弘毅 发表于 2011-8-28 17:02 static/image/common/back.gif
根据产品手册描述,256输出数值代表1g,500多的数值代表加速度为2g左右。

嗯,那请问您输出的数据有经过转换为补码的处理么?我的数据是还没转换为g的表现形式,是原始输出后有经过补码的处理。但是我的数据会跳变,比如0到20°的时候是正常递增的,但过了20多度的时候就会从128跳到-128,之类的情况,是怎么回事呢?

弘毅 发表于 2011-8-29 17:07:38

草冰落 发表于 2011-8-29 16:09 static/image/common/back.gif
嗯,那请问您输出的数据有经过转换为补码的处理么?我的数据是还没转换为g的表现形式,是原始输出后有经过 ...

补码?我只是加速度传感器输出地数据除以256而已。。不除也可以的。

你是使用的arduino嘛?我使用arduino加教程中代码,没发现会从128忽然跳到-128这种问题。。都是正常递增的。

如果你是使用的其他单片机,可以参考下我的代码,都是C语言的,应该好移植。

草冰落 发表于 2011-8-30 17:37:57

弘毅 发表于 2011-8-29 17:07 static/image/common/back.gif
补码?我只是加速度传感器输出地数据除以256而已。。不除也可以的。

你是使用的arduino嘛?我使用ardu ...

我用的是C8051F020 请问您对加速度模式的配置在哪里?比如是13位全分辨率,输出数据右对齐,16g量程之类的。我还是会出现那类的问题,很困惑。

弘毅 发表于 2011-8-30 18:17:46

草冰落 发表于 2011-8-30 17:37 static/image/common/back.gif
我用的是C8051F020 请问您对加速度模式的配置在哪里?比如是13位全分辨率,输出数据右对齐,16g量程之类的。 ...

Wire.begin();//初始化I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.send(Register_2D);
Wire.send(8);
Wire.endTransmission();我设置的配置代码很短。。。
setup里面就这么一句。。。。这样设置出来的结果正常,我也就没深入研究其他开关。

loop里面嘛前半段都是和加速度传感器通信的~~~用来获取数据

你可以看看我的#define定义的那些,看看和你的区别大不。

幻生幻灭 发表于 2011-9-10 23:06:21

支持! 最近入手一个MMA7455L,IIC通讯整得迷糊了,网上也没找到案例。


论坛怎么发图片?

弘毅 发表于 2011-9-11 10:14:58

幻生幻灭 发表于 2011-9-10 23:06 static/image/common/back.gif
支持! 最近入手一个MMA7455L,IIC通讯整得迷糊了,网上也没找到案例。




进入高级编辑模式里,就有图片上传按钮。

wing 发表于 2011-9-27 15:29:27

最近入手ADXL345试了下,用的是LZ程序发现有点小问题,无论什么角度Y==Z重来都没变过.
本来以为芯片Z轴坏了,于是花大价钱去另一家TB店下单买了个天价的.
后来无意中看到::::::::
line 72:
    Z1 = Y1<<8;

    Z_out = Y0+Y1;
:'(:'(:'(:'(:'(:'(:'(:'(:'(:'(:'(:'(

弘毅 发表于 2011-9-27 18:16:50

wing 发表于 2011-9-27 15:29 static/image/common/back.gif
最近入手ADXL345试了下,用的是LZ程序发现有点小问题,无论什么角度Y==Z重来都没变过.
本来以为芯片Z轴坏了 ...

:funk:偶滴小错误引起这么严重的后果。。。。偶赶快改正去

freeplus 发表于 2011-11-21 02:17:21

楼主有没有测试过读取一组加速度数值总共需要多少时间啊?
我用的是非Arduino系统,但是传感器用的是ADXL345,用IIC通信,读取一组数据需要50ms!太慢了,不知慢的原因是IIC、ADXL345、还是我的程序。。。。

lw0616 发表于 2011-12-5 20:58:21

你好,刚刚学习arduino,请问下面的代码中,向ADXL发送Register_X0、Register_X1,以及下面的if条件是什么意思?谢谢
Wire.beginTransmission(ADXAddress);
Wire.send(Register_X0);
Wire.send(Register_X1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2);
{
    X0 = Wire.receive();
    X1 = Wire.receive();
    X1 = X1<<8;
    X_out = X0+X1;
}
页: [1] 2 3 4 5 6 7 8
查看完整版本: arduino学习笔记12 - ADXL345加速度传感器实验