kriswiner / MPU9250

Arduino sketches for MPU9250 9DoF with AHRS sensor fusion
1.04k stars 471 forks source link

slow convergence of Yaw Pitch Roll #336

Open laurentvm opened 5 years ago

laurentvm commented 5 years ago

Running on ESP32, iteraring 5 times the filter each time I get new data from the sensors I have a very slow convergence:

At start, it takes 60 seconds to converge image

If I move it, for unknown reason it seems to be faster to converge, but still slow to me image

Frequency is 4kHz, does that make sense?

8408 a(x,y,z) 1.65 1.83 1008.00 [mg] g(x,y,z) -0.06 -0.01 -0.02 [dps] m(x,y,z) 124 -126 363 [mG] q(0,x,y,z)0.89 -0.19 0.40 0.09 o(y,p,r) 0.88 47.95 -23.40 rate = 3.85 kHz
8513 a(x,y,z) 1.16 1.59 1009.64 [mg] g(x,y,z) -0.09 0.01 -0.08 [dps] m(x,y,z) 121 -111 357 [mG] q(0,x,y,z)0.90 -0.19 0.39 0.09 o(y,p,r) 1.19 47.48 -22.96 rate = 4.17 kHz
kriswiner commented 5 years ago

4 kHz seems about right. I would recommend running the gyro/accel rates at 500 Hz or even 1 kHz, and the mag at 100 Hz.

I see much less "slowness" on my ESP32. Not sure what you are doing wrong. Are you using 400 kHz I2C bus speed and using the interrupt for data ready?

On Tue, Jan 8, 2019 at 12:59 PM laurentvm notifications@github.com wrote:

Running on ESP32, iteraring 5 times the filter each time I get new data from the sensors I have a very slow convergence:

At start, it takes 60 seconds to converge [image: image] https://user-images.githubusercontent.com/37613497/50858305-50016d80-1390-11e9-89a7-3db3f074ee93.png

If I move it, for unknown reason it seems to be faster to converge, but still slow to me [image: image] https://user-images.githubusercontent.com/37613497/50858346-6b6c7880-1390-11e9-8156-2026c842718c.png

Frequency is 4kHz, does that make sense?

8408 a(x,y,z) 1.65 1.83 1008.00 [mg] g(x,y,z) -0.06 -0.01 -0.02 [dps] m(x,y,z) 124 -126 363 [mG] q(0,x,y,z)0.89 -0.19 0.40 0.09 o(y,p,r) 0.88 47.95 -23.40 rate = 3.85 kHz 8513 a(x,y,z) 1.16 1.59 1009.64 [mg] g(x,y,z) -0.09 0.01 -0.08 [dps] m(x,y,z) 121 -111 357 [mG] q(0,x,y,z)0.90 -0.19 0.39 0.09 o(y,p,r) 1.19 47.48 -22.96 rate = 4.17 kHz

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qoMaxBxu77sYycS5l8w8PoyjS9Tcks5vBQavgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

Hi, I am using your sketch https://github.com/kriswiner/MPU9250/blob/master/MPU9250BasicAHRS_t3.ino where I modified the call to the filter based on https://github.com/kriswiner/MPU9250/blob/master/AK8963_as_slave/AK8963Slave0_MPU9250_Ladybug.ino to add iteration.

kriswiner commented 5 years ago

Are you using 400 kHz I2C bus speed and using the interrupt for data ready?

On Wed, Jan 9, 2019 at 3:06 PM laurentvm notifications@github.com wrote:

Hi, I am using your sketch https://github.com/kriswiner/MPU9250/blob/master/MPU9250BasicAHRS_t3.ino http://url where I modified the call to the filter based on https://github.com/kriswiner/MPU9250/blob/master/AK8963_as_slave/AK8963Slave0_MPU9250_Ladybug.ino http://url to add iteration.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-452849684, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qjkASYdtr6Rl-LABynUrCP8ccyB_ks5vBl5hgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

