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;
}
实验串口返回情况
hacker_2023.08.12
666