Wednesday, April 15, 2015

Optimizing Java PCA9685 driver using Saleae Logic 8 Analyzer Part 2

PiHexJ Java PCA9685 Driver

At the end of the last post I had changed the driver to update all the servo channel registers in one sequential write to the I2C Bus. Instead of writing <<address>><<value>><<address>><<value>> I changed it to write <<address>><<value>><<value>>

In the last test I was writing address = 0 and writing all the registers. The PCA9685 has a the auto increment flag bit 5 on mode 1 register. I was not sure if when set I had to start at 0 and increment all registers. I did not know if the register auto increment was reset on a I2C stop command.

I reworked the driver to allow this test to allow the driver to update starting from the first updated servo from the servo update buffer. The PCA9685 did works as expected. I can write servos starting from any channel and write the registers in a sequence. This mean updating the driver to optimize this write pattern. In my initial test it took 3ms to update a single servo without register auto increment. It took 6.5ms to write all registers using auto increment. This is a much faster write rate and the pay is when writing 3 or more servos.

Optimized Single Servo Update

With the optimized driver starting from the first updated servo the times are improved further. The screenshot before shows the write of a single servo.
Update single servo 0.56ms
The time for a single update is 0.56ms. This is way faster that both the 6.5ms sequential write or the 3ms for a single. With this scenario sequential write with register auto increment is always faster.

Optimized Multiple Servo Update

The following screen is showing updating 3 servos. 
3 Servo sequential servo update 1.275ms

Writing 3 servos took 1.275ms. These were three adjacent servo channels 0,1&2. It would take longer if writing 0 and 16 as the sequential write has to start at the lowest channel and auto increment over each channel to the last channel.

Changes to the Driver

With the results of the tests I made the following:

  1. Added UpdateSequential flag - It is unlikely to mix the modes between single servo updates vs sequential servo update. It made sense to make this a constructor on the servo driver. This means the driver update mode is set when the driver is created.
  2. Used the buffer to buffer update events - the update device method checks the first update and uses that channel to set the first register address. It then loops through the updates taking either the new settings in the update buffer or uses a cached value to write the current value back to the register to avoid writing empty values when sequentially writing registers.
  3. Added test for the new writing methods

I have to have to add tests for single write operations to ensure I haven't broken those operations even thought I would recommend using the optimized sequential write mode. I have yet to see a Java PCA9685 driver that works this way.

No comments:

Post a Comment