Arduino有多種通信方式,每一種通信方式都有相對應的類庫來支持:
1)硬件串口通信——HardwareSerial 類庫
2)軟件模擬串口通信——SoftwareSerial 類庫
3)IIC總線的使用——Wire 類庫
4)SPI總線的使用——SPI 類庫
MPU6050的數據接口用的是I2C總線協議,因此我們需要Wire類庫的幫助來實現Arduino與MPU6050之間的通信。
MPU6050的數據寫入和讀出均通過其芯片內部的寄存器實現,這些寄存器的地址都是1個字節,也就是8位的尋址空間,其寄存器的詳細列表說明書請點擊下載:
使用Arduino的Wire類庫來學習MPU6050與arduino的IIC通信,比直接學習MPU6050與單片機或其他更高級芯片的通信要容易許多。在arduino平臺上完成MPU6050的測試後,應該轉而在其他平臺上使用MPU6050。當然能夠實現設備通信只是邁出了其中的一小步,更重要的是在獲得慣性測量單元的數據後,會對數據進行處理。最後,能夠使用MPU6050來做一些小項目是最好的,例如平衡車、四軸飛行器等等。
一、瞭解 wire.h
1.庫包含的函數:
1) Wire.begin()和Wire.begin(address):初始化IIC連接。無參數,設備以主機模式加入IIC總線;寫參數,設備以從機模式加入IIC總線,address爲一個7位的從機地址。語法爲:
begin():
begin(address):
返回值:none
2) Wire.requestFrom():主機向從機發送數據請求信號(n*一個字節)。使用後,從機可以使用onRequest()註冊一個事件以響應主機請求。隨後,數據可以被主設備用available()和read()函數接收。語法爲:
Wire.requestFrom(address, quantity):設備(從機)的地址、請求的字節數
Wire.requestFrom(address, quantity, stop):stop參數爲boolean型值,值爲true則發送停止命令,釋放IIC總線;值爲false則發送重新開始信息,並繼續保持IIC總線的有效連接。
返回值:none
3) Wire.beginTransmission():設定傳輸數據到指定地址的從機設備。隨後可以使用write()函數發送數據,並搭配endTransmission():函數結束數據傳輸。
語法:wire.beginTransmission(address):
返回值:none
4) Wire.endTransmission():結束一個由beginTransmission()開始的並且由write()排列的從機的傳輸。語法爲:
Wire.endTransmission()
Wire.endTransmission(stop):stop爲biilean型值,值爲true(沒有填寫stop參數時,等效使用true)則發送一個停止信息;值爲false則發送一個重新開始信息,並繼續保持IIC總線的有效連接。
返回值:0 成功 1 數據溢出 2 發送addtess時從機接受到NACK 3 發送數據時接受到NACK 4 其他錯誤
5) Wire.write():向從機發送數據(雙向?主機狀態:主機將要發送的數據加入發送隊列;從機狀態:從機發送數據至發起請求的主機)。語法爲:
Wire.write(value):value 要發送的數值(以單字節發送)
Wire.write(string):string 字符組的指針(以一系列字節發送)
Wire.write(data, length):data 一個字節數組(以字節形式發送數組);length 傳輸的字節數
返回值:byte型值,返回輸入的字節數。
6) Wire.available():返回接收到的字節數
在主機中,一般用於主機發送數據請求後;在從機中,一般用於數據接收事件。語法爲:
Wire.available() 無參數
返回值:byte型值,返回輸入的字節數。
7) Wire.read():讀取1B的數據
在主機中,使用requestFrom()函數發送數據請求信號後,需要使用read()函數來獲取數據;在從機中需要使用read()讀取主機發送來的數據。語法爲:
Wire.read() 無參數
char c = Wire.read():以字符串形式接收數據(將數據作爲字符接收)
int x = Wire.read():以整型形式接收數據
返回值:讀到的字節數據
8) Wire.onReceive():在從機端註冊一個事件,當從機收到主機發送的數據時即被觸發。語法爲:
Wire.onReceive(handler):handler 當從機接收到數據時可被觸發的事件。該事件帶有一個int型參數(從主機讀到的字節數)且沒有返回值,如 void myHandler(int numBytes)
返回值:none
9) Wire.onRequest():註冊一個事件,當從機接收到主機數據請求時即被觸發。
Wire.onRequest(handler):handler 可被觸發的事件。該事件不帶參數和返回值,如 void myHandler() 。
返回值:none
二、關於MPU6050:
1.關於輸出精度:
以MPU6050加速度測量值爲例:量程是±8g時,測量精度是4096LSB/g,
LSB的意思是最小有效位,爲數字輸出方式下使用;
一般我們可以用mg/LSB來表示G-Sensor靈敏度,例如:mpu6050輸出的位數爲16位(2的16次方共65536個LSB)對應滿量程,當量程爲±2g時對應靈敏度就爲4g/65536LSB=0.06103515625mg/LSB,取倒數爲16384LSB/g。所以我們可以看到mpu605X寄存器手冊中的accelerometers' sensitivity per LSB in ACCEL_xOUT:
因爲mpu6050只能16位輸出,所以測量範圍越大,對應精度就越低。上面表格的數據存在一個規律,即:
Full Scalse Range * LSB Sensitivity = 32768
三、基礎使用:
以下實例實現 Arduino uno 與 MPU6050 的 IIC 通信,並通過 Arduino 與 PC 機的串口通訊將 MPU6050 的測量值打印在Arduino IDE 的串口監視器上。實例中未使用中斷功能。讀取的數據只經過單位的轉換,未做其他數據處理(如果要應用在項目上,可能要對原始數據進行濾波處理、數學演算等,才能給程序使用。)
//連線方法
//MPU-UNO
//VCC-5V
//GND-GND
//SCL-A5
//SDA-A4
//ADO-GND
//未使用中斷功能,即沒有做 INT-digital pin 2 (interrupt pin 0) 這樣的接線
//參考手冊:MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2
#include <Wire.h>
long accelX, accelY, accelZ; // 定義爲全局變量,可直接在函數內部使用
float gForceX, gForceY, gForceZ;
long gyroX, gyroY, gyroZ;
float rotX, rotY, rotZ;
void setup() {
Serial.begin(9600);
Wire.begin();
setupMPU();
}
void loop() {
recordAccelRegisters();
recordGyroRegisters();
printData();
delay(100);
}
void setupMPU(){
// REGISTER 0x6B/REGISTER 107:Power Management 1
Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet Sec. 9.2)
Wire.write(0x6B); //Accessing the register 6B/107 - Power Management (Sec. 4.30)
Wire.write(0b00000000); //Setting SLEEP register to 0, using the internal 8 Mhz oscillator
Wire.endTransmission();
// REGISTER 0x1b/REGISTER 27:Gyroscope Configuration
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4)
Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s (轉化爲rpm:250/360 * 60 = 41.67rpm) 最高可以轉化爲2000deg./s
Wire.endTransmission();
// REGISTER 0x1C/REGISTER 28:ACCELEROMETER CONFIGURATION
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5)
Wire.write(0b00000000); //Setting the accel to +/- 2g(if choose +/- 16g,the value would be 0b00011000)
Wire.endTransmission();
}
void recordAccelRegisters() {
// REGISTER 0x3B~0x40/REGISTER 59~64
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x3B); //Starting register for Accel Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
// 使用了左移<<和位運算|。Wire.read()一次讀取1bytes,並在下一次調用時自動讀取下一個地址的數據
while(Wire.available() < 6); // Waiting for all the 6 bytes data to be sent from the slave machine (必須等待所有數據存儲到緩衝區後才能讀取)
accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX (自動存儲爲定義的long型值)
accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processAccelData();
}
void processAccelData(){
gForceX = accelX / 16384.0; //float = long / float
gForceY = accelY / 16384.0;
gForceZ = accelZ / 16384.0;
}
void recordGyroRegisters() {
// REGISTER 0x43~0x48/REGISTER 67~72
Wire.beginTransmission(0b1101000); //I2C address of the MPU
Wire.write(0x43); //Starting register for Gyro Readings
Wire.endTransmission();
Wire.requestFrom(0b1101000,6); //Request Gyro Registers (43 ~ 48)
while(Wire.available() < 6);
gyroX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
gyroY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
gyroZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
processGyroData();
}
void processGyroData() {
rotX = gyroX / 131.0;
rotY = gyroY / 131.0;
rotZ = gyroZ / 131.0;
}
void printData() {
Serial.print("Gyro (deg)");
Serial.print(" X=");
Serial.print(rotX);
Serial.print(" Y=");
Serial.print(rotY);
Serial.print(" Z=");
Serial.print(rotZ);
Serial.print(" Accel (g)");
Serial.print(" X=");
Serial.print(gForceX);
Serial.print(" Y=");
Serial.print(gForceY);
Serial.print(" Z=");
Serial.println(gForceZ);
}
代碼中相關設置的依據以及使用的寄存器: 1)MPU6050的IIC地址:
2)電源管理寄存器:
3)陀螺儀配置:
4)加速度計配置:
5)加速度計測量值:
6)陀螺儀測量值:
三、簡單應用: