Search code examples
c++i2craspberry-pi-picompu6050

How can I receive data over i2c?


I try to get data from an MPU-6050 with a Raspberry Pi Pico with an i2c communication. I try to read the data with the Register Map and found the ACCEL_*OUT_H and GYRO_*OUT_H registers I tried to use for X,Y and Z axis, but don't get data from them.

Class header:

#include <map>
#include <string>
#include "pico/stdlib.h"
#include "hardware/i2c.h"

#define MPU6050_ADDRESS 0x68
#define MPU6050_REG_ACCEL_XOUT_H 0x3B
#define MPU6050_REG_ACCEL_YOUT_H 0x3D
#define MPU6050_REG_ACCEL_ZOUT_H 0x3F
#define MPU6050_REG_GYRO_XOUT_H 0x43
#define MPU6050_REG_GYRO_YOUT_H 0x45
#define MPU6050_REG_GYRO_ZOUT_H 0x47
#define MPU6050_REG_PWR_MGMT_1 0x6B

class Pico_and_MPU_6050 {

private:

    int GPIO_SDA = -1;
    int GPIO_SCL = -1;
    int16_t ACCELEROMETER_X = 0;
    int16_t ACCELEROMETER_Y = 0;
    int16_t ACCELEROMETER_Z = 0;
    int16_t GYROSCOPE_X = 0;
    int16_t GYROSCOPE_Y = 0;
    int16_t GYROSCOPE_Z = 0;
    std::map<std::string, int16_t> MPU_6050_data;

public:

    Pico_and_MPU_6050(int SDA, int SCL);

    int read_MPU_6050_data();

    std::map<std::string, int16_t> get_MPU_6050_data();

};

source:

#include "Pico_and_MPU_6050.h"

Pico_and_MPU_6050::Pico_and_MPU_6050(int SDA, int SCL) {

    GPIO_SDA = SDA;
    GPIO_SCL = SCL;
    i2c_init(i2c0, 100000);
    gpio_set_function(SDA, GPIO_FUNC_I2C);
    gpio_set_function(SCL, GPIO_FUNC_I2C);

    i2c_set_slave_mode(i2c0, false, 0);

}

int Pico_and_MPU_6050::read_MPU_6050_data() {

    // Initialisieren Sie den MPU-6050 (wecken Sie ihn auf)
    uint8_t power_mgmt_reg = MPU6050_REG_PWR_MGMT_1;
    uint8_t awake_byte = 0x00; // Wecken Sie den MPU-6050 auf
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &power_mgmt_reg, 1, false);
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &awake_byte, 1, false);

    // Lesen Sie die Beschleunigungsdaten (X, Y, Z)
    uint8_t accel_x_data[2];
    uint8_t accel_x_h_reg = MPU6050_REG_ACCEL_XOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &accel_x_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, accel_x_data, 2, false);

    uint8_t accel_y_data[2];
    uint8_t accel_y_h_reg = MPU6050_REG_ACCEL_YOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &accel_y_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, accel_y_data, 2, false);

    uint8_t accel_z_data[2];
    uint8_t accel_z_h_reg = MPU6050_REG_ACCEL_ZOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &accel_z_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, accel_z_data, 2, false);

    // Lesen Sie die Gyroskopdaten (X, Y, Z)
    uint8_t gyro_x_data[2];
    uint8_t gyro_x_h_reg = MPU6050_REG_GYRO_XOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &gyro_x_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, gyro_x_data, 2, false);

    uint8_t gyro_y_data[2];
    uint8_t gyro_y_h_reg = MPU6050_REG_GYRO_YOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &gyro_y_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, gyro_y_data, 2, false);

    uint8_t gyro_z_data[2];
    uint8_t gyro_z_h_reg = MPU6050_REG_GYRO_ZOUT_H;
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &gyro_z_h_reg, 1, true);
    i2c_read_blocking(i2c0, MPU6050_ADDRESS, gyro_z_data, 2, false);

    ACCELEROMETER_X = (accel_x_data[0] << 8) | accel_x_data[1];
    ACCELEROMETER_Y = (accel_y_data[0] << 8) | accel_y_data[1];
    ACCELEROMETER_Z = (accel_z_data[0] << 8) | accel_z_data[1];

    GYROSCOPE_X = (gyro_x_data[0] << 8) | gyro_x_data[1];
    GYROSCOPE_Y = (gyro_y_data[0] << 8) | gyro_y_data[1];
    GYROSCOPE_Z = (gyro_z_data[0] << 8) | gyro_z_data[1];

    return 0;
}

std::map<std::string, int16_t> Pico_and_MPU_6050::get_MPU_6050_data() {

    MPU_6050_data["ACCELEROMETER_X"] = ACCELEROMETER_X;
    MPU_6050_data["ACCELEROMETER_Y"] = ACCELEROMETER_Y;
    MPU_6050_data["ACCELEROMETER_Z"] = ACCELEROMETER_Z;

    MPU_6050_data["GYROSCOPE_X"] = GYROSCOPE_X;
    MPU_6050_data["GYROSCOPE_Y"] = GYROSCOPE_Y;
    MPU_6050_data["GYROSCOPE_Z"] = GYROSCOPE_Z;

    return MPU_6050_data;

}

main.cpp:

#include <stdio.h>
#include <map>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "Pico_and_MPU_6050.h"

int main() {

    stdio_init_all();

    Pico_and_MPU_6050 mpu_6050(0, 1);

    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(1000);

    mpu_6050.read_MPU_6050_data();

    std::map<std::string, int16_t> data = mpu_6050.get_MPU_6050_data();

    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(1000);
    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(2000);
    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(2000);
    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(2000);
    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(2000);
    printf("Hallo!\n Ich bin aufgewacht!\n");
    sleep_ms(2000);

    while(true){

    mpu_6050.read_MPU_6050_data();

    sleep_ms(50);

    data = mpu_6050.get_MPU_6050_data();

    printf("Beschleunigung\n X-Achse: %d\n", data["ACCELEROMETER_X"]);
    printf("Y-Achse: %d\n", data["ACCELEROMETER_Y"]);
    printf("Z-Achse: %d\n", data["ACCELEROMETER_Z"]);
    printf("Gyroskop\n X-Achse: %d\n", data["GYROSCOPE_X"]);
    printf("Y-Achse: %d\n", data["GYROSCOPE_Y"]);
    printf("Z-Achse: %d\n", data["GYROSCOPE_Z"]);

    sleep_ms(1000);
    }

    return 0;
}

Output:

Beschleunigung
X-Achse: 0
Y-Achse: 0
Z-Achse: 0
Gyroskop
X-Achse: 0
Y-Achse: 0
Z-Achse: 0


Solution

  • I think you have a problem in your initialization. I guess that this:

    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &power_mgmt_reg, 1, false);
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, &awake_byte, 1, false);
    

    is supposed to write 0x00 into the register 0x6B? However, that is not what is happening.

    Look at page 35 in the datasheet for the single and burst write sequences, and you can see that this is not supposed to be two writes of one byte, but one write of two bytes - this is how most I2C devices work.

    Try something like this instead:

    uint8_t data[] = {power_mgmt_reg, awake_byte};
    i2c_write_blocking(i2c0, MPU6050_ADDRESS, data, 2, false);