Using 16-Channel I2C, Servo Module with Raspberry Pi

Servo Board    Send article as PDF   
You want to make a cool robot, maybe a hexapod walker, or in my case I want to use 9g Micro Servos to switch the points on my LEGO Train Layout I’m constructing. Or maybe you want to drive a lot of LEDs with precise PWM output. Then you realize that your Raspberry Pi only has a single PWM output on GPIO-18! What now?

Using a 16-Channel I2C, 12-bit PWM Servo Driver Module with a Raspberry Pi.

You want to make a cool robot, maybe a hexapod walker, or in my case I want to use 9g Micro Servos to switch the points on my LEGO Train Layout I’m constructing. Or maybe you want to drive a lot of LEDs with precise PWM output. Then you realize that your Raspberry Pi only has a single PWM output on GPIO-18! What now?

16-Channel 12-bit PWM/ Servo Driver Module

Well this 16-Channel, 12-bit PWM, Servo Driver Module from Deek-Robot only uses only two pins, control 16 free-running PWM outputs! It uses an i2c-controlled PWM driver with a built in clock.

16-Channel 12-bit PWM/ Servo Driver Module


The Deek-Robot 16-Channel I2C, 12-bit PWM Servo Driver Module is a clone of the on available from Adafruit:

Unlike the TLC5940 family Chips, with this module that uses a ‘PCA9685’ Chip, you do not need to continuously send it signal tying up your microcontroller, its completely free running!

This Module cannot be used for driving anything other than analog (1-2 millisecond pulse drive) servos. DC motors, AC motors and 100% digital servos are not going to work. (NMost ‘Digital Servos’ still use the analog pulse interface and are suitable for use with this controller.)

It is 5V compliant, which means you can control it from a 3.3V Microcontroller and still safely drive up to 6V outputs (this is good for when you want to control white or blue LEDs with 3.4+ forward voltages).

  • Adjustable frequency PWM up to about 1.6 KHz
  • 12-bit resolution for each output – for servos, that means about 4us resolution at 60Hz update rate
  • Configurable push-pull or open-drain output
  • Output enable pin to quickly disable all the outputs
  • Terminal block for power input (or you can use the 0.1″ breakouts on the side)
  • Reverse polarity protection on the terminal block input
  • Green power-good LED
  • 3 pin connectors in groups of 4 so you can plug in 16 servos at once (Servo plugs are slightly wider than 0.1″ so you can only stack 4 next to each other on 0.1″ header).
  • “Chain-able” design
  • A spot to place a big capacitor on the V+ line (in case you need it)
  • 330 ohm series resistors on all the output lines to protect them, and to make driving LEDs trivial
  • Solder jumpers for the 6 address select pins

Addressing the Boards:

With, the 6 address selection pins you can wire up to 62 of these Modules on a single i2c bus, a total of 992 outputs – that’s a lot  of servos or LEDs.

Each board in the chain must be assigned a unique address.  This is done with the address jumpers on the upper right edge of the board.  The I2C base address for each board is 0x40.  The binary address that you program with the address jumpers is added to the base I2C address.

Setting I2C Address

To program the address offset, use a drop of solder to bridge the corresponding address jumper for each binary ‘1’ in the address. 

  • Board 0:  Address = 0x40  Offset = binary 00000 (no jumpers required)
  • Board 1:  Address = 0x41  Offset = binary 00001 (bridge A0 as in the photo above)
  • Board 2:  Address = 0x42  Offset = binary 00010 (bridge A1)
  • Board 3:  Address = 0x43  Offset = binary 00011 (bridge A0 & A1)
  • Board 4:  Address = 0x44  Offset = binary 00100 (bridge A2), etc.


Configuring Your Pi for I2C:

I2C is a very commonly used standard designed to allow one chip to talk to another. So, since the Raspberry Pi can talk I2C we can connect it to a variety of I2C capable chips and modules.

To make sure your Pi is ready to go with I2C we need to start by enabling the hardware. If you are using Raspbian, you will need to open LXTerminal and enter the following command:

sudo nano /etc/modules

and add these two lines to the end of the file:


After editing the file, you will need to reboot for the changes to take effect. 

The I2C bus allows connection of multiple devices to your Raspberry Pi, each with a unique address, that can often be set by changing jumper settings on the module. It is very useful to be able to see which devices are connected to your Pi as a way of making sure everything is working.

To do this, it is worth running the following commands in the Terminal to install the i2c-tools utility.

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

Depending on your distribution, you may also have a file calleraspi-blacklist.conf:

sudo nano /etc/modprobe.d/raspi-blacklist.conf.

If you do not have this file then there is nothing to do, however, if you do have this file, you need to edit it and comment out the lines below by putting a # in front of them.