Yes but I have a modified I2C call compared to you


bool initI2C()
{
    i2c_port_t i2c_master_port = I2C_NUM_0;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = (gpio_num_t)21;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = (gpio_num_t)22;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    //conf.master.clk_speed = 100000;
    conf.master.clk_speed = 400000L;
    //400000L
    return i2c_param_config(i2c_master_port, &conf) == ESP_OK &&
    i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0) == ESP_OK;
}

#define WRITE_BIT         I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT          I2C_MASTER_READ  /*!< I2C master read */
#define ACK_CHECK_EN      0x1              /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS     0x0              /*!< I2C master will not check ack from slave */
#define ACK_VAL           (i2c_ack_type_t)0x0              /*!< I2C ack value */
#define NACK_VAL          (i2c_ack_type_t)0x1 /*!< I2C nack value */

// I2C read/write functions for the MPU9250 and AK8963 sensors

void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
{
    /*
    Wire.beginTransmission(address);  // Initialize the Tx buffer
    Wire.write(subAddress);           // Put slave register address in Tx buffer
    Wire.write(data);                 // Put data in Tx buffer
    Wire.endTransmission();           // Send the Tx buffer
    */
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_EN);
    // write sub-address and data
    uint8_t buf[2] = {subAddress, data};
    i2c_master_write(cmd, buf, sizeof(buf), ACK_CHECK_EN);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
}

uint8_t readByte(uint8_t address, uint8_t subAddress)
{
    /*
    uint8_t data; // `data` will store the register data     
    Wire.beginTransmission(address);         // Initialize the Tx buffer
    Wire.write(subAddress);                  // Put slave register address in Tx buffer
    Wire.endTransmission(I2C_NOSTOP);        // Send the Tx buffer, but send a restart to keep connection alive
    //  Wire.endTransmission(false);             // Send the Tx buffer, but send a restart to keep connection alive
    //  Wire.requestFrom(address, 1);  // Read one byte from slave register address 
    Wire.requestFrom(address, (size_t) 1);   // Read one byte from slave register address 
    data = Wire.read();                      // Fill Rx buffer with result
    return data;                             // Return data read from slave register
    */
    // write sub-address
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_DIS);
    i2c_master_write_byte(cmd, subAddress, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    // read data
    uint8_t data = 0;
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( address << 1 ) | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &data, NACK_VAL);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return data;
}

