ESP32與MPU6050介面連線



加速度計和陀螺儀廣泛應用於工業物聯網,用於測量各種機器的健康狀況和執行引數。MPU6050是一款流行的六軸加速度計+陀螺儀。它是一種MEMS(微機電系統)感測器,這意味著它非常緊湊(從下圖可以看出),並且在很寬的頻率範圍內也非常精確。

MPU6050

在本教程中,我們將學習如何將ESP32與MPU6050連線。在這個過程中,您將學習I2C(積體電路間通訊)協議的使用,這將使您能夠將ESP32與使用I2C協議進行通訊的多個感測器和外圍裝置連線。本教程需要您的ESP32、一個MPU6050和幾根跳線。

MPU6050與ESP32的連線

如下圖所示,您需要將MPU6050的SDA線連線到ESP32的21引腳,SCL線連線到22引腳,GND連線到GND,VCC連線到3V3引腳。MPU6050的其他引腳無需連線。

MPU6050 Connection with ESP32

程式碼詳解

GitHub連結 − https://github.com/

ESP32和Arduino通常將I2C協議稱為“Wire”。因此,所需的庫匯入是Wire.h

#include<Wire.h>

接下來,我們定義常量和全域性變數。

const int MPU_ADDR = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

每個I2C裝置都有一個固定的地址,其他裝置使用該地址識別它並與其通訊。對於MPU6050,該地址為0x68。我們稍後將在初始化與MPU6050的I2C通訊時使用它。接下來我們進入設定程式碼。

void setup() {
   Serial.begin(115200);
   Wire.begin(21, 22, 100000); // sda, scl, clock speed
   Wire.beginTransmission(MPU_ADDR);
   Wire.write(0x6B);  // PWR_MGMT_1 register
   Wire.write(0);     // set to zero (wakes up the MPU−6050)
   Wire.endTransmission(true);
   Serial.println("Setup complete");
}

第一行很簡單。我們正在以115200波特率啟動與序列監視器的通訊。接下來,我們開始I2C通訊。為此,我們向Wire.begin()函式提供3個引數。

這些是SDA和SCL引腳以及時鐘速度。現在,I2C通訊需要兩條線:資料線(SDA)和時鐘線(SCL)。在ESP32上,引腳21和22通常保留用於I2C,其中21為SDA,22為SCL。為了與MPU6050通訊,我們有兩個速度選項:100kbit/s和400kbit/s。我們在這裡選擇了100kHz。如果您的用例需要,您也可以選擇更高的速度選項。

接下來,我們使用Wire.beginTransmission()命令指示ESP32我們想要與地址等於MPU_ADDR的晶片通訊。此時,您可能已經猜到一個ESP32晶片可以與多個I2C外設通訊。事實上,共有128個唯一的地址(地址欄位為7位長),因此ESP32可以使用I2C與128個不同的外設通訊,前提是它們都具有不同的地址。

在接下來的幾行中,我們將MPU6050的PWR_MGMT_1暫存器設定為0。這用於喚醒MPU6050。PWR_MGMT_1暫存器的地址0x6B是MPU6050記憶體中的地址。

它與MPU6050的I2C地址無關。MPU喚醒後,我們結束這段I2C傳輸,設定完成,並在序列監視器上使用列印語句進行指示。現在讓我們跳到迴圈中。您會注意到我們將布林值true作為引數傳遞給Wire.endTransmission。這告訴ESP32傳送停止命令並釋放I2C線路。如果我們將true替換為false,則ESP32將傳送重啟而不是停止,保持連線活動。

void loop() {
   Wire.beginTransmission(MPU_ADDR);
   Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
   Wire.endTransmission(true);
   Wire.beginTransmission(MPU_ADDR);
   Wire.requestFrom(MPU_ADDR, 14, true); // request a total of 14 registers
   AcX = Wire.read() −− 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
   AcY = Wire.read() −− 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
   AcZ = Wire.read() −− 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
   Tmp = Wire.read() −− 8 | Wire.read(); // 0x41 (TEMP_OUT_H) &  0x42 (TEMP_OUT_L)
   GyX = Wire.read() −− 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
   GyY = Wire.read() −− 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
   GyZ = Wire.read() −− 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)


   Serial.print(AcX); Serial.print(" , ");
   Serial.print(AcY); Serial.print(" , ");
   Serial.print(AcZ); Serial.print(" , ");
   Serial.print(GyX); Serial.print(" , ");
   Serial.print(GyY); Serial.print(" , ");
   Serial.print(GyZ); Serial.print("\n");
}

在迴圈中,如果您掃描上面的程式碼片段,您會看到我們總共執行了兩次傳輸。在第一次傳輸中,我們指示MPU6050我們想要從中開始讀取資料的地址,或者更確切地說,將MPU6050的內部指標設定為這個特定地址。在第二次傳輸中,我們告訴MPU我們請求從前面傳送的地址開始的14個位元組。然後我們逐個讀取位元組。您可能會注意到我們沒有在讀取結束時使用Wire.endTransmission(true)命令。這是因為Wire.requestFrom(MPU,14,true)的第三個引數指示ESP32在讀取所需數量的位元組後傳送停止命令。如果我們傳遞false而不是true,ESP32將傳送重啟命令而不是停止命令。

現在,您可能想知道如何確定哪個暫存器對應於哪個讀數。答案是MPU6050暫存器對映。顧名思義,它提供了可以從哪個暫存器獲取哪個值的資訊。根據此對映,我們意識到0x3B和0x3C對應於16位X方向加速度值的較高和較低位元組。接下來的兩個暫存器(0x3D和0x3E)包含16位Y方向加速度值的較高和較低位元組,依此類推。在加速度計和陀螺儀讀數之間,有兩個位元組包含溫度讀數,我們讀取並忽略它們,因為我們不需要它們。

這樣,您就可以成功地在ESP32上獲取MPU6050的資料。恭喜!!繼續下一個教程,學習如何在ESP32上獲取模擬感測器的資料。

參考資料

廣告
© . All rights reserved.