Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: mpu6050, reading time of data

  1. #1

    mpu6050, reading time of data

    Good day,
    I am using a teensy 3.5 and a mpu6050.

    I am using the standard code to get raw data:

    Code:
    #include <i2c_t3.h> 
    const int MPU_ADDR = 0x68; 
    int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
    int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
    int16_t temperature; // variables for temperature data
    
    void setup() {
      Serial.begin(9600);
      Wire.begin();
      Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
      Wire.write(0x6B); // PWR_MGMT_1 register
      Wire.write(0); // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
    }
    void loop() {
      Wire.beginTransmission(MPU_ADDR);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
      Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
      Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
      
      // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
      accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
      accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
      accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
      temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
      gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
      gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
      gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
    
    }
    I want to use the data for controlling of a self balancing robot. When checking the time needed to run the routine in the main loop, I got roughly 1.6ms. This seemed a bit too much. I then checked it with an oszi. And the time needed for the i2c data to be transmitted is 0.2ms. Now I am wondering where the rest of the time comes from. Any ideas?

  2. #2
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Portland, OR
    Posts
    538
    The biggest issue I see with your code is that you should use Wire.setClock() to set the I2C speed. Right now, your code is only using 100 kHz and you should be using 400 kHz.

  3. #3
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,509
    for my self balancing robot 20ms was enough (many many years ago). the hardware (motors, gears, the mass..) needed no faster speed. a nano did it. it had a raspberry (very first version) to control the nano (for remote-control etc) today I'd just use a Teensy LC or 3.2 alone.

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,509
    why do you read the temperature?

  5. #5
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Portland, OR
    Posts
    538
    Quote Originally Posted by Frank B View Post
    why do you read the temperature?
    It's silly, Invensense placed the temperature registers in between the accelerometer and gyro data registers. It's faster to do a burst read of 14 bytes (accel data, temp data, then gyro data) than two 6 byte transactions to get just the accel and gyro data.

  6. #6
    Hey , thanks for your replies. Sorry the wire.setclock got lost in the copy to the forum, so i am already using 400khz. The wire.requestfrom() function needs 1.4ms to be executed. Where does the difference between this time and the measured time of 0.2 ms on the oszi come from? Is there any time consuming stuff going on in the function?
    Thx

  7. #7
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Portland, OR
    Posts
    538
    I dug out my MPU-9250 (essentially the same as your MPU-6050) and ran your code. My hardware setup is using 4.7kOhm resistors for pullup to +3.3V. When I run this, I get a read time (t2 - t1) of 1.6 ms as you report.

    Code:
    #include <i2c_t3.h> 
    const int MPU_ADDR = 0x68; 
    int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
    int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
    int16_t temperature; // variables for temperature data
    
    unsigned long t1, t2;
    
    void setup() {
      Serial.begin(115200);
      while(!Serial) {}
      Serial.println("1");
      Wire.begin();
      // Wire.setClock(400000);
      // Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
      // // Wire.write(0x6B); // PWR_MGMT_1 register
      // // Wire.write(0); // set to zero (wakes up the MPU-6050)
      // Wire.endTransmission(true);
    }
    void loop() {
      
      t1 = micros();
      Wire.beginTransmission(MPU_ADDR);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
      Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
      Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
      
      // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
      accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
      accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
      accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
      temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
      gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
      gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
      gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
      t2 = micros();
      Serial.println(t2 - t1);
      delay(20);
    }
    Simply setting the clock to 400 kHz drops my read time to 440 us.

    Code:
    #include <i2c_t3.h> 
    const int MPU_ADDR = 0x68; 
    int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
    int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
    int16_t temperature; // variables for temperature data
    
    unsigned long t1, t2;
    
    void setup() {
      Serial.begin(115200);
      while(!Serial) {}
      Serial.println("1");
      Wire.begin();
      Wire.setClock(400000);
      // Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
      // // Wire.write(0x6B); // PWR_MGMT_1 register
      // // Wire.write(0); // set to zero (wakes up the MPU-6050)
      // Wire.endTransmission(true);
    }
    void loop() {
      
      t1 = micros();
      Wire.beginTransmission(MPU_ADDR);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
      Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
      Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
      
      // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
      accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
      accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
      accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
      temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
      gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
      gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
      gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
      t2 = micros();
      Serial.println(t2 - t1);
      delay(20);
    }
    Maybe you weren't setting the I2C clock correctly?

    From my experience with the MPU-9250, you won't get faster than the 440 us without switching to SPI, in which case you'll drop to about 20 us to read the sensor.

  8. #8
    Alright, thanks. I will try the mpu9250 with spi.

  9. #9
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Portland, OR
    Posts
    538
    Well, as Frank said, how fast do you need it? Looks like you should be able to get 440 us via I2C. If you need faster reads, then better go with SPI.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •