I have run code on an Arduino to verify that the IMU works, and it works fine. That code is here (https://www.luisllamas.es/usar-arduino- ... -mpu-9250/)I have written data (1 byte each time) to the IMU, and it has gone through fine. However, it stubbornly refuses to read anything off the sensor.
I have omitted the config code for brevity. However, it must be correct, as it has successfully written to a device register.
Here is the working write code:
Code: Select all
esp_err_t I2C::i2c_master_write_slave(uint8_t *data_wr, size_t size, uint8_t register2set)
{ //see above for comments
if (size == 0)
{
return ESP_OK;
}
if (register2set > 0xEF)
{
return ESP_FAIL;
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
std::cout<<"slavewrite status: "<<i2c_master_write_byte(cmd, (slaveaddress << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN)<<std::endl;
std::cout<<"registerwrite status: "<<i2c_master_write_byte(cmd, register2set, ACK_CHECK_EN)<<std::endl;
std::cout<<"data status: "<<i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN)<<std::endl;
std::cout<<"stop status: "<<i2c_master_stop(cmd)<<std::endl;
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
And here is the code that is not working for reading data
Code: Select all
esp_err_t I2C::i2c_master_read_slave(uint8_t *data_rd, size_t size, uint8_t register2get)
{
if (size == 0)
{
return ESP_OK;
}
if (register2get > 0xEF)
{
return ESP_FAIL;
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveaddress << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write_byte(cmd, register2get, ACK_CHECK_EN);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveaddress << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
if (size > 1)
{
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
i2c_master_stop(cmd);
auto ret=i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
Code: Select all
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveaddress << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write_byte(cmd, register2get, ACK_CHECK_EN);
i2c_master_stop(cmd);
auto ret=i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveaddress << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
if (size > 1)
{
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
My code to call the write is here in abridged form. It is an adaptation of the code used successfully by the arduino:
Code: Select all
I2C MPU9250(MPU9250_ADDRESS);
//Buf is the pointer to the length 14 buffer
uint8_t Buf[14];
std::cout<<"IMU Read Status: "<<MPU9250.i2c_master_read_slave(Buf, 1, 0x3B)<<std::endl;
//this always prints -1, which means that it failed.
https://www.esp32.com/viewtopic.php?t=3678
I'm at my wit's end as to why this keeps failing. I've tried all sorts of spurious combinations of commands in hopes that one would work, and so far, the only one that doesn't give the generic failure code (-1) is the one where it simply starts and ends an I2C transmission, which errors in a timeout error instead of a generic -1 error. None of the demo code online for I2C has worked for the writing part either. Does anyone have an idea what is wrong with the code to read from the IMU's register?
***Edit 9/14/2020***
After probing the SCL and SDA lines, it seems as though the ESP32 cannot actually transmit at the advertised speeds of 100KHz. The fastest it goes is actually only 100Hz, or 200Hz with certain combinations of external resistors. After dropping the speed 3 orders of magnitude, it actually outputs a clock signal and can start trying to communicate with other devices.
I'm now getting error 263, which is an error timeout. It's progress, but just barely. Also, it doesn't seem like I'm the only one to have this issue with reading from IMU sensors on the ESP32 platform:
https://www.reddit.com/r/esp32/comments ... c_timeout/