【雕爷学编程】Arduino动手做(48)---GY-291 ADXL345 三轴模块3

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题,希望能够抛砖引玉。

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验四十八:GY-291 ADXL345 数字三轴重力加速度倾斜度模块 IIC/SPI传输

在这里插入图片描述
在这里插入图片描述
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验四十八:GY-291 ADXL345 数字三轴重力加速度倾斜度模块 IIC/SPI传输

程序四:显示传感器的三轴加速度及其状态

Arduino实验开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序四:显示传感器的三轴加速度及其状态
  Arduino------ADXL345
  5V------------VCC
  GND-----------GND
  A4-----------SDA IIC 数据线
  A5-----------SCL IIC 时钟线
*/

#include <Wire.h>
// ADXL345的寄存器
#define ADXL345_ADDRESS (0xA6 >> 1)  // 设备地址为 8 位,但转移到
                                     // 右移 1 位使其变为 7 位,因为
                                     // 线库只接受 7 位地址
#define ADXL345_REGISTER_XLSB (0x32)

int accelerometer_data[3];
// 无效,因为这只告诉 cip 将数据发送到其输出寄存器
// 将数据写入从机的缓冲区
void i2c_write(int address, byte reg, byte data) {
    
    

  // 发送输出寄存器地址
  Wire.beginTransmission(address);
  // 连接到设备
  Wire.write(reg);
  // 发送数据
  Wire.write(data); //低电平字节
  Wire.endTransmission();
}

// 无效,因为使用了指针
//微控制器从传感器的输入寄存器读取数据
void i2c_read(int address, byte reg, int count, byte* data) {
    
    
  // 用于读取接收到的数据个数
  int i = 0;
  // 发送输入寄存器地址
  Wire.beginTransmission(address);
  // 连接到设备
  Wire.write(reg);
  Wire.endTransmission();

  // 连接到设备
  Wire.beginTransmission(address);
// 从slave请求数据
  // Count 代表要请求的字节数
  Wire.requestFrom(address, count);
  while(Wire.available()) // 从机发送的可能少于请求
  {
    
    
    char c = Wire.read(); // 接收一个字节作为字符
    data[i] = c;
    i++;
  }
  Wire.endTransmission();
}

void init_adxl345() {
    
    
  byte data = 0;
  i2c_write(ADXL345_ADDRESS, 0x31, 0x0B);   // 13 位模式 +_ 16g
  i2c_write(ADXL345_ADDRESS, 0x2D, 0x08);   // 电源寄存器
  i2c_write(ADXL345_ADDRESS, 0x1E, 0x00);   // x
  i2c_write(ADXL345_ADDRESS, 0x1F, 0x00);   // Y
  i2c_write(ADXL345_ADDRESS, 0x20, 0x05);   // Z
  // 检查它是否有效!
  i2c_read(ADXL345_ADDRESS, 0X00, 1, &data);
  if(data==0xE5)
    Serial.println("ADXL345启动成功!");
  else
    Serial.println("它工作失败");
}

void read_adxl345() {
    
    
  byte bytes[6];
  memset(bytes,0,6);
  // 从 ADXL345 读取 6 个字节
  i2c_read(ADXL345_ADDRESS, ADXL345_REGISTER_XLSB, 6, bytes);
  // 解压数据
  for (int i=0;i<3;++i) {
    
    
    accelerometer_data[i] = (int)bytes[2*i] + (((int)bytes[2*i + 1]) << 8);
  }
}
// 初始化并启动一切
void setup() {
    
    
  Wire.begin();
  Serial.begin(9600);
  for(int i=0; i<3; ++i) {
    
    
    accelerometer_data[i]  = 0;
  }
  init_adxl345();
}

void loop() {
    
    
  read_adxl345();
  Serial.print("加速器: ");
  //13位模式下3.9mg/LSB比例因子
  Serial.print(float(accelerometer_data[0])*3.9/88);
  Serial.print("\t");
  Serial.print(float(accelerometer_data[1])*3.9/88);
  Serial.print("\t");
  Serial.print(float(accelerometer_data[2])*3.9/88-10);
  Serial.print("\n");
  delay(500);
}

实验串口返回情况

在这里插入图片描述

实验串口绘图器返回情况之一(快速摇动三轴模块)

在这里插入图片描述
实验串口绘图器返回情况之二(慢速摇动三轴模块)

