<< Summary

Use the Adafruit PCA9685 with a Raspberry PI, in Java Raspberry PI
to drive up to 16 servos

The Servo Driver we are talking about here is the Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface - PCA9685.

The original tutorial from Adafruit is available here. The language it uses is Python.

This board has an I2C (pronounced I "square" C) interface, that needs to be enabled on the Raspberry PI.
I2C stands for Inter-Integrated-Circuit.
Arduino & Adafruit provide python libraries that go along with their components. The code we present here is in big part an adaptation of this code.

Enable I2C on the Raspberry PI

We will show how to enable I2C on a Model B Raspberry PI. There is a lot of documentation on the web on how to do it on whatever version on the RasPI you have. We are not going to duplicate the web in this document...
We will need to edit several configuration files. Use the editor you prefer (nano, vi, gedit, ...), as root (sudo).
  1. Edit /etc/modules
    Make sure its content eventually looks like this:
    
      i2c-bcm2708
      i2c-dev
              
    Save your modifications, if you have done any.
  2. Install some I2C Utilities (in python)
    
     Prompt> sudo apt-get install python-smbus
     Prompt> sudo apt-get install i2c-tools
              
  3. Edit /etc/modprobe.d/raspi-blacklist.conf, comment the two lines it contents:
    Before:
    
     blacklist spi-bcm2708
     blacklist i2c-bcm2708
              

    After:
    
     # blacklist spi-bcm2708
     # blacklist i2c-bcm2708
              
    Save your modifications, if you have done any.
  4. By now (the PCA9685 needs to be wired for that), you should be able to run the i2cdetect utility, which will will use to know the address of the servo driver:
    
     Prompt> sudo i2cdetect -y 1
          0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
     00:          -- -- -- -- -- -- -- -- -- -- -- -- --
     10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     70: 70 -- -- -- -- -- -- --
              
    As seen above, the I2C addresses range from 0x03 to 0x77 (binary 0000011 to 1110111). This way, several boards can be used simultaneously from the RasPI, as long as their I2C addresses are different, even if the GPIO interface pins are connected to several different boards.
    For example, if you have connected you would have
    
     Prompt> sudo i2cdetect -y 1
          0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
     00:          -- -- -- -- -- -- -- -- -- -- -- -- --
     10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
     20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     70: 70 -- -- -- -- -- -- 77
              
    where, in addition to the above,

Wiring

The connection setting is quite simple.

PCA9685Raspberry PI
VCC1. 3.3 VDC Power
GND6. 0V (Ground)
SDA3. SDA0 (I2C)
SCL5. SCL0 (I2C)
Raspberry PI P1 Connector map Click to enlarge Click to enlarge
The Raspberry PI, connected to a PCA9685, with 2 servos.
This diagram shows the name of the pins you want to use on the GPIO Connector of the Raspberry PI. As we said before, we need to use the pins 1, 3, 5, and 6.

Programming

You will need to know what address to talk to to reach the PCA9685. Run the i2cdetect utility.

 Prompt> sudo i2cdetect -y 1
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
 00:          -- -- -- -- -- -- -- -- -- -- -- -- --
 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 70: 70 -- -- -- -- -- -- --
      
We will use the 0x40 address to reach the PCA9685.
The Java code we are interested in is in the class named PCA9685. Check it out in the repository. We are going to comment only on the main method of this class, which is a basic example. It assumes that 2 servos are connected to the PCA9685, on the 15 and 14 slots.
The PCA9685 has 16 such slots, numbered - on the board - from 0 to 15. See them on the picture at the top of this document. The slots we are talking about are the 16 columns of 3 holes drilled at the bottom of the board. Their number is printed on top of each column of 3 holes.

  ...
  public static void main(String[] args)
  {
    PCA9685 servoBoard = new PCA9685();   // 0x40 is the default address
    servoBoard.setPWMFreq(60); // Set frequency to 60 Hz
    int servoMin = 150;   // Min pulse length out of 4096
    int servoMax = 600;   // Max pulse length out of 4096
    
    final int CONTINUOUS_SERVO_CHANNEL = 14;
    final int STANDARD_SERVO_CHANNEL   = 15;
    
    for (int i=0; i<10; i++)
    {
      System.out.println("i=" + i);
      servoBoard.setPWM(STANDARD_SERVO_CHANNEL,   0, servoMin);
      servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, servoMin);
      waitfor(1000);
      servoBoard.setPWM(STANDARD_SERVO_CHANNEL,   0, servoMax);
      servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, servoMax);
      waitfor(1000);
    } 
    servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, 0); // Stop the continuous one
    System.out.println("Done with the demo.");
  }
  ...
      
This code loops 10 times and makes the servos go from a value of 150 to a value of 600, and vice versa. It waits for 1000 milliseconds between each message to the servos.
Notice the two int variables, CONTINUOUS_SERVO_CHANNEL and STANDARD_SERVO_CHANNEL.
For this demo, the standard servo we use is the Standard servo - TowerPro SG-5010 - 5010.
As seen in its documentation, the servo rotates on 180°, 90° on each side. Position "0" (1.5ms pulse) is middle, "90" (~2ms pulse) is all the way to the right, "-90" (~1ms pulse) is all the way to the left.
We see we use a 60 Hz frequency. This means we will have 60 cycles per second. Each cycle contains 4096 ticks.
The value minServo is 150.
The value maxServo is 600.
A full cycle (of 4096 ticks) at 60 Hz will take 1 / 60 ~ 16 ms.
150 ticks would take 150 / (60 * 4096) seconds, which is ~ 0.61 ms.
600 ticks would take 600 / (60 * 4096) seconds, which is ~ 2.44 ms.

More generically It is quite easy - and convenient - to put those formulas in a spreadsheet.
Based on those formulas, we should have:
Pulse Width
in ms
Nb Ticks
1246
1.5369
2492
The values given in the Adafruit tutorial (150 & 600) happens to be a bit different of what the documentation of the servo says..., but they actually work fine, and this is the ones we use in the code:
Pulse Width
in ms
Nb Ticks
1150
1.5375
2600

Running

Make sure you've build the required archives:
          
 $I2C.SPI> ../gradlew clean shadowJar
      
You can run the code from a script named servo:

 #!/bin/bash
 CP=./build/libs/I2C.SPI-1.0-all.jar
 sudo java -cp $CP i2c.servo.pwm.PCA9685
      

 Prompt> ./servo
      
And here is the result


 Prompt> ./servo
 Connected to bus. OK.
 Connected to device. OK.
 Setting PWM frequency to 60 Hz
 Estimated pre-scale: 100.72526
 Final pre-scale: 101.0
 i=0
 i=1
 i=2
 i=3
 i=4
 i=5
 i=6
 i=7
 i=8
 i=9
 Done with the demo
 Prompt>
              
The console output

And what next?

Drive the Raspberry PI, on its own cart...
Fuel the Raspberry PI with a solar panel, oriented by servos to face the sun for greater efficiency.

Something to be aware of...

I followed the PWM instructions, came up with several spreadsheets for the calculations, and... it just did not work correctly.
Both standard and continuous servos are supposed to be triggered with pulses having width ranging from 1 to 2 ms. As seen above, at 60 Hz, that makes 246 to 492 ticks.
In reality, after many manual trials, for a frequence of 60 Hz, I used:
For the Standard Servo Between 122 & 615 ticks
For the Continuous Servo Between 340 & 410 ticks, stop at 375
Those values are suprisingly different from the theorical ones..., but they work.
See in the code the classes named i2c.samples.DemoContinuous and i2c.samples.DemoStandard.
Those are the ones I will use as bases for robotic projects.


Oliv did it