Arduino I2C + 三轴加速度计LIS3DH
LIS3DH是ST公司生产的MEMS三轴加速度计芯片,实现运动传感的功能。主要特性有:
- 宽工作电压范围:1.71 ~ 3.6V
- 功耗:低功耗模式2μA;正常工作模式、ODR = 50Hz时功耗11μA(要求SDO/SA0脚浮空或上拉)
- 测量范围:+/-2g ~ +/-16g
- 接口:I2C、三线制/四线制SPI
- 16 bit数据输出
- 两个可编程中断输出脚,用于自由落体和动作检测
- 6D/4D方向检测
- 内置AD支持3路外部信号输入
- 内置温度传感器
- 内置32-slot的10-bit FIFO存储器
- 自检测功能
- 封装:3 x 3 x 1 mm LGA-16
管脚定义
- VCC:电源
- Vdd_IO:数字接口供电电源
- GND:地
- RES:连接到地
- NC:不连接
- CS:I2C接口选择(CS=1);或SPI接口片选脚(CS=0)
- SCL/SPC:I2C接口或SPI接口的时钟线
- SDA/SDI/SDO:I2C接口或SPI接口数据线
- SDO/SA0:I2C地址选择脚;或四线制SPI接口输出脚。浮空时为1。
- INT1:中断信号输出,触发条件可中断
- INT2:同上
- ADC1、ADC2、ADC3:数模转换的模拟信号输入脚
与Arduino的连接
用工作于3.3V/8MHz版本的Arduino Pro Mini进行调试,可避免用UNO时接口电平转换的麻烦。采用I2C接口进行通讯。未利用INT1、INT2和FIFO的功能。
LIS3DH Pro Mini 3.3V/8MHz
VDD <------> 3.3V
GND <------> GND
SCL <------> A5 (SCL)
SDA <------> A4 (SDA)
功能调试
1. 根据应用手册,LIS3DH用于倾斜检测时,最好将测量范围设置为+/-2g。
2. 设备上电后,需要约5ms的启动时间,之后自动进入低功耗模式。之后不同的模式间切换也需要少许的时间,与ODR有关。
3. 存储结果的寄存器的值为有符号数(二补码)。应用笔记中“Example of acceleration data”中的示例表格,1g对应的高位寄存器值应为40h,资料应该是误写成了04h。
4. 手册中的功耗数据只适用于SDO/SA0脚接电源、或者空接的情况。若该管脚接地,功耗会增加150μA;若通过下拉电阻接地,功耗则会更大。
测试代码
1 /* 2 Measurement of acceleration values using motion sensor LIS3DH 3 */ 4 5 #include <Wire.h> 6 7 #define ADDRESS_LIS3DH 0x19 8 #define CTRL_REG1 0x20 9 #define CTRL_REG4 0x23 10 #define CTRL_REG5 0x24 11 #define STATUS_REG 0x27 12 #define OUT_X_L 0x28 13 14 byte buffer[6]; 15 byte statusReg; 16 17 boolean ready = false; 18 int outX, outY, outZ; 19 int xVal, yVal, zVal; 20 21 void setup() 22 { 23 Wire.begin(); 24 Serial.begin(9600); 25 delay(5); //5 ms boot procedure 26 27 // reboot memory content, to make a clean start 28 Wire.beginTransmission(ADDRESS_LIS3DH); 29 Wire.write(CTRL_REG5); 30 Wire.write(0x80); 31 Wire.endTransmission(); 32 33 delay(5); 34 35 //set ODR = 1 Hz, normal mode, x/y/z axis enabled 36 Wire.beginTransmission(ADDRESS_LIS3DH); 37 Wire.write(CTRL_REG1); 38 Wire.write(0x17); 39 Wire.endTransmission(); 40 41 //set BDU= 1, scale = +/-2g, high resolution enabled 42 Wire.beginTransmission(ADDRESS_LIS3DH); 43 Wire.write(CTRL_REG4); 44 Wire.write(0x80); 45 Wire.endTransmission(); 46 } 47 48 void loop() 49 { 50 // read STATUS_REG 51 while(ready == false) 52 { 53 Wire.beginTransmission(ADDRESS_LIS3DH); 54 Wire.write(STATUS_REG); 55 Wire.endTransmission(); 56 Wire.requestFrom(ADDRESS_LIS3DH, 1); 57 if (Wire.available() >= 1) 58 { 59 statusReg = Wire.read(); 60 } 61 if (bitRead(statusReg, 3) == 1) //new data available 62 { 63 ready = true; 64 } 65 delay(10); 66 } 67 68 if (bitRead(statusReg, 7) == 1) 69 { 70 Serial.println("Some data have been overwritten."); 71 } 72 73 //read the result 74 Wire.beginTransmission(ADDRESS_LIS3DH); 75 Wire.write(OUT_X_L | 0x80); //read multiple bytes 76 Wire.endTransmission(); 77 Wire.requestFrom(ADDRESS_LIS3DH, 6); 78 if (Wire.available() >= 6) 79 { 80 for (int i = 0; i < 6; i++) 81 { 82 buffer[i] = Wire.read(); 83 } 84 } 85 86 //calculation 87 outX = (buffer[1] << 8) | buffer[0]; 88 outY = (buffer[3] << 8) | buffer[2]; 89 outZ = (buffer[5] << 8) | buffer[4]; 90 xVal = outX / 16; 91 yVal = outY / 16; 92 zVal = outZ / 16; 93 94 Serial.print("outX: "); Serial.print(xVal); Serial.print(" "); 95 Serial.print("outY: "); Serial.print(yVal); Serial.print(" "); 96 Serial.print("outZ: "); Serial.println(zVal); 97 98 ready = false; 99 }
ODR更新频率设置为1Hz,通过串口打印三轴加速度测量结果,单位mg。