在这里插入图片描述
实验串口绘图器返回情况之三(缓慢转动三轴模块)

在这里插入图片描述
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验四十八:GY-291 ADXL345 数字三轴重力加速度倾斜度模块 IIC/SPI传输

程序五:使用三轴ADXL345模块控制9G舵机

实验开源仿真编程(Linkboy V4.63)

在这里插入图片描述
打开Linkboy——各种常用小工具——串口绘图器,查看实验波形
实验串口绘图器返回情况

在这里插入图片描述
Arduino实验场景图

在这里插入图片描述
实验的视频记录
https://v.youku.com/v_show/id_XNTg2ODk1ODk0MA==.html

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验四十八:GY-291 ADXL345 数字三轴重力加速度倾斜度模块 IIC/SPI传输
程序六:使用Adafruit_ADXL345_U库读取三轴X\Y\Z
Arduino实验开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序六:使用Adafruit_ADXL345_U库读取三轴X\Y\Z
  Arduino------ADXL345
  5V------------VCC
  GND-----------GND
  A4-----------SDA IIC 数据线
  A5-----------SCL IIC 时钟线
*/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>

//同时给这个传感器分配一个唯一的ID
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

void displaySensorDetails(void){
    
    
  sensor_t sensor;

  accel.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("传感器:       "); Serial.println(sensor.name);
  Serial.print  ("驱动版本:   "); Serial.println(sensor.version);
  Serial.print  ("唯一标识:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("最大值:    "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
  Serial.print  ("最小值:    "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
  Serial.print  ("分辨率:   "); Serial.print(sensor.resolution); Serial.println(" m/s^2");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void displayDataRate(void){
    
    
  Serial.print  ("数据速率:  ");
  
  switch(accel.getDataRate())
  {
    
    
    case ADXL345_DATARATE_3200_HZ:
      Serial.print  ("3200 ");
      break;
    case ADXL345_DATARATE_1600_HZ:
      Serial.print  ("1600 ");
      break;
    case ADXL345_DATARATE_800_HZ:
      Serial.print  ("800 ");
      break;
    case ADXL345_DATARATE_400_HZ:
      Serial.print  ("400 ");
      break;
    case ADXL345_DATARATE_200_HZ:
      Serial.print  ("200 ");
      break;
    case ADXL345_DATARATE_100_HZ:
      Serial.print  ("100 ");
      break;
    case ADXL345_DATARATE_50_HZ:
      Serial.print  ("50 ");
      break;
    case ADXL345_DATARATE_25_HZ:
      Serial.print  ("25 ");
      break;
    case ADXL345_DATARATE_12_5_HZ:
      Serial.print  ("12.5 ");
      break;
    case ADXL345_DATARATE_6_25HZ:
      Serial.print  ("6.25 ");
      break;
    case ADXL345_DATARATE_3_13_HZ:
      Serial.print  ("3.13 ");
      break;
    case ADXL345_DATARATE_1_56_HZ:
      Serial.print  ("1.56 ");
      break;
    case ADXL345_DATARATE_0_78_HZ:
      Serial.print  ("0.78 ");
      break;
    case ADXL345_DATARATE_0_39_HZ:
      Serial.print  ("0.39 ");
      break;
    case ADXL345_DATARATE_0_20_HZ:
      Serial.print  ("0.20 ");
      break;

    case ADXL345_DATARATE_0_10_HZ:
      Serial.print  ("0.10 ");
      break;

    default:
      Serial.print  ("???? ");
      break;
  }  
  Serial.println(" Hz");  
}

void displayRange(void){
    
    
  Serial.print  ("范围:  +/- ");
  
  switch(accel.getRange())
  {
    
    
    case ADXL345_RANGE_16_G:
      Serial.print  ("16 ");
      break;
    case ADXL345_RANGE_8_G:
      Serial.print  ("8 ");
      break;
    case ADXL345_RANGE_4_G:
      Serial.print  ("4 ");
      break;
    case ADXL345_RANGE_2_G:
      Serial.print  ("2 ");
      break;
    default:
      Serial.print  ("?? ");
      break;
  }  
  Serial.println(" g");  
}

void setup(void){
    
    
#ifndef ESP8266
  while (!Serial);
#endif

  Serial.begin(9600);
  Serial.println("加速度计测试"); Serial.println("");
  
  //初始化传感器
  if(!accel.begin())
  {
    
    
    //检测 ADXL345 时出现问题...检查您的连接
    Serial.println("糟糕,没有检测到 ADXL345……检查你的接线!");
    while(1);
  }

  //将范围设置为适合您项目的范围
  accel.setRange(ADXL345_RANGE_16_G);

  // accel.setRange(ADXL345_RANGE_8_G);
  // accel.setRange(ADXL345_RANGE_4_G);
  // accel.setRange(ADXL345_RANGE_2_G);
  
  //显示这个传感器的一些基本信息
  displaySensorDetails();
  
  // 显示附加设置(sensor_t 范围之外)
  displayDataRate();
  displayRange();
  Serial.println("");
}

void loop(void){
    
    
  //获取新的传感器事件
  sensors_event_t event;

  accel.getEvent(&event);

  //显示结果(加速度以 m/s^2 为单位)
  Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print("  ");Serial.println("m/s^2 ");

  delay(500);
}

实验串口返回情况

在这里插入图片描述
打开Arduino IDE——工具——串口绘图器,查看实验波形
实验串口绘图器返回情况

在这里插入图片描述
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验四十八:GY-291 ADXL345 数字三轴重力加速度倾斜度模块 IIC/SPI传输

程序七:使用ADXL345_WE 库的活动/非活动中断功能

Arduino实验开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序七:使用ADXL345_WE 库的活动/非活动中断功能
  Arduino------ADXL345
  5V------------VCC
  GND-----------GND
  A4-----------SDA IIC 数据线
  A5-----------SCL IIC 时钟线
*/

#include<Wire.h>
#include<ADXL345_WE.h>
#define ADXL345_I2CADDR 0x53 // 如果 SDO = HIGH,则为 0x1D
const int int2Pin = 2;
volatile bool in_activity = false; // 活动或不活动中断发生

/* 有几种方法可以创建您的 ADXL345 对象:
   ADXL345_WE myAcc = ADXL345_WE()                -> uses Wire / I2C Address = 0x53
   ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR) -> uses Wire / ADXL345_I2CADDR
   ADXL345_WE myAcc = ADXL345_WE(&wire2)          -> uses the TwoWire object wire2 / ADXL345_I2CADDR
   ADXL345_WE myAcc = ADXL345_WE(&wire2, ADXL345_I2CADDR) -> all together
*/

ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR);

void setup() {
    
    
  Wire.begin();
  Serial.begin(9600);
  pinMode(int2Pin, INPUT);
  Serial.println("ADXL345 - 活动和不活动中断");
  Serial.println();
  if (!myAcc.init()) {
    
    
    Serial.println("ADXL345 未连接!");
  }

  /* 插入来自 ADXL345_calibration.ino 的数据并取消注释以获得更精确的结果*/
  // myAcc.setCorrFactors(-266.0, 285.0, -268.0, 278.0, -291.0, 214.0);

  /* Choose the data rate         Hz
      ADXL345_DATA_RATE_3200    3200
      ADXL345_DATA_RATE_1600    1600
      ADXL345_DATA_RATE_800      800
      ADXL345_DATA_RATE_400      400
      ADXL345_DATA_RATE_200      200
      ADXL345_DATA_RATE_100      100
      ADXL345_DATA_RATE_50        50
      ADXL345_DATA_RATE_25        25
      ADXL345_DATA_RATE_12_5      12.5
      ADXL345_DATA_RATE_6_25       6.25
      ADXL345_DATA_RATE_3_13       3.13
      ADXL345_DATA_RATE_1_56       1.56
      ADXL345_DATA_RATE_0_78       0.78
      ADXL345_DATA_RATE_0_39       0.39
      ADXL345_DATA_RATE_0_20       0.20
      ADXL345_DATA_RATE_0_10       0.10
  */
  myAcc.setDataRate(ADXL345_DATA_RATE_25);
  Serial.print("数据速率:");
  Serial.print(myAcc.getDataRateAsString());

  /* 选择测量范围
      ADXL345_RANGE_16G    16g
      ADXL345_RANGE_8G      8g
      ADXL345_RANGE_4G      4g
      ADXL345_RANGE_2G      2g
  */
  myAcc.setRange(ADXL345_RANGE_4G);
  Serial.print(" /g 范围: ");
  Serial.println(myAcc.getRangeAsString());
  Serial.println();

  attachInterrupt(digitalPinToInterrupt(int2Pin), in_activityISR, RISING);

  /* 必须为活动设置三个参数:
      1.直流/交流模式:
          ADXL345_DC_MODE - 阈值是定义的(参数 3)
          ADXL345_AC_MODE - 阈值 = 启动加速度 + 定义的阈值
     2. 轴,考虑:
          ADXL345_000  -  没有轴(没有意义)
          ADXL345_00Z  -  z
          ADXL345_0Y0  -  y
          ADXL345_0YZ  -  y,z
          ADXL345_X00  -  x
          ADXL345_X0Z  -  x,z
          ADXL345_XY0  -  x,y
          ADXL345_XYZ  -  所有轴
     3. 以 g 为单位的阈值
  */

  myAcc.setActivityParameters(ADXL345_DC_MODE, ADXL345_XY0, 0.5);

  /* 在活动中必须设置四个参数:
    1.直流/交流模式:
        见活动参数
    2. 轴,考虑:
        见活动参数
    3. 以 g 为单位的阈值
    4. 以秒为单位的不活动时间阈值(最大 255)
  */

  myAcc.setInactivityParameters(ADXL345_DC_MODE, ADXL345_XY0, 0.5, 10.0);

  /* 仅当同时使用活动和不活动时,设置链接位才有意义
    如果未设置链接位:
    - 活动中断可以随时多次触发
    - 如果不活动参数可以触发不活动。满足,独立于活动参数。 (如果使用)
    如果设置了链接位:
    - 活动中断只能在非活动中断后触发
    - 在下一个非活动中断发生之前,只能触发一个活动中断
  */
  // myAcc.setLinkBit(true);

  /* 你可以选择以下中断:
     变量名:触发,如果:
    ADXL345_OVERRUN - 新数据替换未读数据
    ADXL345_WATERMARK - FIFO 中的样本数量等于 FIFO_CTL 中定义的数量
    ADXL345_FREEFALL - 所有轴的加速度值都低于 THRESH_FF 中定义的阈值
    ADXL345_INACTIVITY - 符合。所有包含轴的值是 < THRESH_INACT for period > TIME_INACT
    ADXL345_ACTIVITY - 符合。包含轴的值 > THRESH_ACT
    ADXL345_DOUBLE_TAP - 在一个(包括)上检测到双击。轴和各种定义的条件得到满足
    ADXL345_SINGLE_TAP - 在一个上检测到单击,包括。轴和各种定义的条件得到满足
    ADXL345_DATA_READY - 新数据可用

    将中断分配给 INT1 (INT_PIN_1) 或 INT2 (INT_PIN_2)。数据就绪,溢出
    始终启用。您只能更改这些默认情况下为 INT1 的分配。

    您可以使用 deleteInterrupt(type) 删除中断;
  */

  myAcc.setInterrupt(ADXL345_ACTIVITY, INT_PIN_2);
  myAcc.setInterrupt(ADXL345_INACTIVITY, INT_PIN_2);

}

/*  在主循环中进行了一些检查:
    getActTapStatus() 以字节形式返回负责活动中断的轴(库中的代码)
    getActTapStatusAsString() 以字符串形式返回导致中断的轴
    readAndClearInterrupts(); 将中断类型返回为字节(库中的代码)
    checkInterrupt(intSource, type) 如果 intSource 的类型为 bool,则返回
*/

void loop() {
    
    
  if ((millis() % 1000) == 1) {
    
    
    xyzFloat g = myAcc.getGValues();
    Serial.print("g-x   = ");
    Serial.print(g.x);
    Serial.print("  |  g-y   = ");
    Serial.print(g.y);
    Serial.print("  |  g-z   = ");
    Serial.println(g.z);
  }

  if (in_activity == true) {
    
    
    //byte actTapSource = myAcc.getActTapStatus();
    //Serial.println(actTapSource, BIN);
    String axes = myAcc.getActTapStatusAsString();
    byte intSource = myAcc.readAndClearInterrupts();
    if (myAcc.checkInterrupt(intSource, ADXL345_ACTIVITY)) {
    
    
      Serial.print("活动在: ");
      Serial.println(axes);
    }

    if (myAcc.checkInterrupt(intSource, ADXL345_INACTIVITY)) {
    
    
      Serial.println("不活动!");
    }

    delay(500);
    myAcc.readAndClearInterrupts();
    in_activity = false;
  }
}

void in_activityISR() {
    
    
  in_activity = true;
}

实验串口返回情况

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41659040/article/details/131826479
今日推荐