【雕爷学编程】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; }
实验串口返回情况