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; }
實驗串口返回情況