【雕爺學編程】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;
}

  實驗串口返回情況

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章