Sunday, April 12, 2015

Optimizing Java PCA9685 driver using Saleae Logic 8 Analyzer Part 1

In my previous post Saleae Logic 8 to Monitor Servo PWM and I2C to PCA9685 I was able to verify my servo updates were performing as expected by monitoring both the I2C traffic and the resulting PWM pulses on the servo channels. The was one observation that gave cause for concern was the time it took to update to update a single servo. It takes 4 register updates to change the servo PWM pulse. That means 4 I2C updates passing the device address, register address and value to write in the register.

In the logic analyzer screenshot below the green and yellow channels show the I2C traffic for the single servo update. The duration is annotated in the window on the right. The duration is approx 3ms. This doesn't sound a lot. However a typical leg move will require updates to at least 3 servos and possibly upto  9. That means a min of 18ms for all servos to be updated. Sequencing a smooth motion with a 18ms+ latency will not be effective.

Time annotation showing duration of 1 servo update
The PCA9685 data sheet describes bit 5 of the MODE1 register enables auto-increment.

MODE1 Register

The foot note describes the following...
When the Auto Increment flag is set, AI = 1, the Control register is automatically incremented after a read or write. This allows the user to program the registers sequentially.

I wanted to see the effect of using the auto increment function by setting this flag. The datasheet provides an example of using this with the flag clear.
Write all registers
This shows setting the device address, followed by the registers starting with register 0 to set auto increment. I ran a test using this approach writing all registers up to register 69 that corresponds to the 16th servo channel.

I ran a test setting all the registers from register 0 as per the datasheet example to evaluate the time take. The screen shot below from the Saleae logic analyzer shows the I2C traffic. The time for writing all 69 registers is 6.5ms compared to 3ms for 4 registers individually. This is a significant improvement and will be way more effective for creating smoother motions when animating the servos to perform leg movements.

Time annotation showing duration of sequential 16 servo update
The next test I will try to further optimize the writes is to determine if I have to start at register zero when using auto increment. The datasheet is not specific about this but does hint at the possibility as it mentions auto increment also works on registers 250 - 254 before rolling over to register 0. What is not clear is if the I start at servo 0 register, register 6 and right some registers what will happen.

The Salae logic analyzer will help determine the what will happen to the servo outputs. I will post an update once I have the test results. I have checked in the code used to test this use case. It obviously will need further updates once the optimization testing is done.