void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
{  
    /*
    Wire.beginTransmission(address);   // Initialize the Tx buffer
    Wire.write(subAddress);            // Put slave register address in Tx buffer
    Wire.endTransmission(I2C_NOSTOP);  // Send the Tx buffer, but send a restart to keep connection alive
    //  Wire.endTransmission(false);       // Send the Tx buffer, but send a restart to keep connection alive
    uint8_t i = 0;
    //        Wire.requestFrom(address, count);  // Read bytes from slave register address 
    Wire.requestFrom(address, (size_t) count);  // Read bytes from slave register address 
    while (Wire.available()) {
        dest[i++] = Wire.read(); }         // Put read results in the Rx buffer
*/

    // write sub-address
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_DIS);
    i2c_master_write_byte(cmd, subAddress, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) return ;//false;
    // read data
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( address << 1 ) | READ_BIT, ACK_CHECK_EN);
    if (count > 1) {
        i2c_master_read(cmd, dest, count - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, dest + count - 1, NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

}

This is a timing plot

image

kriswiner commented 5 years ago

So you are sending data to the serial terminal at 10 Hz?

On Thu, Jan 10, 2019 at 10:27 AM laurentvm notifications@github.com wrote:

Yes but I have a modified I2C call compared to you

bool initI2C() { i2c_port_t i2c_master_port = I2C_NUM_0; i2c_config_t conf; conf.mode = I2C_MODE_MASTER; conf.sda_io_num = (gpio_num_t)21; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; conf.scl_io_num = (gpio_num_t)22; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; //conf.master.clk_speed = 100000; conf.master.clk_speed = 400000L; //400000L return i2c_param_config(i2c_master_port, &conf) == ESP_OK && i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0) == ESP_OK; }

define WRITE_BIT I2C_MASTER_WRITE /!< I2C master write /

define READ_BIT I2C_MASTER_READ /!< I2C master read /

define ACK_CHECK_EN 0x1 /!< I2C master will check ack from slave/

define ACK_CHECK_DIS 0x0 /!< I2C master will not check ack from slave /

define ACK_VAL (i2c_ack_type_t)0x0 /!< I2C ack value /

define NACK_VAL (i2c_ack_type_t)0x1 /!< I2C nack value /

// I2C read/write functions for the MPU9250 and AK8963 sensors

void writeByte(uint8_t address, uint8_t subAddress, uint8_t data) { / Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer Wire.write(data); // Put data in Tx buffer Wire.endTransmission(); // Send the Tx buffer / i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_EN); // write sub-address and data uint8_t buf[2] = {subAddress, data}; i2c_master_write(cmd, buf, sizeof(buf), ACK_CHECK_EN); i2c_master_stop(cmd); i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); }

uint8_t readByte(uint8_t address, uint8_t subAddress) { / uint8_t data; // data will store the register data
Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer Wire.endTransmission(I2C_NOSTOP); // Send the Tx buffer, but send a restart to keep connection alive // Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive // Wire.requestFrom(address, 1); // Read one byte from slave register address Wire.requestFrom(address, (size_t) 1); // Read one byte from slave register address data = Wire.read(); // Fill Rx buffer with result return data; // Return data read from slave register
/ // write sub-address i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_DIS); i2c_master_write_byte(cmd, subAddress, ACK_CHECK_EN); i2c_master_stop(cmd); i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); // read data uint8_t data = 0; cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, ( address << 1 ) | READ_BIT, ACK_CHECK_EN); i2c_master_read_byte(cmd, &data, NACK_VAL); i2c_master_stop(cmd); i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); return data; }

void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t dest) { / Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer Wire.endTransmission(I2C_NOSTOP); // Send the Tx buffer, but send a restart to keep connection alive // Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive uint8_t i = 0; // Wire.requestFrom(address, count); // Read bytes from slave register address Wire.requestFrom(address, (size_t) count); // Read bytes from slave register address while (Wire.available()) { dest[i++] = Wire.read(); } // Put read results in the Rx buffer */

// write sub-address
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( address << 1 ) | WRITE_BIT, ACK_CHECK_DIS);
i2c_master_write_byte(cmd, subAddress, ACK_CHECK_EN);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) return ;//false;
// read data
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( address << 1 ) | READ_BIT, ACK_CHECK_EN);
if (count > 1) {
    i2c_master_read(cmd, dest, count - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, dest + count - 1, NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);

}

This is a timing plot

[image: image] https://user-images.githubusercontent.com/37613497/50988707-b364da00-150d-11e9-8d83-3d498af92038.png

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453202156, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qviRQwzmpmj2hnqcgZd31spCYjZMks5vB4YHgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

Yes

kriswiner commented 5 years ago

Doesn't this affect the quaternion update rate?

On Thu, Jan 10, 2019 at 10:51 AM laurentvm notifications@github.com wrote:

Yes

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453210190, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qlrGKUTFd_RbmVfdoR5JYz29GPECks5vB4u_gaJpZM4Z2Q90 .

laurentvm commented 5 years ago

I'm not sure but I do not think it affects.

It affects for sure how fast we can retrieve a newData from sensor. But the sensor is not moving, so having new data is not helping or at least I do not see why it would help, nothing is changing.

Changing to 1hz or 0.2Hz output does not change: image

I'm iterating 5 times the filter on the same newData, should i push this much higher?

kriswiner commented 5 years ago

If this is heading versus seconds yes this is way too slow. Not sure why, I don't see this kind of behavior....

Are you running the gyro at 200 or 250 Hz. Mybe go to 1 kHz. Accel too. Mag at 100 Hz. You should be able to get the fusion rate at 5 or 10 x the sample rate.

This should provide good results if the sensors are properly calibrated.

On Thu, Jan 10, 2019 at 11:17 AM laurentvm notifications@github.com wrote:

I'm not sure but I do not think it affects.

It affects for sure how fast we can retrieve a newData from sensor. But the sensor is not moving, so having new data is not helping or at least I do not see why it would help, nothing is changing.

Changing to 1hz or 0.2Hz output does not change: [image: image] https://user-images.githubusercontent.com/37613497/50991355-bca57500-1514-11e9-8760-1e11a15a092b.png

I'm iterating 5 times the filter on the same newData, should i push this much higher?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453218934, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qrV-qM6ayRbKXVTqiokRD04lxICGks5vB5HHgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

Kris,

I have this in the init writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x04); I guess that's wrong, seems to be 200hz? it should be writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00); as in the calibration routine

