Site icon AranaCorp

Using a PCA9685 module with Raspberry Pi

3.5
(16)

The PCA9685 module is a 16-channel controller that can control 16 PWM outputs via I2C communication. Among other things, it allows you to free up inputs and outputs of your microcontroller and drive up to 16 LEDs or servomotors (or any other module taking a PWM signal as input) using two pins (SCL and SDA) while keeping the pins of your microcontroller for other modules such as sensors. The Raspberry Pi is a microcontroller with integrated Bluetooth and Wifi modules. Very easy to use, it is lightweight and has a higher memory and computing capacity than the Arduino. We will see in this tutorial how to drive several servomotors with a Raspberry Pi and a PCA9685 module.

Prerequisite : Configuration of the Raspberry Pi in I2C

Hardware

Principle of operation

The module is based on the PCA9685 controller, which allows PWM outputs to be controlled using I2C communication and an integrated clock. The module has 6 bridges to select the address of the board and thus allow up to 62 controllers to be placed on the same bus for a total of 992 servomotors (addresses available 0x40 to 0x7F).
It can drive PWM outputs with adjustable frequency and 12-bit resolution. The module is compatible with 5V and 3.3V microcontrollers.

Schematic

The Raspberry Pi has dedicated pins for I2C communication (GPIO2/GPIO3).
The module is equipped with an I2C bus and a power input. The I2C bus is connected as follows:

Code

Library installation

To use the PCA9685 module we use the following library adafruit_servokit.h. This library is not present by default in the Python installation. To install it, simply open a terminal and enter the following command line.

sudo pip3 install adafruit-circuitpython-servokit

Script Python

PWM widths are usually given in microseconds over a period of 20ms (50Hz) but these values can vary from one servo motor to another and between suppliers. You will need to modify the code values to suit your servomotor. In our case, we use the MG90S servomotor with pulse widths between 500 and 2500µs over 20ms.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#Libraries
import time	#https://docs.python.org/fr/3/library/time.html
from adafruit_servokit import ServoKit	#https://circuitpython.readthedocs.io/projects/servokit/en/latest/

#Constants
nbPCAServo=16 

#Parameters
MIN_IMP  =[500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500]
MAX_IMP  =[2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500]
MIN_ANG  =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
MAX_ANG  =[180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180]

#Objects
pca = ServoKit(channels=16)

# function init 
def init():

	for i in range(nbPCAServo):
		pca.servo[i].set_pulse_width_range(MIN_IMP[i] , MAX_IMP[i])


# function main 
def main():

	pcaScenario();


# function pcaScenario 
def pcaScenario():
	"""Scenario to test servo"""
	for i in range(nbPCAServo):
		for j in range(MIN_ANG[i],MAX_ANG[i],1):
			print("Send angle {} to Servo {}".format(j,i))
			pca.servo[i].angle = j
			time.sleep(0.01)
		for j in range(MAX_ANG[i],MIN_ANG[i],-1):
			print("Send angle {} to Servo {}".format(j,i))
			pca.servo[i].angle = j
			time.sleep(0.01)
		pca.servo[i].angle=None #disable channel
		time.sleep(0.5)




if __name__ == '__main__':
	init()
	main()

Applications

Sources

How useful was this post?

Click on a star to rate it!

Average rating 3.5 / 5. Vote count: 16

No votes so far! Be the first to rate this post.

Exit mobile version