blacklist spi-bcm2708
blacklist i2c-bcm2708

.. then edit the file so that it appears as below, and then save and exit the file using CTRL-x and Y. 

Raspberry Pi Blacklist

When you are ready to continue, enter the following commands to add SMBus support (which includes I2C) to Python:

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

i2c-tools isn’t strictly required, but it’s a useful package since you can use it to scan for any I2C or SMBus devices connected to your board. If you know something is connected, but you don’t know it’s 7-bit I2C address, this library has a great little tool to help you find it. python-smbus is required, it adds the I2C support for python!

Once this is all done, reboot!

sudo reboot

Now when you log in you can type the following command to see all the connected devices (if you are running a 512MB Raspberry Pi Model B):

sudo i2cdetect -y 1

Raspberry Pi I2C Detect

This shows that two I2C addresses are in use – 0x40 and 0x70.

Note that if you are using one of the very first Raspberry Pis (a 256MB Raspberry Pi Model B) then you will need to change the command to:

sudo i2cdetect -y 0

The Raspberry Pi designers swapped over I2C ports between board releases. Just remember: 512M Pi’s use i2c port 1, 256M ones use i2c port 0!

If an 16-Channel I2C, 12-bit PWM Servo Driver Module is properly connected and it’s set to it’s default address — meaning none of the 6 address solder jumpers at the top of the board have been soldered shut — it should show up at 0x40 (binary 1000000).

Once both of these packages have been installed, you have everything you need to get started accessing I2C and SMBus devices in Python.

Hooking it Up:

The TCA9685 (the actual chip that drives the servos) is powered by the 3.3V supply on the Pi (labelled VCC on the servo breakout). Because the servos have different power requirements — typically a 5V supply and as much as a couple hundred mA per servo — they need to be powered from a separate power supply, labelled V+.

Why not use the +5V supply on the Raspberry Pi?

Switching directions on the servo can cause a lot of noise on the supply, and the servo(s) will cause the voltage to fluctuate significantly, which is a bad situation for the Pi. It’s highly recommended to use an external 5V supply with servo motors to avoid problems caused by voltage drops on the Pi’s 5V line.

The easiest way to hook the servo module up to your Pi if you don’t have a WaveShare DVK512, is with a Pi Cobbler, as seen in the wiring diagram below:

Raspberry Pi Cobbler & Servo Module
For clarity sake, the servo in this image is connected to port 15 on the breakout.
The example code provided uses ports 0-4 by default.

16Ch Servo Board WaveShare DVK52 Rasbpberry Pi
16Ch Servo Module, WaveShare DVK512 Expansion Board and Rasbpberry Pi B+

If you are fortunate to own a Waveshare DVK512 for your Raspberry Pi B+, the connection couldn’t be simpler. Connect a 4x wire cable between the DVK512’s I2C Port and the Servo Module taking care to connect the wires correctly as labled.

VCC = the digital supply for the IC at 3.3V!
V+ = the supply for the servo motors (typically 5V)
     Be sure not to confuse the two or you may end up with burnt Pi!

Using the Adafruit Python Library:

Before you start, you’ll need to have the python smbus library installed by running:

sudo apt-get install python-smbus

The Python code for Adafruit’s PWM/Servo Module is suitable for the Deek-Robot Module as well and is available for the Pi  on Github at:

This code should be a good starting point to gaining an understanding how you can access SMBus/I2C devices with your Pi, and getting things moving with your PWM/Servo Module.

Downloading the Code from Github:

The easiest way to get the code onto your Pi is to hook up an Ethernet cable, and clone it directly using ‘git’, which is installed by default on most distros.  Simply run the following commands from an appropriate location (ex. “/home/pi/code“): 

git clone
cd Adafruit-Raspberry-Pi-Python-Code
cd Adafruit_PWM_Servo_Driver 

If you see the “check your I2C address” error message…

First, make certain that you have configured the right I2C address in, and that the Servo Driver is visible at that address. Refer back to the tutorial page Configuring Your Pi for I2C for instructions on verifying your I2C address and I2C bus number.

If your Servo Driver is responding to I2C, but the code is still giving you “check your I2C address” errors, then modify the code as follows: In the file, change:

self.i2c = Adafruit_I2C(address)

self.i2c = Adafruit_I2C(address, 0) for 256MB Raspberry Pi’s

self.i2c = Adafruit_I2C(address, 1) for 512MB Raspberry Pi’s

Testing the Library:

Once the code has be downloaded to an appropriate folder, and you have your PWM/Servo breakout and motor properly connected, you can test it out with the following command (the driver includes a simple demo program):

sudo python