Where do I change the gyro and Mag rate? Mag, I have this uint8_t Mmode = 0x06;

kriswiner commented 5 years ago

I believe changing SMPLRT_DIV to 0 sets both accel and gyro rates to 1 kHz. Mag at 0x06 is already at 100 Hz.

// Configure Gyro and Thermometer // Disable FSYNC and set thermometer and gyro bandwidth to 41 and 42 Hz, respectively; // minimum delay time for this setting is 5.9 ms, which means sensor fusion update rates cannot // be higher than 1 / 0.0059 = 170 Hz // DLPF_CFG = bits 2:0 = 011; this limits the sample rate to 1000 Hz for both // With the MPU9250, it is possible to get gyro sample rates of 32 kHz (!), 8 kHz, or 1 kHz writeByte(MPU9250_ADDRESS, CONFIG, 0x03); // 41 Hz bandwidth, 5.9 ms delay // writeByte(MPU9250_ADDRESS, CONFIG, 0x02); // 92 Hz bandwidth, 3.9 ms delay

// Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV) writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x05); // Use a 167 Hz rate; a rate consistent with the filter update rate // determined in set in CONFIG above

// Set accelerometer sample rate configuration // It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for // accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG2); // get current ACCEL_CONFIG2 register value c = c & ~0x0F; // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0]) c = c | 0x03; // Set accelerometer rate to 1 kHz and bandwidth to 41 Hz writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c); // Write new ACCEL_CONFIG2 register value

On Thu, Jan 10, 2019 at 11:41 AM laurentvm notifications@github.com wrote:

Kris,

I have this in the init writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x04); I guess that's wrong, seems to be 200hz? it should be writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00); as in the calibration routine

Where do I change the gyro and Mag rate? Mag, I have this uint8_t Mmode = 0x06;

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453227007, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qvJB6ECHFBsJ7qFZULUAieD363uBks5vB5dSgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

It does not change anything. I got approximately the same timings

