硬件设置接线:
MMA8452--------- Arduino
“+”- - - - - - - - - - - - - - - - - - - - - - - - 3.3 v
SDA - - - - - - - - - - - - - - A4
SCL - - - - - - - - - - - - - - A5
“—”- - - - - - - - - - - - - - - - - - - - - - -GND
加速度传感器的原理是检测xyz轴上的值
而后将这三个数值储存在g中
然后在依次读取,所以这里我们以图1的代码来解释
图1
这段代码中我们主要用到的是打印出来的g值三个值为一行
打印出来的效果如图2:
图2
图2中三个值分别是x、y、z的数值。
合理使用这三个数值
简单陀螺仪原理:
首先要知道加速度传感器的安装位置(即传感器正向方向)已确定x、y、z轴。
然后根据x、y、z的值进行判断装置运动的方向,具体思路简单理解如下:
当x值变化且y、z值基本不变时,装置是沿x轴方向运动的;
同理y、z也是这样;
当x、y值变化且z值基本不变时,装置是沿y=kx+b方向运动的;
同理y、z也是这样;
当x、y、z都变化时,装置是沿ax+by+cz=d方向运动的;
碰撞检测原理:
确定好加速度传感器的方向,然后确定以x、y、z其中的一个值,多测测是找到撞击临 界点的加速度,然后将这个值设置为报警值,当加速度大于或等于这个值时报警撞击(这 里我应用在老年人摔倒报警拐杖上,当加速度大于19.55时,开启警报告知周围的人老 人摔倒了请尽快扶起)
参考读取数据的代码:(我也是网上查的改了一下拿来用)
/*
硬件设置:
MMA8452--------- Arduino
3.3 v - - - - - - - - - - - - - - - - - - - - - - - - 3.3 v
SDA - - - - - - - - - - - - - - A4
sci - - - - - - - - - - - - - - A5
接地- - - - - - - - - - - - - - - - - - - - - - -接地
*/
#include <Wire.h> // 用于I2C
//SparkFun断接板默认值为1,如果设置板底部的SA0跳线,则设置为0
#define MMA8452_ADDRESS 0x1D // 如果SA0高则0x1D,如果低则0x1C
//定义一些我们将在MMA8452上访问的寄存器
#define OUT_X_MSB 0x01
#define XYZ_DATA_CFG 0x0E
#define WHO_AM_I 0x0D
#define CTRL_REG1 0x2A
#define GSCALE 2 // 将全尺寸范围设置为+/-2、4或8g。用于计算实际g值。
void setup()
{
Serial.begin(9600);
Serial.println("MMA8452 Basic Example");
Wire.begin(); //Join the bus as a master
initMMA8452(); //Test and intialize the MMA8452
pinMode(5, OUTPUT);
pinMode(6, INPUT);
pinMode(2, OUTPUT);
pinMode(12, INPUT);
pinMode(7, OUTPUT);
pinMode(13, OUTPUT);
}
//定义超声波传感器的trig为5号端口,定义echo为6号端口,并测出距离值
float checkdistance_5_6()
{
digitalWrite(5, LOW);
delayMicroseconds(2);
digitalWrite(5, HIGH);
delayMicroseconds(10);
digitalWrite(5, LOW);
float distance = pulseIn(6, HIGH) / 58.00;
delay(10);
return distance;
}
void loop()
{
//光控led
if (analogRead(A3) < 500)
{
digitalWrite(13,HIGH);
}
else
{
digitalWrite(13,LOW);
}
int accelCount[3]; // 存储12位的签名值
readAccelData(accelCount); // 读取x/y/z adc值
//现在我们要计算实际的g的加速度值
float accelG[3]; //将实际accel值存储在g中
for (int i = 0 ; i < 3 ; i++)
{
accelG[i] = (float) accelCount[i] / ((1<<12)/(2*GSCALE)); // 得到实际的g值,这取决于所设置的刻度
}
// 打印出的数值
for (int i = 0 ; i < 3 ; i++)
{
Serial.print(accelG[i], 4); // 打印出g值
Serial.print("\t"); // 打印轴间制表符
}
Serial.println();
// float v = 0.0;
delay(10); // 此处为能见度延迟
/* v = accelG[2] * 9.8;
Serial.print(v,4);
while (v > 19.55 or v < -19.55)
{
digitalWrite(7,HIGH);
if (digitalRead(12))
{
digitalWrite(7,LOW);
break;
}
Serial.print("摔倒了!!");
}
//测距
if (checkdistance_5_6() < 30)
{
digitalWrite(2,HIGH);
}
else
{
digitalWrite(2,LOW);
}*/
}
void readAccelData(int *destination)
{
byte rawData[6]; // x/y/z accel注册存储在这里的数据
readRegisters(OUT_X_MSB, 6, rawData); // 将6个原始数据寄存器读入数据数组
// 循环计算每个轴的12位ADC和g值
for(int i = 0; i < 3 ; i++)
{
int gCount = (rawData[i*2] << 8) | rawData[(i*2)+1]; //将两个8位寄存器合并成一个12位数字
gCount >>= 4; //寄存器是左对齐的,这里我们右对齐12位整数
//如果数字为负,我们必须手动设置(没有12位数据类型)
if (rawData[i*2] > 0x7F)
{
gCount = ~gCount + 1;
gCount *= -1; // 转换成- 2的补码#
}
destination[i] = gCount; //将这个g计数记录到3 int数组中
}
}
// 初始化MMA8452寄存器
// 有关设置所有这些寄存器的更多信息,请参阅许多应用程序说明:
// http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
void initMMA8452()
{
byte c = readRegister(WHO_AM_I); // WHO_AM_I寄存器中读取
if (c == 0x2A) // WHO_AM_I总是0x2A
{
Serial.println("MMA8452Q is online...");
}
else
{
Serial.print("Could not connect to MMA8452Q: 0x");
Serial.println(c, HEX);
while(1) ; // 如果通信没有发生,则永远循环
}
MMA8452Standby(); // 必须处于待命状态才能更改寄存器吗
// 将整个范围设置为2,4或8g。
byte fsr = GSCALE;
if(fsr > 8) fsr = 8; //简单的错误检查
fsr >>= 2; //灵巧的技巧,见第22页。00 = 2G, 01 = 4A, 10 = 8G
writeRegister(XYZ_DATA_CFG, fsr);
//默认的数据速率是800Hz,在这个示例代码中我们不修改它
MMA8452Active(); //设置为active开始阅读
}
//将MMA8452设置为待机模式。它必须处于备用状态才能更改大多数寄存器设置
void MMA8452Standby()
{
byte c = readRegister(CTRL_REG1);
writeRegister(CTRL_REG1, c & ~(0x01)); //清除活动位进入备用状态
}
// 将MMA8452设置为活动模式。需要在此模式下输出数据
void MMA8452Active()
{
byte c = readRegister(CTRL_REG1);
writeRegister(CTRL_REG1, c | 0x01); //设置活动位开始检测
}
// 按顺序读bytesToRead,从addressToRead开始读到dest字节数组
void readRegisters(byte addressToRead, int bytesToRead, byte * dest)
{
Wire.beginTransmission(MMA8452_ADDRESS);
Wire.write(addressToRead);
Wire.endTransmission(false); //结束传输,但保持连接活动
Wire.requestFrom(MMA8452_ADDRESS, bytesToRead); //请求字节,一旦完成,总线在默认情况下被释放
while(Wire.available() < bytesToRead); //等待,直到我们得到所期望的字节数
for(int x = 0 ; x < bytesToRead ; x++)
dest[x] = Wire.read();
}
// 从addressToRead读取一个字节并将其作为字节返回
byte readRegister(byte addressToRead)
{
Wire.beginTransmission(MMA8452_ADDRESS);
Wire.write(addressToRead);
Wire.endTransmission(false); //结束传输,但保持连接活动
Wire.requestFrom(MMA8452_ADDRESS, 1); //请求一个字节,一旦完成,总线在默认情况下被释放
while(!Wire.available()) ; //等待数据返回
return Wire.read(); //返回一个字节
}
// 将单个字节(dataToWrite)写入addressToWrite
void writeRegister(byte addressToWrite, byte dataToWrite)
{
Wire.beginTransmission(MMA8452_ADDRESS);
Wire.write(addressToWrite);
Wire.write(dataToWrite);
Wire.endTransmission(); //停止传输
}