Raspberry PI Tutorial #8: mehrere Servomotoren mit dem Modul PCA9685 steuern

Im Beitrag Raspberry PI Tutorial #7: Servomotor steuern habe ich beschrieben wie man einen Servomotor am Raspberry PI steuern kann. In diesem Beitrag möchte ich nun zeigen wie man mehrere Servomotoren mit dem Modul PCA9685 steuern kann.

PCA9685 16 Kanal Servo Driver Shield
PCA9685 16 Kanal Servo Driver Shield

An diesem Modul kann man bis zu 16 PWM steuerbare Geräte anschließen (RGB / LED Stripes, Servomotoren usw. ). Der Vorteil ist das man mehrere solcher Module hintereinander Schalten kann (nennt man auch Kaskadieren). Wenn man mehrere Module vom Typ PCA9685 hintereinander schaltet kann jedes Modul mit einer definierbaren Adresse angesprochen werden.

Das Modul PCA9685 habe ich bereits im Beitrag Weekend Project: 7 Segmentanzeige mit Servomotoren verwendet, jedoch habe ich dort einen Arduino verwendet.

 

benötigte Bauteile

  • einen Raspberry PI,
    • Ladekabel,
    • Netzwerkkabel
    • ggf. HDMI Kabel & Tastatur
  • vier Breadboardkabel, weiblich – weiblich, 20cm,
  • externe Spannungsversorgung mit 5V*

Je nach verwendetem Servomotor muss auf die Stromstärke geachtet werden. Ich verwende ein 5V Netzteil mit 2A Leistung.

Anschluss und Schaltung

Nun möchte ich dir gerne zeigen wie du das Modul an deinen Raspberry PI anschließen kannst. Wie bereits erwähnt verwende ich in diesem (und weitere) Beitrag das Model „Raspberry PI Modell B+“.

Pinbelegung - Raspberry PI Modell B+
Pinbelegung – Raspberry PI Modell B+

Wenn du ein anderes Model verwendest musst du ggf. auf eine andere Pinbelegung achten. 

Anschluss

Das Modul PCA9685 verfügt über 6 Pins welche wie folgt an den Raspberry PI angeschlossen werden.

 PCA9685   Raspberry PI 
GND GND (Pin6)
OE  
SCL GPIO 3 / SCL 
SDA GPIO 2 / SDA
VCC 3,3V (Pin 1)
V+  

Die beiden Pins OE & V+ werden in diesem Aufbau nicht verwendet.

Wenn du mehr als die möglichen 16 Geräte anschließen möchtest so kannst du ein weiteres Modul, kaskadierend anschließen.
Dazu nutzt du den Pins auf der gegenüberliegenden Seite.

Schaltung

In der nachfolgenden Schaltung möchte ich zeigen wie man das Modul PCA9685 am Raspberry PI anschließt. Für den Aufbau habe ich ein Power Supply Modul für ein Breadboard und einer 9V Block Batterie  als Stromversorgung genutzt.

Raspberry PI mit PCA9685 Modul und 2 Servomotoren
Raspberry PI mit PCA9685 Modul und 2 Servomotoren

Der Vorteil des Modules PCA9685 ist das die Servomotoren direkt angeschlossen werden können da der Stecker quasi passend vorkonfektioniert ist.

Raspberry PI Modell B+ mit Adafruit PCA9685 Modul und 3 Servomotoren vom Typ SG90
Raspberry PI Modell B+ mit Adafruit PCA9685 Modul und 3 Servomotoren vom Typ SG90

Installieren der Bibliotheken und Pakete

Bevor wir die benötigten Bibliotheken installieren können müssen bzw. sollten wir einmal ein Update durchführen.

sudo apt-get update

Nach diesem Update können wir nun die Pakete für die spätere Verwendung von I2C und der Bibliothek „Adafruit PCA9685“ mit nachfolgendem Befehl installieren.

sudo apt-get install build-essential python-dev python-smbus i2c-tools python-pip – yes

Je nach verwendetem Raspberry PI kann dieses etwas länger dauern. Bei meinem Raspberry PI Modell B+ dauerte dieses ca. 4 min.

aktivieren von I2C

Nachdem die Pakete installiert wurden müssen wir (soweit nicht bereits geschehen) die I2C Funktionalität am Raspberry PI aktivieren. 

Zunächst wird der Befehl

sudo raspi-config

eingegeben und wie in den folgenden Grafiken gezeigt I2C aktiviert. 

In dem „Fenster“ kann mit den Pfeiltasten navigiert werden, ein Menüpunkt wird jeweils mit der Enter Taste bestätigt.

Wenn das Modul PCA9685 bereits am Raspberry PI angeschlossen ist, dann kann geprüft werden ob ein I2C Gerät erkannt wird.

Dazu wird der Befehl 

i2cdetect -y 1

eingegeben. 

In meinem Fall werden werden 2 Geräte erkannt.

prüfen auf angeschlossene I2C Geräte
prüfen auf angeschlossene I2C Geräte

installieren der Adafruit Bibliothek PCA9685

Zum installieren der Bibliothek wird einfach der nachfolgende Befehl auf der Konsole ausgeführt:

sudo pip install Adafruit-PCA9685

Alternativ kann natürlich auch die Bibliothek vom Adafruit GitHub Repository geladen werden. Jedoch muss diese dann etwas umständlicher in den späteren Quellcode importiert werden.

Quellcode

Im GitHub Repository zur Adafruit Bibliothek PCA9685 findet man auch ein gutes und wie ich finde ausführliches Beispiel. Und genau dieses Beispiel möchte ich nutzen um 3 Servomotoren zu steuern.

