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

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

 

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

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

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

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

Arduino实验开源代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
  【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实验开源代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
  【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实验开源代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
  【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;
}

  实验串口返回情况

 

posted @   行者花雕  阅读(180)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
历史上的今天:
2021-07-20 【雕爷学编程】Arduino动手做(88)---水流量传感器模块
点击右上角即可分享
微信分享提示