Thanks to Gianluca Filippini from EBV for creating the original tutorial.

A slightly more complete version of this project is also available HERE



These are the step-by-step instructions on how to set up a MaaXBoard to drive multiple servos with an accurate PWM external add-on card. The goal is to be able to control these motors with Python. We will reuse code originally written for RaspberryPi by Adafruit's Tony DiCola. Only few modifications are required to get everything working on the MaaXBoard.




Go through the MaaXBoard headless setup here first.



Components list

Beside the board itself, we will need a few external parts:


PCA9685 servo driver

The external control will use the PCA9685 chip which allows the control up to 16 independent channels (i.e. 16 servo) leveraging a single I2C bus. There are multiple shields with PCA9685 made for Raspberry Pi. We can use the shield from Adafruit, or as an alternative, the shield from WaveShare.


GPIO adaptor (optional)

Since the heatsink on the MaaxBoard is quite high, if you use the shield from WaveShare you may also need an adapter to mount it. We can use a GPIO riser or a right-angle GPIO adapter for raspberry pi. This will allow to mount any external shield “vertically” which is even more convenient in case you have a fan mounted on your MaaxBoard heatsink.


Servo motor
When selecting the type of servo motor for your project, you need to pay attention to the type of motor you are using. There are few standard labels (SG90, MG90S, MG995, MG996R, etc) but the PCA9685 is compatible for most of the variants.



Once you have all the parts, you need to install the servo driver and attach the servos to it.

Image courtesy of Kattni Rembor


NOTE: the shield from Adafruit is different from the one from Waveshare. While the Waveshare version uses an onboard 5V/3A regulator to power the servos (eventually with a battery as a power backup) the Adafruit version gives you the flexibility to use an external power supply to provide 5V to the servos. If you plan to use many servos (max 16) the Adafruit version might be a better choice since you won’t power the servos directly from of the raspberry power supply (5V).




Once you have connected the shield we need to make sure that the hardware is recognized. For this reason we need to install i2ctools package. Connect to your board over SSH and install the package


sudo apt-get install i2c-tools

To allow our user to access i2c-dev hw without using sudo we need to add a custom rule. We first create a custom rule file


sudo touch /etc/udev/rules.d/50-i2c.rules

Then edit the file with nano editor:


sudo nano /etc/udev/rules.d/50-i2c.rules

and make sure the content is the following


SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"

Now we add our user to the “i2c” group and set permissions:


sudo adduser ebv i2c sudo chmod g+rw /dev/i2c-* sudo reboot

Once the board has been rebooted connect to it over ssh and check that the shield has been detected. Run:


sudo i2cdetect -y 1

The output of the i2cdetect (for /dev/i2c-dev-1) should look like this:
Screen Shot 2020-04-30 at 8.48.17 PM.png


Python libraries

To use the device with Python we need to install few libraries.


sudo apt-get install git build-essential python-dev

Adafruit libraries

To control GPIO and PWM with Python we need to download three libraries by Adafruit directly from GitHub. Create a work folder and pull the libraries into it.


cd ~/ mkdir example cd example

git clone

git clone

git clone

Install tree so you can check the directories:


sudo apt-get install tree

Now print the directory tree:


tree -d

The example directory's tree should look like this:
The Adafruit libraries need to be modified to run on the MaaxBoard. Luckily, it's only a minor modification. Create your “test” folder like this:


cd ~/ cd example mkdir test cd test

Create symlinks of the actual Python libraries we are going to use for our simple test Python application:


ln -s ../Adafruit_Python_GPIO/Adafruit_GPIO/ .

ln -s ../Adafruit_Python_PureIO/Adafruit_PureIO/ .

ln -s ../Adafruit_Python_PCA9685/Adafruit_PCA9685/ .

NOTE: we could also compile and install these libraries (system-wide install) but doing this allows us to directly modify the code and use it case-by-case.
Now we need to modify two files of the GPIO library to make sure the MaaXBoard is recognized as a linux system (same as if it was a RaspberryPi).
The two files to be modified are and Platform.Py.
Open using nano:


cd Adafruit_GPIO nano

We need to add one line in the get_default_bus() (around line 40) function by adding the bolded elif statement:
elif plat == Platform.BEAGLEBONE_BLACK:
# Beaglebone Black has multiple I2C buses, default to 1 (P9_19 and P9_20).


return 1

elif plat == Platform.MAAXBOARD:


return 1

For we need to add one more define to select MAAXBOARD. Still in the test/Adafruit_GPIO directory, open in nano:



Add the bolded lines below (around line 24):
# Platform identification constants.
In the def platform_detect() function, add the bold lines:
# Handle Beaglebone Black
# TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading
# the platform.
plat = platform.platform()
if plat.lower().find('armv7l-with-debian') > -1:



elif plat.lower().find('tegra-aarch64-with-ubuntu') > -1:
     return JETSON_NANO
elif plat.lower().find('aarch64-with-debian') > -1:



Final should look something like this:
Screen Shot 2020-05-01 at 12.55.47 PM.png
Python application
Now we are ready to use one of the example provided by Adafruit. Thanks to the portability of Python code, no modifications are needed here. We copy the file into our test directory:


cd example cp Adafruit_Python_PCA9685/examples/ test

Execute the test file.


cd example/test python ./

If everything is working correctly your servo motor will move until you exit the script with CTRL-C.
NOTE: for this example we are controlling channel N.0 so make sure to connect your servo to the numbered header in position zero of your shield.




Now you can control multiple servo motors for your mechanical assembly like pan-tilt-zoom or animatronics or industrial prototypes. Always make sure to control servo type and maximum current rating when you plan to use more than one servo on the external shield, eventually adding a specific power supply dedicated only to the servo shield.