I’m building a system that uses 4 BNO055 IMUs with an ESP32. Since each BNO055 has only two I²C addresses (0x28, 0x29), I split them across two I²C buses:
Bus 1 (GPIO 21/22) → IMU1 (0x28) + IMU2 (0x29)
Bus 2 (GPIO 18/19) → IMU3 (0x28) + IMU4 (0x29)
From my timing tests:
Reading quaternion data from one IMU takes ~2 ms
Sequentially reading all 4 → ~8 ms total
In theory, if I use dual-core tasks, Core0 could read IMU1+IMU2, and Core1 could read IMU3+IMU4, which should bring the total down to ~4 ms
What I want to clarify:
Can I use xTaskCreatePinnedToCore() so that each core runs its own I²C bus handling independently (Core0 = Bus1, Core1 = Bus2)?
Will this actually reduce acquisition time (true parallelism), or will there still be sequential overhead due to ESP32 scheduling or I²C driver limitations?
Do the two cores execute tasks truly in parallel, or is there a hidden bottleneck in the I²C hardware/driver that still serializes operations?
What’s the best way to time-stamp each IMU’s data (millis(), micros(), or ESP32 timers) so that I can keep track of when data was captured?
Are there any pitfalls with FreeRTOS tasks, I²C driver conflicts, or synchronization between cores that I should watch out for?
My goal is to make sure IMU readings from both buses are as close in time as possible.
If anyone has tried something similar (ESP32 + multiple IMUs + dual core), I’d love to hear your experience.
Yes you can, though you could also read both busses from the same core.
It should do.
Only 1 core can access any bus at one time.
The main thing to consider is data transfer between the cores.
That might be rather tricky to achieve. One core will be running the main App, and the other won't be. One core may be running the WiFi events and the other won't be. You could send a trigger through a Queue between 1 core and the other to initiate reading and another Queue to send back the results to the Main App.
Now i am starting to wonder why though. What do you need for orientation sensors for to begin with and how are you physically going to connect them to the MCU for them to provide you with different data ?
That sounds seriously excessive (even at the default speed). I haven't read up to 6much on it, but how much data are we talking about here ?
Assuming you're not sharing data between ISR and non-ISR code across cores (which would require a Critical Section, then you can use the same synchronization techniques as in a single-core, multi-tasking environment.
Also, Core 0 is much more sensitive to misbehaving tasks. You'll get a watchdog reset if a task hangs for too long. That only happen on Core 1 if you hang a task with interrupts disabled.