I am using the following hardware:
stm32f401ccu6+ mpu9250
(or rather 6500 - without a magnetometer)esp32 + mpu9250
(or rather 6500 - without a magnetometer)
Software:arduino IDE 1.8.19
- example code from here.
I know for sure that myMPU9250
is fake and does not have a magnetometer.
But ... now I am conducting an experiment, I takeESP32 + MPU9250
andSTM32F4 + MPU9250
.
I flash these two microcontrollers with the same code, of course, forSTM32
I choose the core, and forESP32
I choose the core.
These cores have differentwire.cpp
files.
But the point is not that, on each microcontroller, I compare with the help of alogic analyzer
what happens on theI2C
bus when the microcontroller communicates with theMPU9250
board.
So, when I run the code onSTM32 + MPU9250
, packet transmission starts on theI2C
bus.
The first packet has3 bytes
, then after99.6ms
another packet of31 bytes
, and then after2.9ms
the last packet of30 bytes
and with that all activity on the bus stops.
In this case, of course, theMPU9250
does not transmit any data to the bus, and nothing is output to the serial.
It is impossible to make screenshots in detail, because it is very small and you get a lot of information.
When I load the code intoESP32 + MPU9250
, miracles happen.
Firstly, the data from theMPU9250
board goes to theserial
port.
Of course, themagnetometer
does not give anything - because it does not exist!
But, what is going on on theI2C
bus?
And what happens on the bus is approximately the same as on theSTM32F4
bus, only there are differences.
Packet transmission also starts with3 bytes
, and is similar to the packet inSTM32F4
.
Then, after99.3 ms
, there is also a packet of31 bytes
and it is similar to the packet inSTM32F4
.
But the next packet is different ... it consists of26 bytes
, i.e.4 bytes
shorter thanSTM32F4
.
Data from the signal analyzer of the third package fromSTM32F4 + MPU9250
below
Data on theI2C
bus on theSTM32F4
1.
write to 0x68 ack data: 0x6B 0x80
2.
write to 0x68 ack data: 0x6B 0x00
write to 0x68 ack data: 0x1D 0x48
write to 0x68 ack data: 0x1B 0x18
write to 0x68 ack data: 0x1C 0x00
write to 0x68 ack data: 0x1A 0x03
write to 0x68 ack data: 0x19 0x13
write to 0x68 ack data: 0x1A 0x04
write to 0x68 ack data: 0x38 0x00
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00
3.
write to 0x68 ack data: 0x37 0x82
write to 0x0C nak
read to 0x0C nak
write to 0x0D nak
read to 0x0D nak
write to 0x0E nak
read to 0x0E nak
write to 0x0F nak
read to 0x0F nak
write to 0x68 ack data: 0x34 0x04
write to 0x68 ack data: 0x6B 0x40
write to 0x68 ack data: 0x6C 0x3F
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10
write to 0x68 ack data: 0x6A 0x00
Stop
Data from the signal analyzer of the third package from ESP32 + MPU9250
below
Data on the
I2C
bus on the ESP32
in table
1.
write to 0x68 ack data: 0x6B 0x80
2.
write to 0x68 ack data: 0x6B 0x00
write to 0x68 ack data: 0x1D 0x48
write to 0x68 ack data: 0x1B 0x18
write to 0x68 ack data: 0x1C 0x00
write to 0x68 ack data: 0x1A 0x03
write to 0x68 ack data: 0x19 0x13
write to 0x68 ack data: 0x1A 0x04
write to 0x68 ack data: 0x38 0x00
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00
3.
write to 0x68 ack data: 0x37 0x82
write to 0x0C nak
write to 0x0D nak
write to 0x0E nak
write to 0x0F nak
write to 0x68 ack data: 0x34 0x04
write to 0x68 ack data: 0x6B 0x40
write to 0x68 ack data: 0x6C 0x3F
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10
write to 0x68 ack data: 0x6A 0x00
4.
write to 0x68 ack data: 0x6B 0x01
write to 0x68 ack data: 0x6C 0x00
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x11
write to 0x68 ack data: 0x6A 0x20
5.
write to 0x68 ack data: 0x6B 0x01
write to 0x68 ack data: 0x6C 0x00
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x20
write to 0x68 ack data: 0x64 0x11
write to 0x68 ack data: 0x6A 0x20
6. Data...
write to 0x68 ack data: 0x1A 0x06
write to 0x68 ack data: 0x19 0x63
write to 0x68 ack data: 0x34 0x00
write to 0x68 ack data: 0x34 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x05
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xDE 0xF8 0xCE 0x50 0xEF 0x08
write to 0x68 ack data: 0x43
read to 0x68 ack data: 0xFF 0xB3 0x00 0x2B 0x00 0x1D
write to 0x68 ack data: 0x49
read to 0x68 ack data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A
ESP32 on the left, STM32F4 on the right.
For
STM32F4
, communication on the I2C
bus ends with 3 packets
.For
ESP32
after three packet of data, activity on the I2C
bus continues .After the third packet of data, after
49.9 ms
there is a packet of data consisting of 16 bytes
, and then, also after 49.9 ms
, another packet of data consisting of 16 bytes
.Well, then, after
50.1 ms
, the actual data transfer from the MPU9250
begins and this data is output to the ESP32 serial port
.I don't understand what's wrong with my
STM32F4
or MPU9250
?The
I2C
bus on STM32F4
works, but stops working.@fpistm everything works for you ...
I noticed that in the
wire.cpp
file of the ESP32
there is no bit shift to the left for the device address, in the wire.cpp
file of the STM core this happens.
ownAddress = address << 1;
_i2c.isMaster = (address == MASTER_ADDRESS) ? 1 : 0;
_i2c.generalCall = (generalCall == true) ? 1 : 0;
_i2c.NoStretchMode = (NoStretchMode == true) ? 1 : 0;
recoverBus(); // in case I2C bus (device) is stuck after a reset for example
i2c_custom_init(&_i2c, 100000, I2C_ADDRESSINGMODE_7BIT, ownAddress);
I tried to remove the bit shift of the address, but there are no changes in the work.
Only a different address is written to the I2C
bus, apparently in the ESP32 core, the device address is shifted elsewhere(or file) in order to have a 7-bit address
.
...
Termination of activity on the I2C
bus occurs after the execution of the code
Pack 1
write to 0x68 ack data: 0x6B 0x80 //inv_mpu.c string 652 pwr_mgmt_1
Pack 2
write to 0x68 ack data: 0x6B 0x00 //inv_mpu.c 658 pwr_mgmt_1
write to 0x68 ack data: 0x1D 0x48 //inv_mpu.c 668 accel_cfg2
write to 0x68 ack data: 0x1B 0x18 //inv_mpu.c 1171 gyro_cfg
write to 0x68 ack data: 0x1C 0x00 //inv_mpu.c 1236 accel_cfg
write to 0x68 ack data: 0x1A 0x03 //inv_mpu.c 1305/1368 lpf
write to 0x68 ack data: 0x19 0x13 //inv_mpu.c 1358 rate_div
write to 0x68 ack data: 0x1A 0x04 //inv_mpu.c 1361 lpf
write to 0x68 ack data: 0x38 0x00 //inv_mpu.c 579 int_enable
write to 0x68 ack data: 0x6A //user_ctrl, mpu_set_bypass
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00 //user_ctrl
Pack 3
write to 0x68 ack data: 0x37 0x82 //inv_mpu.c 2868 mpu_set_bypass(1)
/* Find compass. Possible addresses range from 0x0C to 0x0F. */
write to 0x0C nak //inv_mpu.c 2871 find compass - no
read to 0x0C nak
write to 0x0D nak
read to 0x0D nak
write to 0x0E nak
read to 0x0E nak
write to 0x0F nak
read to 0x0F nak//Compass not found
write to 0x68 ack data: 0x34 0x04 //inv_mpu.c 1408 s4_ctrl
write to 0x68 ack data: 0x6B 0x40
write to 0x68 ack data: 0x6C 0x3F
write to 0x68 ack data: 0x6A
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10 //inv_mpu.c 1614 s1_do
write to 0x68 ack data: 0x6A 0x00 //inv_mpu.c 1617
Stop
Simple code works great on stm32f401ccu6+ mpu9250
#include "Wire.h"
const int MPU_addr = 0x68; // sensor address
// data array
// [accX, accY, accZ, temp, gyrX, gyrY, gyrZ]
// acc - acceleration, gyr - angular velocity, temp - temperature (raw)
int16_t data[7];
void setup() {
// initialization
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up)
Wire.endTransmission(true);
Serial.begin(115200);
}
void loop() {
getData(); // get data
// print
for (byte i = 0; i < 7; i++) {
Serial.print(data[i]);
Serial.print('\t');
}
Serial.println();
delay(200);
}
void getData() {
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
for (byte i = 0; i < 7; i++) {
data[i] = Wire.read() << 8 | Wire.read();
}
}
and I get raw data ACCEL_XOUT_H
on I2C
write to 0x68 ack data: 0x6B 0x00
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x4C 0x00 0xC8 0x41 0x88 0x0E 0x20 0xFD 0xAB 0x01 0x93 0x00 0x9A
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x68 0x00 0xA0 0x41 0x7C 0x0E 0x70 0xFD 0xBA 0x01 0x86 0x00 0xB8
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x50 0x00 0xAC 0x41 0x8C 0x0E 0x70 0xFD 0xA0 0x01 0x8E 0x00 0xAC
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x34 0x00 0xD0 0x41 0x20 0x0E 0x50 0xFD 0xA5 0x01 0x74 0x00 0xA1
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x90 0x00 0x90 0x41 0x94 0x0E 0x40 0xFD 0xA2 0x01 0x6B 0x00 0xBB
write to 0x68 ack data: 0x3B
read to 0x68 ack data: 0xF2 0x98 0x01 0x10 0x41 0x7C 0x0E 0x50 0xFD 0x97 0x01 0x6D 0x00 0xE1
and Serial
.
I also found that the core uses a not very fresh Wire library, but everything works for others, it doesn’t work only with my hardware (I have 3 BlackPills).
What could be the problem?