Tuesday, April 7, 2015

Saleae Logic 8 to Monitor Servo PWM and I2C to PCA9685

I started working on sending multiple signals to multiple servo channels. The PCA9685 is a 16 Channel PWM controller. As I need to work with 18 Channels for my PiHexJ robot at some point I have to add support for more than one PCA9685 device. I have two ready to hook up. That gives me 32 channels enough for the all 18 leg servos and plenty left over for additional controls.

In order to get a better view of what's going on at the I2C bus level I need a better analyzer. I decided on a Saleae Logic 8. I have a number of up coming use cases that I want to use this for including;
  • Analyzing the I2C bus when addressing more than 1 device
  • PWM measurement in response to servo update commands
  • Measuring sensor output and ADC output
  • RC receiver decoding that I will be working on shortly.
The Saleae device is tiny. In the picture below you can see the size relative to my breadboard. It connects to my Mac via USB and comes with 8 input channels. I have hooked up the device as follows
  • channels 0-4 to corresponding servo PWM signal output channels 0 -4
  • channel 4 to I2C SDA
  • channel 5 to I2C SCL
To test out the Saleae I am going to test updating a servo output. Before the capture I update the servo to -90 but posting {"channel":0,"angle":-90} to my rest api on PiHexJ. I create the rest api to make it easier to send these kind of commands for the PiHexJ robot controller to handle.

Analyzing servo output with Saleae Logic 8 
I2C signals a start by pulling SDA low. This is the trigger. I set the trigger in the Saleae Logic application on the falling edge of SDA and started the capture so I could see the I2C bus messages and the resulting change to the signal output on the servo channel. Once set I post {"channel":0,"angle":90} to the rest interface PiHexJ will send the I2C instruction to the PCA9685 controller to set the PWM output to the max. The pulse width should change from 1ms to 2ms

Capture of I2C and Servo PWM Channel 0
The Saleae device can capture up to 8 channels. In this example I am only showing 3 channels. On the left of the screen shot you can see the channel labels. The logic application includes protocol analyzers for some common protocols including I2C. I have added the I2C protocol analyzer to my capture with SDA and SCL marked appropriately.

Channel 0 is my servo channel shown in blue. As you can see the blue channel has pulses regularly with the I2C data sent in the yellow and green channels in the middle of the screen. Lets zoom in to see the change to PCA9685 PWM output as a result of the I2C signals.

PWM updated via I2C
On the Servo0 channel (blue) you can see the the signal has changed from length 1ms to 2ms. The Saleae Logic application has a useful measure annotation you can put on the trace to measure the width of the signal. I was looking for 1ms and 2ms. It's pretty close at 1.025ms and 2.046.

Now lets zoom in even further and look at the I2C signals:

I2C Signals
My code is far from ideal as it writes registers one by one. I can optimize that later with the operation that writes sequential registers. However we can see the signals correspond to the code.
    public void updateServo(ServoUpdateEvent servoUpdate) throws IOException {
        if (servoUpdate.getServo().getServoConfig().getChannel() > 15) {
            log.warn("Haven't implemented channels > 15");
        // update cache first
        if (isMoved(servoUpdate)) {
            // only send update to servo if its position has actually moved.
            int servoChannel = servoUpdate.getServo().getServoConfig().getChannel();
            int pulseLength = servoUpdate.getServo().getPulseLength(servoUpdate.getAngle());

            // calc num counts for ms
            long count = Math.round(pulseLength * RESOLUTION / ((double) 1 / (double) getPulseFrequency()) / (double) 1000000);

            log.debug("Updating servo position: {}, count: {}", servoUpdate.toString(), count);

            byte[] offBytes = ByteUtils.get2ByteInt((int) count);
            device.writeRegister(getRegisterForChannel(servoChannel, Register.ON_LOW), (byte) 0x00);
            device.writeRegister(getRegisterForChannel(servoChannel, Register.ON_HIGH), (byte) 0x00);
            device.writeRegister(getRegisterForChannel(servoChannel, Register.OFF_LOW), offBytes[ByteUtils.LOW_BYTE]);
            device.writeRegister(getRegisterForChannel(servoChannel, Register.OFF_HIGH), offBytes[ByteUtils.HIGH_BYTE]);
I currently start servo pulses at 0 so I write 0 to both ON low and high registers. This is not smart I should stagger this to spread the power draw more evenly.

Looking at the debug from my PiHexJ code I can see the update servo log entry:
DEBUG com.margic.adafruitpwm.AdafruitServoDriver - Updating servo position: com.margic.pihex.event.ServoUpdateEvent@d71bd3[servo=com.margic.pihex.ServoImpl@1342314[servoConfig=com.margic.pihex.model.ServoConfig@149ca71[name=Leg 0 Coxa,channel=0,range=180,center=0,startAngle=0,lowlimit=-90,highLimit=90]],angle=90], count: 410

I currently start servo pulses at 0 so I write 0 to both ON low and high registers. This is not smart I should stagger this to spread the power draw more evenly. My code calculates for a default calibration a +90 deg angle (or max right angle) should be 410 counts of the 4096 total counts for a 20ms duration. Where 4096 is the servo drivers resolution. Therefore on is 0 off is 410.
410 is 0000000110011010 in binary

high byte 0000 0001 = 0x01
low byte 1001 1010 = 0x9A

There are four interactions corresponding to the 4 writes in my ServoDriver class. My code writes correspond to following: (see PCA9685 Datasheet for reference)
  • 0x00 to register 0x06 (LED0_ON_L)
  • 0x00 to register 0x07 (LED0_ON_H)
  • 0x9A to register 0x08 (LED0_OFF_L)
  • 0x01 to register 0x09 (LED0_OFF_H)
Lets look at that third write even closer to see the signaling of register and value

The Saleae Logic application's protocol analyzer has done the hard work of decoding the I2C values for us. We can see my application wrote 0x80, the register address and 0x9A the register value. In addition to automatically adding the labels in blue above the SDA channel it also has a protocol output window. I have it set to show from the start of the interaction to the end. This window shows all the values written for my PCA9685 I2C writes.

In conclusion I think the Saleae Logic 8 device will be extremely beneficial for my PiHexJ Raspberry Pi Based Hex Robot. Over the next few weeks I'm sure I'll be posting more use cases. I'm looking forward to the RC radio receive signal decoding, multiplexing and timing in the AVR microcontroller.


  1. constantly i used to read smaller content that also clear their motive, and that is also happening with this post which I am reading at this place. sign in to gmail

  2. thanks due to the fact you have been precise-natured to percentage opinion subsequent to us. we are able to continually recognize all you have finished here because I understand you are selected worried thinking about our. Young Thug Net Worth

  3. An alternative technology is the use of highly efficient 'white' LEDs around the border of the screen (usually referred to as 'edge-lit').Desktopcon's 240hz monitor

  4. Nowadays, since they are in same price range we may see that people slowly start to change their LCD for LED monitors since they use less power and may produce more vivid colors, better brightness and deeper black levels. In fact, LEDs use about 20-30% less power compared to LCD monitors.Click here

  5. Please let me know if you’re looking for a article writer for your site. You have some really great posts and I feel I would be a good asset. If you ever want to take some of the load off, I’d absolutely love to write some material for your blog in exchange for a link back to mine. Please send me an email if interested. Thank you! Best 240HZ Monitor 2019

  6. I will always be treated with all the utmost respect. canadian mortgage calculator There are two forces that will customize the value from the equity within the house, market growth and mortgage repayment. mortgage calculator