Das Skript kann entweder per Copy & Paste in den Editor kopiert werden oder per 

wget https://raw.githubusercontent.com/adafruit/Adafruit_Python_PCA9685/master/examples/simpletest.py

in das aktuelle Verzeichnis heruntergeladen werden.

# Simple demo of of the PCA9685 PWM servo/LED controller library.
# This will move channel 0 from min to max position repeatedly.
# Author: Tony DiCola
# License: Public Domain
from __future__ import division
import time
 
# Import the PCA9685 module.
import Adafruit_PCA9685
 
 
# Uncomment to enable debug output.
#import logging
#logging.basicConfig(level=logging.DEBUG)
 
# Initialise the PCA9685 using the default address (0x40).
pwm = Adafruit_PCA9685.PCA9685()
 
# Alternatively specify a different address and/or bus:
#pwm = Adafruit_PCA9685.PCA9685(address=0x41, busnum=2)
 
# Configure min and max servo pulse lengths
servo_min = 150  # Min pulse length out of 4096
servo_max = 600  # Max pulse length out of 4096
 
# Helper function to make setting a servo pulse width simpler.
def set_servo_pulse(channel, pulse):
    pulse_length = 1000000    # 1,000,000 us per second
    pulse_length //= 60       # 60 Hz
    print('{0}us per period'.format(pulse_length))
    pulse_length //= 4096     # 12 bits of resolution
    print('{0}us per bit'.format(pulse_length))
    pulse *= 1000
    pulse //= pulse_length
    pwm.set_pwm(channel, 0, pulse)
 
# Set frequency to 60hz, good for servos.
pwm.set_pwm_freq(60)
 
print('Moving servo on channel 0, press Ctrl-C to quit...')
while True:
    # Move servo on channel O between extremes.
    pwm.set_pwm(0, 0, servo_min)
    time.sleep(1)
    pwm.set_pwm(0, 0, servo_max)
    time.sleep(1)

Zerlegen wir zunächst einmal das Beispiel „Stück für Stück“.

Zunächst müssen wir die für den Code benötigte Bibliotheken importieren.

from __future__ import division
import time
import Adafruit_PCA9685

Wenn man das PCA9685 Modul per Default d.h. ohne das eine Adresse über einen Lötpunkt „eingerichtet“ wurde betreiben möchte dann wird das PWM Objekt wie folgt initialisiert:

pwm = Adafruit_PCA9685.PCA9685()

Sollte jedoch eine andere Adresse gewünscht sein so muss dem Konstruktor diese Adresse übergeben werden.

pwm = Adafruit_PCA9685.PCA9685(address=0x41, busnum=2)

Im Beispielcode wird die PWM Frequenz auf 60Hz gesetzt, in meinem Fall verwende ich jedoch die „MicroServos SG90“ mit 50Hz laut Datenblatt wenn man jedoch den Wert auf 50Hz anpasst so arbeiten die Servos nicht. Daher belasse ich den Wert auf 60.

pwm.set_pwm_freq(60)

Mit dem Befehl „print“ kann man einen Text auf der Konsole ausgeben. In dem Beispielcode wird darauf hingewiesen dass, das Skript per Strg + C abgebrochen werden kann.

print('Moving servo on channel 0, press Ctrl-C to quit...')

Zum Schluss kommt eine Endlosschleife in welcher wir den Servo / die Servos bewegen.

while True:
    # Bewegen des Servos am Port 0, von 0 bis 180 Grad
    pwm.set_pwm(0, 0, servo_min)
    # eine Pause von 1 Sekunde
    time.sleep(1)
    pwm.set_pwm(0, 0, servo_max)
    time.sleep(1)

Um nun alle 3 Servos gleichzeitig zu betreiben muss man nur den Aufruf der Methode „pwm.set_pwm(…)“ kopieren.

In meinem Fall sieht das dann wiefolgt aus:

while True:
    pwm.set_pwm(0, 0, servo_min)
    pwm.set_pwm(7, 0, servo_min)
    pwm.set_pwm(15, 0, servo_min)
    time.sleep(1)
    pwm.set_pwm(0, 0, servo_max)
    pwm.set_pwm(7, 0, servo_max)
    pwm.set_pwm(15, 0, servo_max)
    time.sleep(1)

Wenn man auf der Konsole das laufende Skript mit der Tastenkombination „Strg + C“ abbricht so wird eine zusätzliche Ausgabe getätigt das ein KeyboardInterrupt aufgetreten ist.

Um nun diese zusätzliche Ausgabe zu unterdrücken, können wir das Event mit einem „try except“ Block abfangen:

try:
   while True: 
      pwm.set_pwm(0, 0, servo_min) 
      pwm.set_pwm(7, 0, servo_min) 
      pwm.set_pwm(15, 0, servo_min) 
      time.sleep(1) 
      pwm.set_pwm(0, 0, servo_max) 
      pwm.set_pwm(7, 0, servo_max) 
      pwm.set_pwm(15, 0, servo_max) 
      time.sleep(1)
except KeyboardInterrupt:
   pass

Wenn man nun das Skript abbricht wird keine Fehlermeldung ausgegeben, denn wir fangen diese ab. (Man könnte nun eine zusätzliche Ausgabe mit dem Befehl „print“ tätigen.)

Abbruch eines Python3 Skriptes mit Strg + C auf der Konsole
Abbruch eines Python3 Skriptes mit Strg + C auf der Konsole

Die Methode „set_servo_pulse(channel, pulse)“ kann auskommentiert oder entfernt werden denn diese wird in dem Skript nicht verwendet.

Video

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.