MMA8452加速传感器的应用(简)

硬件设置接线:

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(); //停止传输
}

 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轮舞之翼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值