Raspberry Pi Servo Module Example Code

To stop the example, simple press CTRL+C.

And that is it. Now you can but your Raspberry Pi to work controlling heaps of RC Servo Motors.

Future Plans for the Servo Control Module:

As first mentioned, I intend to use a Raspberry Pi to control my LEGO Train diaramer I am currently constructing. My intention is to use the cheap 9gram Servos to switch the Track’s Points controlled with a 16-Channel I2C Servo Control Module.

The images below show my chosen method of mounting of the 9g Servos under a 9mm MDF baseboard that the Train Track is fixed too. This mounting choice conceals the Servo, and bypasses the LEGO Switching Mechanism which requires a lot of force to switch state of a set of points. This approach only requires only moving the derailing plate, which relies on a very soft spring. Hence these baby servo motors are almost over-engineered for the job at hand.

Servo Controlled LEGO Train Track Points LegoTrainPoints-02

This method of switch the Points wasn’t initially obvious to me. The light-bulb-moment occur during a TV advert brake while I was unselfconsciously playing with a set of LEGO Track Points.

Also attached to the Raspberry Pi will be a number of Infra-red Train Position sensors, and RFID Readers to determine the position of individual trains, and to flip points to avoid derailments. Each Train Engine will have an unique RFID Number attached to its underside for the RFID Readers to read as the Train passes over.

My intention is for all of this too be controlled via a Web Interface run on the the Raspberry Pi’s own web-server. Well that’s the plan.

Python Library Reference:

The driver consists of the following functions, which you can use to drive the underlying hardware when writing your own application in Python:

setPWMFreq(self, freq)


This function can be used to adjust the PWM frequency, which determines how many full ‘pulses’ per second are generated by the IC. Stated differently, the frequency determines how ‘long’ each pulse is in duration from start to finish, taking into account both the high and low segments of the pulse.

Frequency is important in PWM, since setting the frequency too high with a very small duty cycle can cause problems, since the ‘rise time’ of the signal (the time it takes to go from 0V to VCC) may be longer than the time the signal is active, and the PWM output will appear smoothed out and may not even reach VCC, potentially causing a number of problems.


freq: A number representing the frequency in Hz, between 40 and 1000


The following code will set the PWM frequency to the maximum value of 1000Hz: 



setPWM(self, channel, on, off)


This function sets the start (on) and end (off) of the high segment of the PWM pulse on a specific channel. You specify the ‘tick’ value between 0..4095 when the signal will turn on, and when it will turn of.  Channel indicates which of the 16 PWM outputs should be updated with the new values. 


  • channel: The channel that should be updated with the new values (0..15)
  • on: The tick (between 0..4095) when the signal should transition from low to high
  • off: The tick (between 0..4095) when the signal should transition from high to low


The following example will cause channel 15 to start low, go high around 25% into the pulse (tick 1024 out of 4096), transition back to low 75% into the pulse (tick 3072), and remain low for the last 25% of the pulse: 

pwm.setPWM(15, 1024, 3072)

If you need to calculate pulse-width in microseconds, you can do that by first figuring out how long each cycle is. That would be 1/freq where freq is the PWM frequency you set above. For 1000 Hz, that would be 1 millisecond. Then divide by 4096 to get the time per tick, eg 1 millisecond / 4096 = ~0.25 microseconds. If you want a pulse that is 10 microseconds long, divide the time by time-per-tick (10us / 0.25 us = 40) then turn on at tick 0 and turn off at tick 40.


Adding an optional Filter Capacitor to the Servo Driver Modeule:

We have a spot on the PCB for soldering in an electrolytic capacitor. Based on your usage, you may or may not need a capacitor. If you are driving a lot of servos from a power supply that dips a lot when the servos move, n * 100uF where n is the number of servos is a good place to start – eg 470uF or more for 5 servos. Since its so dependent on servo current draw, the torque on each motor, and what power supply, there is no “one magic capacitor value” we can suggest which is why we don’t include a capacitor in the kit.

Previous Post

New A+ Model Raspberry Pi and Touch Screen LCD Announced...

It’s time to get excited all you Raspberry Pi enthusiasts as pretty soon, you’ll be able to pick-up an official touch screen to connect to your Raspberry Pi. Plus, a ... Read more

Next Post
Pridopia Pi-9685-23017

Raspberry Pi 'Plate' or Add-on with 16 Ch. Servo & 16 Ch. GPIO

Over 12 months ago I came across a "I2C: 16 Channel, 12 bit PMW Servo & I2C 23017, 16 GPIO" add-on board for the Raspberry Pi made by a U.K. ... Read more

Short URL:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Do NOT follow this link or you will be banned from the site!