EZ-B V3 Configuration icon EZ-B V3 Configuration Manage EZ-B hardware settings: edit Bluetooth name and apply updates to restore altered configurations. Try it →
New Zealand
Asked
MPU9150 polling freezes PCA9685 servos

MPU9150 Polling Freezes PCA9685 Servos

Setup: Arduino Uno over USB to ARC running the Arduino EZB firmware, with an Adafruit PCA9685 16channel servo driver on the Arduino’s I2C (addr 0x40) driving 8 MG996R servos. Separate 5V/6A supply to servos, common ground tied to Arduino and PCA9685. I also have an MPU9150 IMU (addr 0x68) on the same I2C bus. In ARC I’m using the MPU9150 Accelerometer, Gyro, Temperature, Compass robot skill to read orientation and map roll/pitch to two servos. Variables look good in the Variable Watcher until things lock.

Symptom: With a script polling the MPU9150 every 100 ms using ControlCommand("MPU9150", "RunOnce"), after 20-90 seconds all servos on the PCA9685 freeze and the EZB connection becomes unresponsive until I reset the Arduino. If I stop polling the IMU, the PCA9685 runs for hours. Slowing to 500 ms extends the time but it still eventually freezes.

What I tried:

  • Verified I2C addresses: PCA9685 0x40, MPU9150 0x68, no conflicts.
  • Shortened SDA/SCL leads to ~20 cm and added 4.7k pullups to 5V (also tried 2.2k).
  • Ensured solid 5V servo supply and GND common to Arduino/PCA9685/IMU.
  • Called Init once, then RunOnce as documented; also tried pausing Auto Position during reads.
  • Removed the IMU: no freezes; left IMU connected but no RunOnce calls: no freezes.

Minimal script causing the issue:

ControlCommand("MPU9150", "Init")
:loop
  ControlCommand("MPU9150", "RunOnce")
  $roll = $mpu9150_roll
  $pitch = $mpu9150_pitch
  Servo(D0, 90 + ($roll*2))
  Servo(D1, 90 + ($pitch*2))
  Sleep(100)
Goto(loop)

Is this a known I2C blocking issue when using the MPU9150 skill alongside a PCA9685 via an Arduino running EZB firmware, and would migrating the servos to the PCA9685 servo Driver robot skill (recommended method) or reducing the EZB I2C clock be the right fix here?



Related Hardware (view all EZB hardware)
Control PCA9685 servo breakout with Arduino Uno using Synthiam ARC and EZB firmware; servo shield support and programming tutorial.
USB
Servos 16
Camera
Audio
UART
I2C
ADC
Digital

Related Robot Skills (view all robot skills)
MPU9150 ARC control reads compass, gyro, accelerometer and temperature via I2C, initializes and sets EZ-Script variables on demand.
PCA9685 Servo Driver by Synthiam Inc
Drive 16 servos over EZB I2C with a PCA9685 PWM controller, using ARC servo commands and hardware-timed outputs.

ARC Pro

Upgrade to ARC Pro

Elevate your robot's capabilities to the next level with Synthiam ARC Pro, unlocking a world of possibilities in robot programming.

Author Avatar
PRO
Canada
Twitter YouTube GitHub
#1  

Yes - this sounds much more like an I2C bus lock/blocking issue on the Arduino + EZB firmware side than a PCA9685 servo problem.

What your symptoms suggest

  • PCA9685 runs fine for hours until IMU polling starts
  • Freezing gets worse with more frequent RunOnce calls
  • Arduino becomes unresponsive until reset
  • Stopping IMU polling makes the problem disappear

That pattern usually means the MPU9150 read is occasionally hanging the I2C bus or the firmware thread, and once that happens the PCA9685 updates stop too because they share the same controller/bus path.


Why this happens

On a shared I2C bus:

  • The PCA9685 is being written repeatedly for servo PWM
  • The MPU9150 skill is periodically reading sensor data over the same bus
  • If the IMU read stalls, NACKs, or the device/bus gets into a bad state, the firmware can lock waiting on I2C
  • Once the Arduino firmware is blocked, all ARC communication can appear frozen

So even though the servo driver and IMU have different addresses, they still depend on the same I2C bus transaction flow.


Most likely fixes

1) Use the PCA9685 servo Driver robot skill instead of Arduino firmware I2C for servos

This is the recommended path now.

The big advantage is that ARC manages the PCA9685 through the skill layer, which tends to behave better than mixing multiple I2C devices through older firmware paths.

If your servos are on the PCA9685, I’d strongly recommend moving them to that skill and keeping the IMU separate in how it’s polled/handled.


2) Lower the I2C clock speed

If the IMU and PCA9685 must share the same bus, reducing I2C speed can improve reliability.

In ARC, the I2C clock can be set through script:

I2C.setClockSpeed(100000)

You can also try:

I2C.setClockSpeed(50000)

If the bus is marginal, slower is often more stable.


3) Poll less aggressively and avoid tight loops

Your 100 ms loop is reasonable, but if the device occasionally stalls, frequent reads increase the chance of hitting the failure window.

Try:

  • 250 ms or 500 ms
  • Add a fail-safe delay if readings stop changing
  • Avoid doing servo writes immediately after every IMU read unless necessary

4) Rework the logic so servo updates don’t depend directly on every IMU read

Instead of reading IMU and commanding servos in one tight loop, split responsibilities:

  • one loop updates IMU values
  • another loop applies servo positions at a slower rate

That can help reduce I2C pressure.


Important note about your current script

This part is suspicious:

Servo(D0, 90 + ($roll*2))
Servo(D1, 90 + ($pitch*2))

If these servos are actually on the PCA9685, they should usually be virtual ports like v0, v1, etc., not d0 and d1, unless you truly have native servo outputs on the Arduino firmware ports.

If those are PCA9685 channels, it should look more like:

Servo(v0, 90 + ($roll * 2))
Servo(v1, 90 + ($pitch * 2))

That matters because the port type determines whether ARC is talking through the correct servo subsystem.


What I would test next

  1. Confirm whether the PCA9685 servos are on virtual ports in ARC, not D ports
  2. Set I2C speed to 100000, then try 50000
  3. Change IMU polling to 250-500 ms
  4. If possible, move the servos to the PCA9685 servo Driver robot skill
  5. Test with the IMU loop only, then servos only, then both together

My recommendation

If this were my setup, I would:

  • migrate the PCA9685 to the PCA9685 servo Driver robot skill
  • keep the IMU on the bus only if needed
  • reduce I2C speed if instability remains
  • confirm all servo commands are using the correct V ports

That gives you the best chance of avoiding the bus lock.


If you want, I can help you rewrite that script for the PCA9685 skill using V0/V1 ports and show a safer architecture for the IMU polling loop.

I am a customer support AI and still learning. Please verify important answers in our support documentation. For advanced AI features, use the AI Script Agent built into ARC.