void initMPU9250()
{  
    // wake up device
    writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x00); // Clear sleep mode bit (6), enable all sensors 
    delay(100); // Wait for all registers to reset 

    // get stable time source
    writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x01);  // Auto select clock source to be PLL gyroscope reference if ready else
    delay(200); 

    // Configure Gyro and Thermometer
    // Disable FSYNC and set thermometer and gyro bandwidth to 41 and 42 Hz, respectively; 
    // minimum delay time for this setting is 5.9 ms, which means sensor fusion update rates cannot
    // be higher than 1 / 0.0059 = 170 Hz
    // DLPF_CFG = bits 2:0 = 011; this limits the sample rate to 1000 Hz for both
    // With the MPU9250, it is possible to get gyro sample rates of 32 kHz (!), 8 kHz, or 1 kHz
    writeByte(MPU9250_ADDRESS, CONFIG, 0x03);  

    // Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV)
    writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00);  // Use a 200 Hz rate; a rate consistent with the filter update rate 
    // determined inset in CONFIG above

    // Set gyroscope full scale range
    // Range selects FS_SEL and GFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
    uint8_t c = readByte(MPU9250_ADDRESS, GYRO_CONFIG); // get current GYRO_CONFIG register value
    // c = c & ~0xE0; // Clear self-test bits [7:5] 
    //c = c & ~0x02; // Clear Fchoice bits [1:0] 
    c = c & ~0x03; // Clear Fchoice bits [1:0] 
    c = c & ~0x18; // Clear GFS bits [4:3]
    c = c | Gscale << 3; // Set full scale range for the gyro
    // c =| 0x00; // Set Fchoice for the gyro to 11 by writing its inverse to bits 1:0 of GYRO_CONFIG
    writeByte(MPU9250_ADDRESS, GYRO_CONFIG, c ); // Write new GYRO_CONFIG value to register

    // Set accelerometer full-scale range configuration
    c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG); // get current ACCEL_CONFIG register value
    // c = c & ~0xE0; // Clear self-test bits [7:5] 
    c = c & ~0x18;  // Clear AFS bits [4:3]
    c = c | Ascale << 3; // Set full scale range for the accelerometer 
    writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, c); // Write new ACCEL_CONFIG register value

    // Set accelerometer sample rate configuration
    // It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for
    // accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz
    c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG2); // get current ACCEL_CONFIG2 register value
    c = c & ~0x0F; // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0])  
    c = c | 0x03;  // Set accelerometer rate to 1 kHz and bandwidth to 41 Hz
    writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c); // Write new ACCEL_CONFIG2 register value

    // The accelerometer, gyro, and thermometer are set to 1 kHz sample rates, 
    // but all these rates are further reduced by a factor of 5 to 200 Hz because of the SMPLRT_DIV setting

    // Configure Interrupts and Bypass Enable
    // Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared,
    // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips 
    // can join the I2C bus and all can be controlled by the Arduino as master
    //   writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22);    
    writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x12);  // INT is 50 microsecond pulse and any read to clear  
    writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01);  // Enable data ready (bit 0) interrupt
    delay(100);
}
kriswiner commented 5 years ago

Don't know what to tell you...Maybe try another MCU and/or senor breakout to be sure?

On Thu, Jan 10, 2019 at 12:24 PM laurentvm notifications@github.com wrote:

It does not change anything. I got approximately the same timings

void initMPU9250() { // wake up device writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x00); // Clear sleep mode bit (6), enable all sensors delay(100); // Wait for all registers to reset

// get stable time source
writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x01);  // Auto select clock source to be PLL gyroscope reference if ready else
delay(200);

// Configure Gyro and Thermometer
// Disable FSYNC and set thermometer and gyro bandwidth to 41 and 42 Hz, respectively;
// minimum delay time for this setting is 5.9 ms, which means sensor fusion update rates cannot
// be higher than 1 / 0.0059 = 170 Hz
// DLPF_CFG = bits 2:0 = 011; this limits the sample rate to 1000 Hz for both
// With the MPU9250, it is possible to get gyro sample rates of 32 kHz (!), 8 kHz, or 1 kHz
writeByte(MPU9250_ADDRESS, CONFIG, 0x03);

// Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV)
writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00);  // Use a 200 Hz rate; a rate consistent with the filter update rate
// determined inset in CONFIG above

