ESP32實作mpu6050 === ###### tags: `ESP32 Tourist` `I2C` `ESP32` `MPU6050` #### 從上一節的內容,我們可以透過ESP32使用I2C匯流排來配置mpu6050的寄存器。在本章節,我們將探討如何使用esp32來配置mpu6050 Configuration Register,並讀取 Sensor Register,藉此得到六軸感測資訊和溫度資訊。 ![](https://hackmd.io/_uploads/ryc0Fg003.png) ##### <center>圖片來源 mpu6050 datasheet</center> * ## **ESP32 I2C Driver Install ** #### ESP32要使用I2C匯流排進行通訊前,我們需要先啟用內部I2C控制器,藉由安裝I2C控制器,我們就可以進行I2C的數據傳輸囉! #### 首先,我們先決定好esp32在進行I2C傳輸時需要的參數: :::info #### ESP32 I2C工作於哪一個模式(Master) ```c .mode = I2C_MODE_MASTER, // 0 ``` #### SDA和SCL傳輸線 ```c #define I2C_MASTER_SDA_IO 21 /*!< GPIO 21 用於I2C SDA使用,提供I2C數據傳輸 */ #define I2C_MASTER_SCL_IO 22 /*!< GPIO 22 用於I2C SCL使用,提供I2C時脈訊號來源 */ .sda_io_num = I2C_MASTER_SDA_IO, //將SDA傳輸線配置為GPIO 21 .scl_io_num = I2C_MASTER_SCL_IO, //將SCL傳輸線配置為GPIO 22 ``` #### 並且開啟上拉電阻 ```c .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE ``` #### SCL傳輸線輸出頻率(400kHz) ```c #define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency,400KHz */ .clk_speed = I2C_MASTER_FREQ_HZ, ``` #### 關閉ESP32 I2C RX、TX Buffer ```c #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ ``` #### 將上述參數整理為一個結構體(Struct),命名為i2c_config_t,用來儲存參數配置之參數 ```c i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master = { .clk_speed = I2C_MASTER_FREQ_HZ, } }; ``` #### 透過i2c_param_config(i2c_master_port, &conf)來對I2C Driver進行參數配置。 ```c i2c_param_config(i2c_master_port, &conf); Parameter : i2c_master_port: I2C 控制器編號,esp32提供2個i2c控制器,供使用者使用,分別為0和1。 &conf : 剛才儲存參數的結構體,我們將此結構體"位址"(用取址運算符"&"的到記憶體位址)作為參數,讓i2c_param_config由地址取出全部參數的資料。 ``` #### 最後安裝I2C控制器,開啟ESP32 I2C功能: ```c i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); ``` ::: * ## **ESP32 I2C 配置寄存器** #### 上章節[https://hackmd.io/@Jiaming/SJC6gv6Rn](https://hackmd.io/@Jiaming/SJC6gv6Rn) #### 從上章節,我們介紹了mpu6050用於工作模式配置的寄存器和感測器寄存器,現在我們要以ESP32來對MPU6050工作模式配置寄存器來進行配置,然後開啟mpu6050,我們才可以透過mpu6050來讀取6軸感測數據。 #### 由Datasheet取得我們要進行配置的寄存器: :::info ```c #define MPU6050_WHO_AM_I 0x75 #define MPU6050_PWR_MGMT_1_REG_ADDR 0x6B /*!< Register addresses of the power managment register,default 0x01 */ #define MPU6050_GYRO_CONFIG_ADDR 0x1B /*!< Register addresses of the gyroscope register,defult 0x18 */ #define MPU6050_ACCEL_CONFIG_ADDR 0x1C /*!< Register addresses of the accelerometer register,default 0x01 */ #define MPU6050_ENABLE_FIFO_ADDR 0x23 /*!< Register addresses of the FIFO register,disable 0x00 */ #define MPU6050_SMPLRT_DIV_ADDR 0x19 /*!< Register addresses of the sample rate register,default 0x06 */ #define MPU6050_CONFIG 0x1A /*!< Register addresses of the Digital Low Pass Filter(DLPF) register,default is 0x06 */ ``` #### 我們建立好ESP32在I2C中讀/寫的函式 #### Read: ```c esp_err_t JM_mpu6050:: mpu6050_register_read(uint8_t reg_addr, uint8_t *data, size_t len) { return i2c_master_write_read_device(I2C_MASTER_NUM, mpu6050_slave_addr, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); } ``` #### Write ```c esp_err_t JM_mpu6050::mpu6050_register_write_byte(uint8_t reg_addr, uint8_t data) { int ret; uint8_t write_buf[2] = {reg_addr, data}; ret = i2c_master_write_to_device(I2C_MASTER_NUM, mpu6050_slave_addr, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); return ret; } ``` #### 由上述內容,我們將已經定義好的寄存器位址進行Configuration register配置 ```c mpu6050_register_write_byte(MPU6050_PWR_MGMT_1_REG_ADDR, 0x80); /* 對電源管理寄存器寫入0x80進行復位 */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_PWR_MGMT_1_REG_ADDR, 0x01); /* 對電源管理寄存器寫入0x01啟動電源 */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_GYRO_CONFIG_ADDR, 0x00 | (GYRO_SCALE_RANGE_2000 << 3)); /* 對陀螺儀配置寄存器設置為(0001 1000)設置陀螺儀敏感度(+-2000/s) */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_ACCEL_CONFIG_ADDR, 0x00 | (ACCEL_SCALE_RANGE_2G << 3)); /* 對加速度感測器配置寄存器設置為(0000 0001)設置加速度感測器敏感度(+-2g) */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_ENABLE_FIFO_ADDR, 0x00); /* 對FIFO配置寄存器設置為(0000 0000),關閉FIFO */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_SMPLRT_DIV_ADDR, 0x13); /* 對SMPLRT_DIV寄存器設置為(0001 0011),設置感測器採樣頻率50Hz */ vTaskDelay(10 / portTICK_PERIOD_MS); mpu6050_register_write_byte(MPU6050_CONFIG , (0x06 | ACCEL_BAND_5HZ_GYRO_BAND_5HZ)); /*開啟低通濾波,並設置為 ACCEL_BAND_5HZ_GYRO_BAND_5HZ(110),頻率為1kHz*/ vTaskDelay(10 / portTICK_PERIOD_MS); ``` #### 配置完成後,我們就可以使用mpu6050六軸感測器了! ::: * ## **ESP32 I2C 讀取溫度感測器資料** ![](https://hackmd.io/_uploads/ByIgzaRC3.png) #### 我們在上章節有提到mpu6050感測器中,溫度感測器數據存放的位址,為0x41~0x42,2Bytes資料。 #### 藉由ESP32向mpu6050內0x41寄存器讀取2Bytes的資料後,我們整合為16bit float資料即可得到初步數據。 :::info ```c mpu6050_register_read(MPU6050_TEMP_ADDR , data, 1); /*從0x41寄存器讀取溫度數據*/ temp = ((int16_t)data[0]<<8) | data[1]; ``` ::: #### 根據得到的初步數據,必須在對該資料進行校正,程式如下: :::info ```c (float(temp)/340) + 36.53; ``` #### 這樣就可以獲得溫度數據了! ::: * ## **ESP32 I2C 讀取6感測器資料** ![](https://hackmd.io/_uploads/S199zT00n.png) #### 六軸感測數據,其加速度計感測數據會被存放至0x3B~0x40,我們藉由ESP32向MPU6050讀取該感測器數據,就可以得到x、y、z三軸16bit數據。 :::info ```c mpu6050_register_read(MPU6050_ACCEL_X_ADDR , data, 1); /*從0x3B寄存器讀取x軸加速度數據*/ accel_data = (int16_t)(data[0] << 8) | data[1]; ``` ::: #### 取得16bit數據後,必須轉換為感測器數據範圍: :::info 1. +-2g 2. +-4g 3. +-8g 4. +-16g #### 本範例以配置為+-2g ```c ret = float(accel_data) / 16384; // 4/65536 = 16384 ``` ::: #### 這樣就可以得到x軸加速度感測器的數據了。 #### 在以相同的方法,我們可以得到y、z軸加速度和x、y、z軸陀螺儀數據。 --- ![](https://hackmd.io/_uploads/rkzNEaC02.png) :::info ```c float get_mpu6050_gyro_y(){ uint8_t data[2]; float ret = 0; mpu6050_register_read(MPU6050_GYRO_Y_ADDR , data, 1); /*對溫度感測器寄存器取值*/ ret = (int16_t)(data[0] << 8) | data[1]; ret = (float)ret / 16.4; ret *= SENSORS_DPS_TO_RADS; return ret; } ``` ::: * ## **ESP32 讀取mpu6050程式範例** ![](https://hackmd.io/_uploads/Hym6Y6RR3.png) #### 本章節實作可以參考影片說明,影片會提供程式碼範例供大家參考。 * ### **Mpu6050六軸感測器實作教學影片** ![](https://hackmd.io/_uploads/B1afJDp03.png) * [https://www.youtube.com/watch?v=ZGw88J1PExE](https://www.youtube.com/watch?v=ZGw88J1PExE) --- * ## 參考資料 #### [1] mpu6050 datasheet