// Set gyroscope full scale range
// Range selects FS_SEL and GFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
uint8_t c = readByte(MPU9250_ADDRESS, GYRO_CONFIG); // get current GYRO_CONFIG register value
// c = c & ~0xE0; // Clear self-test bits [7:5]
//c = c & ~0x02; // Clear Fchoice bits [1:0]
c = c & ~0x03; // Clear Fchoice bits [1:0]
c = c & ~0x18; // Clear GFS bits [4:3]
c = c | Gscale << 3; // Set full scale range for the gyro
// c =| 0x00; // Set Fchoice for the gyro to 11 by writing its inverse to bits 1:0 of GYRO_CONFIG
writeByte(MPU9250_ADDRESS, GYRO_CONFIG, c ); // Write new GYRO_CONFIG value to register

// Set accelerometer full-scale range configuration
c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG); // get current ACCEL_CONFIG register value
// c = c & ~0xE0; // Clear self-test bits [7:5]
c = c & ~0x18;  // Clear AFS bits [4:3]
c = c | Ascale << 3; // Set full scale range for the accelerometer
writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, c); // Write new ACCEL_CONFIG register value

// Set accelerometer sample rate configuration
// It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for
// accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz
c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG2); // get current ACCEL_CONFIG2 register value
c = c & ~0x0F; // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0])
c = c | 0x03;  // Set accelerometer rate to 1 kHz and bandwidth to 41 Hz
writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c); // Write new ACCEL_CONFIG2 register value

// The accelerometer, gyro, and thermometer are set to 1 kHz sample rates,
// but all these rates are further reduced by a factor of 5 to 200 Hz because of the SMPLRT_DIV setting

// Configure Interrupts and Bypass Enable
// Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared,
// clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips
// can join the I2C bus and all can be controlled by the Arduino as master
//   writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22);
writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x12);  // INT is 50 microsecond pulse and any read to clear
writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01);  // Enable data ready (bit 0) interrupt
delay(100);

}

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453240848, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qmyW5ACbAhfoRiychfpBVRUYwcFoks5vB6GTgaJpZM4Z2Q90 .

laurentvm commented 5 years ago

I will try to use the Wire class as you do. There is maybe something wrong.

Could you advise me where to buy a good board (Teensy?). I'm in europe so a european shop would be better and faster.

There still something I do not understand on the concept. If the filter is a gradient based algo, it's higly dependent on the starting point. You get a sensor data point, previous quaternion and iterate a few time to converge the filter from previous quaternion.

When the sensor is not moving at all, I probably start with an initial bad starting point. If you look at previous graph, we see that. It reach very slowly an optimum and then it's faster because you follow a movement from previous points that is not too far from current position.

When you are standing still, basically, the update rate of sensor (if resonnable) does not affect anything because you do not have to follow a movement. You are iterating with an initial point that is the same after the filter.

kriswiner commented 5 years ago

If the sensor is well calibrated, yes it will take some (short) time (seconds) to converge to a stable absolute orientation when starting from the arbitrary 1 0 0 0 quaternion, but it shouldn;t take 60 seconds.

I recommend this https://www.tindie.com/products/TleraCorp/ladybug-stm32l432-development-board/ device. or this https://www.tindie.com/products/TleraCorp/dragonfly-stm32l47696-development-board/ one.

On Thu, Jan 10, 2019 at 12:56 PM laurentvm notifications@github.com wrote:

I will try to use the Wire class as you do. There is maybe something wrong.

Could you advise me where to buy a good board (Teensy?). I'm in europe so a european should would be better and faster.

There still something I do not understand on the concept. If the filter is a gradient based algo, it's higly dependent on the starting point. You get a sensor data point, previous quaternion and iterate a few time to converge the filter from previous quaternion.

When the sensor is not moving at all, I probably start with an initial bad starting point. If you look at previous graph, we see that. It reach very slowly an optimum and then it's faster because you follow a movement from previous points that is not too far from current position.

When you are standing still, basically, the update rate of sensor (if resonnable) does not affect anything because you do not have to follow a movement. You are iterating with an initial point that is the same after the filter.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/336#issuecomment-453250468, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qrIBGAtpJ4e7uCt1QYqjp4np5fiDks5vB6j1gaJpZM4Z2Q90 .