Raspberry Pi: Unterschied zwischen den Versionen
Zeile 817: | Zeile 817: | ||
=== Potentiometer === | === Potentiometer === | ||
[[Datei:Poti über MCP 3002 einlesen.jpg|200px|thumb|left|Poti über MCP 3002 einlesen aus dem [[Links_und_Bücher|Sensorbuch]]]] | |||
Dieser Drehwiderstand besitzt meist 3 Pins, wobei sich Links/Mitte und Mitte/Rechts ergänzend verhalten und Links/Rechts immer den maximalen Widerstand liefern. Ein Beispiel findet sich auch beim [[Arduino#Potentiometer|Arduino]]. Im Gegensatz zu diesem müssen wir beim Raspi einen AD-Wandler einsetzen wie etwa den [[Raspberry_Pi#A.2FD-Wandler_MCP_300x_oder_MCP_320x|MCP 3002]]. Damit dieser angesprochen werden kann, muss [[Raspberry_Pi#SPI|SPI]] freigschaltet sein. | Dieser Drehwiderstand besitzt meist 3 Pins, wobei sich Links/Mitte und Mitte/Rechts ergänzend verhalten und Links/Rechts immer den maximalen Widerstand liefern. Ein Beispiel findet sich auch beim [[Arduino#Potentiometer|Arduino]]. Im Gegensatz zu diesem müssen wir beim Raspi einen AD-Wandler einsetzen wie etwa den [[Raspberry_Pi#A.2FD-Wandler_MCP_300x_oder_MCP_320x|MCP 3002]]. Damit dieser angesprochen werden kann, muss [[Raspberry_Pi#SPI|SPI]] freigschaltet sein. | ||
<div style="clear: both"></div> | |||
# botbook_mcp3002.py - read analog values from mcp3002 | # botbook_mcp3002.py - read analog values from mcp3002 | ||
Zeile 849: | Zeile 853: | ||
Weitere Beispiele für die Anbindung des Wandlers im [http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html Netz]. | Weitere Beispiele für die Anbindung des Wandlers im [http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html Netz]. | ||
=== Schalter === | === Schalter === |
Version vom 2. September 2021, 23:42 Uhr
Einführung
Der RasPi ist ein Mini-Computer, der meist unter Linux betrieben wird. Dies im Gegensatz zu einem Mikrokontroller wie etwa dem Arduino. Er kann in diversen Sprachen programmiert werden, wobei vielfach c oder Python verwendet wird. Er besitzt eine Steckleiste ähnlich dem Userport des Commodore 64. Diese Steckleiste wird GPIO genannt und bedeutet General Purpose Input Output. Dies heisst, dass an die Anschlüsse für eigene Bedürfnisse anpassen kann. Einige der Anschlüsse kann man auch verwenden, um spezifische Protokolle wie UART (seriell), oder SPI zu benutzen.
Auch wenn es Bücher gibt, welche eine Einspeisung direkt über die GPIO-Pins empfehlen (etwa für den Batteriebetrieb), wird dringend davon abgeraten, da es dann keinen Spannungsschutz mehr gibt. Stattdessen sollte immer über den vorgesehenen Micro-USB eingespiesen werden, auch wenn man ein Batterie-Pack verwendet.
Betriebsystem
Es gibt spezifische Betriebsysteme, welche explizit auf die Bedürfnisse des RaspPi zugeschnitten sind wie kleiner Speicherverbrauch und Vorkompilierung der verwendeten Kernelmodule. Entsprechend eine Liste der Distributionen, wobei die Liste länger ist: RasPi Betriebsysteme im Kurzportrait
Betriebssystem | Eigenschaften | Erscheinungsjahr | SD-Karte |
---|---|---|---|
Raspian |
|
2012 | 4GB (8GB wenn GUI) |
Pidora |
|
2014 | 2GB |
Windows 10 IoT Core |
|
2015 | ? |
Ubuntu Core |
|
2014 | ? |
Risc OS |
|
2014? | 2GB |
Arch Linux ARM |
|
2015? | 2GB |
FreeBSD |
|
2015? | ? |
GPIO verwenden
Je nach Revision und Gneration sind die Pins etwas anders. Daher unbedingt schauen, welche Version eingesetzt wird. Die Belegung ist zwar gleich, doch die Pins haben andere Nummern, so dass man dann evtl. den "falschen" Pin anspricht. Entsprechend hier die Revision B der neueren Boards.
Pinnummer | Funktion | - | Funktion | Pinnummer |
---|---|---|---|---|
- | 3.3V | o o | 5V | - |
2 | SDA | o o | 5V | - |
3 | SCL | o o | GND | - |
4 | I/O | o o | TX | 14 |
- | GND | o o | RX | 15 |
17 | I/O | o o | I/O | 18 |
27 | I/O | o o | GND | - |
22 | I/O | o o | I/O | 23 |
- | 3.3V | o o | I/O | 24 |
10 | MOSI | o o | GND | - |
9 | MISO | o o | I/O | 25 |
11 | SCKL | o o | I/O | 8 |
- | 3.3V | o o | I/O | 7 |
Bedeutung der Bezeichnungen
- 3.3V -> stellt 3.3V mit max. 50mA zur Verfügung
- 5V -> stellt 5V mit max. 250mA zur Verfügung -> Darf nie an einen GPIO-Pin gelangen, da dieser sonst sofort zerstört wird!
- GND -> Ground-Pins
- I/O -> Reine Input/Output-Pins, welche nicht für andere Zwecke vorbelegt sind. Im Gegensatz zum Arduino sind keine analogen Ein-/Ausgänge vorhanden. Sollten nicht mehr als 3mA-Strom ziehen. Es geht zwar mehr (max. 16 mA), doch auf Kosten der Lebensdauer des Chips.
- TX -> Send (transmit) der seriellen Schnittstelle (UART)
- RX -> Empfang (receive) der seriellen Schnittstelle (UART)
- SDA -> Daten? der IC-Schnittstelle
- SCL -> Clock der IC-Schnittstelle
- MOSI -> Master Out der SPI-Schnittstelle (Daten vom Server zu den Slaves) (Die Kabel werden nicht gekreuzt)
- MISO ->Master In der SPI-Schnittstelle (Daten von den Slaves zum Server) (Die Kabel werden nicht gekreuzt)
- SCKL -> Clock der SPI-Schnittstelle
Bei [Doktor Monk] gibt es eine Schablone zum Ausdrucken der Pinbelegung, damit man diese direkt auf dem RasPi sieht. Möchte man aber nicht immer Kabel manuell stecken, gibt es eine Adapterplatte mit Flachbandkabel; den Pi-Cobbler, den es in diversen Elektronik-Geschäften gibt. Etwas vergleichen, sonst kauft man ihn überteuert.
Spanungen wandeln (5V -> 3.3V)
Wenn man den RasPi mit anderen Geräten koppelt, kann es sein, dass diese mit 5V arbeiten. In diesem Fall muss die Spannung heruntergesetzt werden, damit der RasPi nicht beschädigt wird. Dies geschieht entweder mit einem Spannungsteiler oder mit einem Pegelwandler-Modul. Verwendet man Widerstände, so sollten diese im Verhältnis 1:2 sein, damit die Spannung den geforderten 3.3V entspricht. Dies erreicht man etwa mit einem 270 und einem 470 Widerstand. Da dies aber verhältnismässig viel Strom braucht, wäre es idealer, höhere Werte wie 2.7k und 4.7k zu verwenden. Falls es von der Signalstabilität her reicht, ginge entsprechend auch ein 27k und ein 47k Widerstand.
Ein Wandlermodul hingegen ist intern schon auf die gewünschten Potentiale aufgebaut und muss nur noch mit den gewünschten Spannungen angeschlossen werden. Die Wandler gibt es etwa mit 4 oder 8 Kanälen. Kostengünstiger ist es natürlich, wenn man nur wenige Potentiale wandeln muss, dies über Widerstände zu lösen, doch bei einer grösseren Menge lohnt sich der Einsatz von BOB-11978, BOB-12009 oder Adafruit 395.
GPIO ohne Root-Rechte nutzen
Für den Zugriff auf die GPIO braucht man normalerweise Root-Rechte. Während manche empfehlen, einfach das entsprechende Skript/Programm unter Sudo auszuführen, kann man mit nachfolgender Rule die I/O auch für normale Benutzer verfügbar machen und so auf Root zu verzichten.
Die Datei wird im Verzeichnis /etc/udev/rules.d
abgelegt. Die Zahl im Dateinamen kann angepasst werden. Es soll nur sichergestellt werden, dass es eine eindeutige Zahl ist.
# /etc/udev/rules.d/88-gpio-without-root.rules - GPIO without root on Raspberry Pi # <1> # Copyright http://BotBook.com # # Gruppe dialout mit Besitzer root setzen. SUBSYSTEM=="gpio", RUN+="/bin/chown -R root.dialout /sys/class/gpio/" SUBSYSTEM=="gpio", RUN+="/bin/chown -R root.dialout /sys/devices/virtual/gpio/" # # Sticky-Bit, damit neue Dateien auch dieser Gruppe angehören. SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/class/gpio/" SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/devices/virtual/gpio/" # # Lese- und Schreibberechtigung setzen SUBSYSTEM=="gpio", RUN+="/bin/chmod -R ug+rw /sys/class/gpio/" SUBSYSTEM=="gpio", RUN+="/bin/chmod -R ug+rw /sys/devices/virtual/gpio/"
Die Datei kann mit sudoedit Dateiname
bearbeitet werden. Die Datei wird mit Ctrl-x -> y -> Enter
gespeichert und geschlossen. Um die Regeln zu übernehmen wird entweder der Raspi neu gestartet oder man liest die Regeln neu ein:
sudo service udev restart sudo udevadm trigger -subsystem-match=pgio
GPIO-Zugriff von der Konsole
Um etwa den Tasterzustand von GPIO3 zu lesen, wird folgendermassen vorgegangen:
$ echo 3|tee /sys/class/gpio/export # Datei gpio3 erzeugen $ echo in|tee /sys/class/gpio/gpio3/direction # Den Pin als Input setzen $ cat /sys/class/gpio/gpio3/value # Tasterzustand zurücklesen
Da der interne Pull-Up-Widerstand aktiv ist, liefert offen eine 1, während geschlossen eine 0 liefert.
Module freischalten
Damit das entsprechende Modul vom Kernel geladen wird, muss man es folgendermassen einrichten:
- Kontrolle, dass es nicht in der /etc/modprobe.d/raspi-blacklist.conf aktiv ist -> einfach mit einem # am Anfang auskommentieren
- Das Modul in /etc/modules hinzufügen
- Bibliotheken installieren, falls notwendig
- udev-Regeln hinzufügen, für die Verwendung ohne Root
- Den RaspPi neu starten
IC
IC wird für langsame Verbindungen (Standard 100kHz, max 5MHz) verwendet, benötigt aber nur 2 Leitungen. Die Verbindung wird immer vom Master eröffnet und dient daher nur zum Abfragen. Vorteilhaft für Peripheriegeräte, die nicht schnell zu sein brauchen wie Lautstärkeregler, Analog-Digital- oder Digital-Analog-Wandler mit niedriger Abtastrate, Echtzeituhren, kleine, nichtflüchtige Speicher oder bidirektionale Schalter und Multiplexer. Während des Betriebes können Chips zum Bus hinzugefügt oder entfernt werden (Hot-Plugging). Das Protokoll ist aber sehr anfällig auf Übersprechen, Rauschen oder EMV. Entsprechend kann es nur auf kurzen Distanzen eingesetzt werden und wenn man nicht Buchsen und Stecker verwenden muss, die das Signal stören können. Das Protokoll beinhaltet aber ein Kontroll-Bit, mit dem der Slave angeben kann, dass er die Daten verstanden hat.
Das freizuschaltende Modul heisst i2c-bcm2708. Zusätzlich sollte auch i2c-dev geladen werden. Für den Zugriff sollte man auch die i2c-tools
installieren:
$ sudo apt-get install i2c-tools
Damit man IC auch ohne Root-Rechte nutzen kann, sollte man im Verzeichnis /etc/udev/rules.d/
die Datei 99-i2c.rules
anlegen, die nur eine Zeile enthält:
SUBSYSTEM=="i2c-dev", MODE="0666"
Beim Verwenden darauf achten, wie viel Strom die Geräte brauchen und diese sonst extern einspeisen. Hat man ein Gerät verbunden, kann man nun seine Adresse herausfinden. Jedes angeschlossene Gerät braucht eine eindeutige Adresse:
$ sudo i2cdetect -y 1
Bei ganz alten Boards muss der Bus mit 0 anstatt 1 angegeben werden. Das Tool listet die Adressen (hex) entsprechend auf. Will man mehrere Geräte anschliessen, sollte man immer eines nach dem anderen anschliessen und die Adresse dann entsprechend eindeutig gestalten.
SPI
SPI (Serial Peripheral Interface) verwendet (mindestens) 3 (meistens 4 oder mehr) Leitungen und verwendet kein Kontroll-Bit. Das Protokoll ist sehr flexibel. So kann je nach Ausführung die Chipselect-Leitung pro Chip oder gemeinsam geführt werden. Unterschiedliche Taktfrequenzen bis in den MHz-Bereich sind zulässig. Da die Spezifikation für die Taktflanke, die Wortlänge oder die Übertragung (MSB oder LSB zuerst) nicht genau festgelegt sind, gibt es diverse Einstellungsmöglichkeiten. Trotzdem kann es sein, dass manche Kombinationen inkompatibel sind. Man sollte sich daher vor dem Kauf die Spezifiationen und Einstellungsmöglichkeiten der Chips anschauen. Wenn man mit nur 4 Leitungen auskommen möchte, wird Daisy-Chain verwendet, wie es im Artikel So funktioniert SPI erklärt wird. Da dabei die Daten von Slave zu Slave weitergereicht werden, sind bei längeren Ketten Bitlänge*Slave-Position Taktzyklen zur Verarbeitung notwendig. Bei 5 Slaves in einem 8-Bit-System wären dies für den letzten Slave 40 Taktzyklen. Dieses Prinzip der Weiterleitung beherrschen aber nicht alles Slaves. Sonst sind durch die hohe Taktfrequenz auch grössere Ketten möglich; auch für Geräte mit hohem Durchsatz/Abtastfrequenz.
Das freizuschaltende Modul heisst spi-bcm2708. Zusätzlich sollte auch spidev geladen werden.
Für den Zugriff mit Python auf SPI muss man je nachdem noch ein Git-Repository einbinden, auch wenn dies wohl meist unterdessen schon hinzugefügt wurde. Falls nicht, geht dies auf nachfolgende Art:
$ sudo apt-get install git $ sudo apt-get install python-dev $ git clone git://github.com/doceme/py-spidev $ cd py-spidev/ $ sudo python setup.py install
Damit man SPI auch ohne Root-Rechte nutzen kann, sollte man im Verzeichnis /etc/udev/rules.d/
die Datei 99-spi.rules
anlegen, die nur eine Zeile enthält:
SUBSYSTEM=="spidev", MODE="0666"
Nach einem Neustart kann SPI über Python angesprochen werden.
PiFace Digital Interface Board
Das PiFace erweitert den RasPi um zusätzliche Ein- und Ausgänge (8 Outputs, wovon 2 mit Relais, 8 Inputs, wovon 4 mit Taster). Es arbeitet über SPI, welches entsprechend freigeschaltet werden muss.
$ wget http://pi.cs.man.ac.uk/download/install.txt $ bash install.txt $ sudo reboot
Mit dem Treiber wird auch ein Emulator ausgeliefert, mit welchem man nicht nur den Zustand sehen, sondern auch Outputs schalten kann.
Die Programmierung mit Python geschieht etwa folgendermassen zum Ein- und Ausschalten des ersten Outputs:
$ python >>> import piface.pfio as pfio >>> pfio.init() >>> pfio.digital_write(0,1) >>> pfio.digital_write(0,0)
Möchte man den Taster am ersten Eingang abfragen, wird digital_read
verwendet:
$ python >>> import piface.pfio as pfio >>> import time >>> pfio.init() >>> while True: ... print(pfio.digital_read(0)) ... time.sleep(1)
Echtzeituhr (DS1307)
![](/mediawiki/images/thumb/5/5c/RTC-Modul.jpg/200px-RTC-Modul.jpg)
Die Uhr ist dann von Vorteil, wenn man den Raspi nicht am Internet hängen hat, da sonst der Zeitserver jeweils die korrekte Zeit (genauer) liefert.
Es gibt verschiedene Chips und man sollte schauen, dass das gewünschte Modul auch für 3.3V ausgelegt ist. Sonst gibt es auch die Möglichkeit, einen Arduino mit Echtzeitmodul (wenn vorhanden) anzuschliessen und von diesem die Zeit zu übernehmen. Das Modul wird meist über die [[Raspberry_Pi#I.7F.27.22.60UNIQ--postMath-0000000A-QINU.60.22.27.7FC|I2]C] -Schnittstelle angesprochen, welche entsprechend freigeschaltet sein muss.
Wie man sieht, wird hier das Modul an 5V angeschlossen. Damit die Spannung auf den I2C-Pins nicht hochgezogen wird, darf man auf dem Modul keine Pull-Up-Widerstände verwenden.
Nach dem Anschluss und der Freigabe des I2C-Busses wird nun die Adresse des Moduls gesucht und danach der Treiber für den Kernel geladen:
$ sudo i2cdetect -y 1 # Alle i2c-Geräte ausgeben lassen $ ...68... # Ausgabe der Adresse des Moduls $ sudo modprobe rtc-ds1307 # Kernel-Modul versuchen zu laden $ sudo bash $ sudo echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device # Gerät mit der Adresse von oben hinzufügen $ date # Kontrolle der Uhrzeit -> Wird hier die falsche Zeit ausgegeben, muss man die Uhrzeit erst korrekt (übers Internet) setzen $ sudo hwclock -w # Schreibt die aktuelle Uhrzeit ins HW-Modul $ sudo hwclock -r # Auslesen der gespeicherten Zeit zur Kontrolle
Um die Uhr beim Start einzulesen, müssen folgende Schritte durchgeführt werden:
- /etc/modules um das neue Modul erweitern -> Auf der untersten Zeile folgendes hinzufügen: rtc-ds1307
- /etc/rc.local erweitern, um das Modul einzulesen -> Zusatzzeilen vor dem abschliessenden "exit 0":
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device sudo hwclock -s
Gertboard
Das [Gertboard] ist eine Erweiterungsplatine, welche neben gepufferten digitalen I/O unter anderem A/D- (10 Bit) und D/A-Wandler (8, 10 oder 12 Bit) bietet und auch eine Motorsteuerung (Maximum 18V and 2A) enthält. Zusätzlich befindet sich noch eine ATmega328ATmega328 MCU (gleicher Chip wie auf dem Arduino Uno) auf dem Board, mit der man unabhängige Arduino Programme laufen lassen kann. Die gepufferten Eingänge schützen unter anderem die I/O des RasPi. Die Ausgänge können übrigens mit bis zu 50V mit 0.5A betrieben werden.
Für das Gertbourd gibt es Beispielprogramme, die man folgendermassen installiert:
$ wget http://raspi.tv/download/GB_Python.zip $ unzip GB_Python.zip $ cd GB_Python
Die Programme teilen beim Start mit, welche Jumper wie gesteckt werden müssen, damit die notwendigen Bereiche auf dem Board korrekt verbunden sind:
$ sudo python buttons-rg.py
RaspiRobot-Board
Das Board liefert Ausgänge mit denen man entweder einen Schrittmotor oder 2 Gleichstrommotoren antreiben kann. Dazu gibt es zwei Low-Power-Ausgänge und zwei digitale Eingänge. Das Board kann über die Standard-Bibliotheken bedient werden:
$ sudo apt-get install python-rpi.gpio $ sudo apt-get install python-serial $ wget https://github.com/simonmonk/raspirobotboard/archive/master.zip $ unzip master.zip $ cd raspirobotboard-master $ sudo python setup.pi install
Nun ein Beispiel für einen Zugriff auf das Board:
$ sudo python >>> from raspirobotboard import * >>> rr = RaspiRobot() >>> rr.set_led1(1) # Schaltet Led 1 ein >>> rr.set_led1(0) >>> rr.set_oc1(1) >>> rr.set_oc1(0) # Schaltet Ausgang 1 aus >>> print(rr.sw1_closed()) # Liest den Status des Drückers 1 ein.
Die Verwendung der Motoren (forward, reverse, left, right, stop) wird unter anderem auf der Projektseite von [RaspiRobot] beschrieben.
Prototyping-Boards (Humble Pi / Pi Plate / Paddle Board)
Diese Boards sind reine Entwicklungsplatten ohne Elektronik und dienen dazu, Schaltungen zu entwickeln. Sie besitzen einen Stecker für die GPIO und Lötpins, damit man eigene Schaltungen entwerfen kann. Fürs Prototyping kann natürlich auch ein Steckboard verwendet werden.
Humble Pi
- Besitzt Aussparungen für die grossen Stecker des RasPi.
- besondere Bereiche für Spannungsregler und Transistoren
- Hersteller: [Ciseco]
Pi Plate
- keine Aussparungen sondern höhere Sockel
- Bereich für SDM und Schraubklemme
- Schraubklemmen, welche direkt mit den GPIOs verbunden sind -> Alternative ist das Paddle-Board zum Klemmen der Drähte.
Paddle Board
- Wird über ein Flachbandkabel angeschlossen
- Alle GPIO-Verbindungen können einfach mittels Draht eingeführt werden, so dass keine Female-Adapter notwendig sind.
- Mehr Platz als direkt auf dem Board
- Alternative ist das Pi Plate, bei dem auch Litzen verwendet werden können, weil die Anschlüsse geschraubt werden.
Wichtige Bibliotheken
Damit man auf die Hardware zugreifen kann, muss je nach Sprache und Anwendungsfall die entsprechende Bibliothek installiert werden. Die Bibliotheken abstrahieren auch den Zugriff auf die GPIO-Dateien, so dass man nicht mehr die Dateien abfragen muss, sondern direkt die Zustände abfragen kann. Hier ein Beispiel ohne GPIO-Bibliothek:
# led_hello.py - blink external LED to test GPIO pins # (c) BotBook.com - Karvinen, Karvinen, Valtokari import time, os def writeFile(filename, contents): # Funktion zum Schreiben in eine Datei with open(filename, 'w') as f: # Dateihandle erstellen. Mit "with" wird sichergestellt, dass der Dateihandle am Schluss geschlossen wird. f.write(contents) # Inhalt schreiben print("Blinking LED on GPIO 27 once...") if not os.path.isfile("/sys/class/gpio/gpio27/direction"): # Testen ob es eine Datei für den Pin27 gibt. writeFile("/sys/class/gpio/export", "27") # Datei erstellen writeFile("/sys/class/gpio/gpio27/direction", "out") # Pin als Output definieren writeFile("/sys/class/gpio/gpio27/value", "1") # Pin einschalten time.sleep(2) writeFile("/sys/class/gpio/gpio27/value", "0")
Nun das Gleiche mit der GPIO-Bibliothek:
import time, os, RPi.GPIO as GPIO print("Blinking LED on GPIO 27 once...") GPIO.setmode(GPIO.BCM) # Pin im Broadcom-Modus ansprechen GPIO.setup(27, GPIO.OUT) # Pin als Output definieren GPIO.output(27, 1) # Pin einschalten time.sleep(2) GPIO.output(27, 0)
Wie man sieht, ist es nicht nur kürzer, sondern auch aufs Wesentliche konzentriert.
RPi.GPIO
Diese Bibliothek ist bei den meisten Distributionen schon vorinstalliert. Sollte dies nicht der Fall sein, muss diese mit dem Paketmanager installiert werden. Allgemeine Infos zum Umgang mit Linux im Artikel Allgemeine Daten zu Linux, Tipps und Tricks und Systemeinstellungen.
Ist apt
im Einsatz, kann man die Bibliothek folgendermassen installieren:
$ sudo apt-get install python-dev $ sudo apt-get install python-rpi.gpio
WiringPi
WiringPi ist eine Bibliothek, welche unter c / c++ verwendet wird, auf die man mit den entsprechenden Wrappern auch von anderen Sprachen aus zugreifen kann wie etwa über Python. Mit gpio
kann direkt von der Shell aus auf die Pins zugegriffen werden und dies ermöglicht auch den Zugriff aus Shell-Skripten heraus.
Wie man der Entwickler-Webseite entnehmen kann, wird die Bibliothek nicht mehr weiter entwickelt und ist auch nicht für Anfänger gedacht, sondern für Leute, die sich auskennen.
$ sudo apt-get install wiringpi
Test der Installation:
$ gpio -v $ gpio readall
PySerial
Notwendig, um die serielle Schnittstelle mit Python zu verwenden.
$ suto apt-get install python-serial
Nicht vergessen, die serielle Konsole zu deaktivieren.
bottle (Webserver)
Mit Einbindung dieser Bibliothek können GPIOs über einen Webserver abgefragt (dargestellt) und gesetzt werden. Die Installation von bottle wird im Artikel Python -> bottle beschrieben.
from bottle import route, run import RPi.GPIO as GPIO hostIP = '192.168.1.199' # Die IP des Raspi entsprechend anpassen portNr = 80 # Standard-http Port. https verwendet 443. Ohne Portangabe wartet der Webbrowser auf 8080. GPIO.setmode(GPIO.BCM) # BCM Nummerierungsschema verwenden led_pins = [18, 23, 24] # 3 LEDs werden auf den PINs angesteuert led_states = [0, 0, 0] # Status ist ausgeschaltet switch_pin = 25 # 1 Taster auf diesem Pin einlesen GPIO.setup(led_pins[0], GPIO.OUT) # Pin auf Output setzen GPIO.setup(led_pins[1], GPIO.OUT) # Pin auf Output setzen GPIO.setup(led_pins[2], GPIO.OUT) # Pin auf Output setzen GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Pin auf Input setzen und den internen Pull-Up Widerstand aktivieren def switch_status(): # Funktion zum Einlesen des Tasters state = GPIO.input(switch_pin) # Status des Tasters einlesen if state: # Wenn aktiv return 'Nicht gedrückt' # Status zurückliefern. Durch den Pull-Up Widerstand muss man die Logik umkehren. else: # Wenn nicht aktiv return 'Gedrückt' # entsprechend anderen Status liefern. def html_for_led(led): # Funktion zum Setzen der LEDs led = str(led) # Sicherstellen, dass die gewünschte LED als String ausgewertet wird result = " <input type='button' onClick='changed(" + led + ")' value='LED " + led + "'/>" # JavaScript-Routine aufrufen, um den Status-Button zum Schalten der LED zu verwenden return result # Den neuen Status der LED rückmelden. def update_leds(): # Funktion, um den Status der LED effektiv zu setzen for i, value in enumerate(led_states): # LED-Feld einzeln auslesen GPIO.output(led_pins[i], value) # Pins entsprechend ihres Werts setzen @route('/') # Der Aufruf geschieht über localhst und man muss nicht eine Subadresse eingeben (http://localhost/subadresse), um die Webseite sehen zu können. @route('/<led>') # Es werden noch Unterseiten für jede LED erstellt def index(led = "n"): # Index-Seite erstellen. Je nachdem, welche Nummer übergeben wurde, wird diese dann im Skript ausgewertet. Ohne Angabe bekommt die Variable den Wert "n" print(led) # ? if led != "n": # Wurde in der URL die Nummer der LED mitgegeben (localhost/1), so wird diese ausgewertet -> Es gibt keine Prüfung auf zu grosse oder kleine Zahlen led_num = int(led) # sicherstellen, dass die Eingabe ein Int war led_states[led_num] = not led_states[led_num] # Status der gewählten LED invertieren update_leds() # Funktion zum Setzen des Status aufrufen response = "<script>" # JavaScript-Routine dynamisch erstellen response += "function changed(led)" response += "{" response += " window.location.href='/' + led" # Es wird auf die Unterseite verzweigt, deren Button gedrückt wurde und dann wird der Code oben für diese LED ausgeführt response += "}" response += "</script>" response += "<h1>GPIO Control</h1>" # Überschrift h1 generieren response += "<h2>Button=" + switch_status() + "</h2>" # Status des Tasters auslesen und als Überschrift h2 darstellen response += "<h2>LEDs</h2>" # Überschrift h2 response += html_for_led(0) # Einbindung der ersten LED response += html_for_led(1) # Einbindung der zweiten LED response += html_for_led(2) # Einbindung der dritten LED return response # Darstellung der Webseite run(host = hostIP, port = portNr, debug=True, reloader=True) # Starten des Scripts. Der Parameter debug ist optonal und sollte entfernt werden, wenn das Script produktiv ist. # Dies gilt auch für reloader, der dafür sorgt, dass Änderungen an der Quelldatei ohne Neustart des Web-Servers übernommen werden
Das Programm stammt von Simon Monk und kann auf github heruntergeladen werden.
Serielle Schnittstelle
Der RasPi ist normalerweise so konfiguriert, dass er die Ein-/Ausgabe der Konsole parallel auch auf die Pins der seriellen Schnittstelle leitet. Dies ist zwar nützlich bei einer Analyse ohne Monitor, doch störend, wenn man mit einem externen Gerät "ungestört" kommunizieren möchte. Entsprechend muss man diese Weiterleitung in /etc/inittab
auskommentieren.
$ sudo nano /etc/inittab ... #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Speichern mit Ctrl-X gefolgt von Y. Danach den RasPi neu starten. Zum Einschalten muss die Zeile entsprechend wieder entkommentiert werden.
Um die serielle Schnittstelle über Python zu erreichen, wird die entsprechende Bibliothek installiert. Anschliessend kann man noch [minicom] installieren, um die Verbindung zu testen.
$ sudo apt-get install minicom $ minicom -b 9600 -o -D /dev/ttyAMA0
Die Baudrate muss natürlich mit den Angaben der Gegenstelle übereinstimmen. Im minicom kann die Hilfe mit Ctrl-A und danach Z aufgerufen werden. Mit der Taste E wird das lokale Echo eingeschaltet, so dass man die eigenen Eingaben auch sieht.
externe Computerchips (ICs)
Externe Chips können entweder über die obigen Schnittstellen angeschlossen werden oder sie arbeiten unabhängig und brauchen nur direkt angeschlossene Steuerleitungen, um die gewünschten Funktionen auszuführen. Nachfolgend einige ICs, die in Verwendung mit dem RasPi nützlich sind.
Damit man weiss, welche PINs sich wo befinden, haben elle ICs entweder eine Einkerbung auf einer Seite oder einen Punkt über PIN 1. Normalerweise werden die Pins im Gegenuhrzeigersinn nummeriert, doch dies steht im entsprechenden Datenblatt.
Für die Anbindung braucht es meist noch elektronische Bauteile wie Transistoren, Widerstände oder Kondensatoren. Diese Bauteile werden auf der Seite Elektronik beschrieben.
A/D-Wandler MCP 300x oder MCP 320x
Diese Bausteine liefern je nach Serie eine andere Auflösung und entsprechende Eingänge. Die Anbindung geschieht über SPI. Die 300x-Serie liefert eine Auflösung von 10 Bit und die 320x eine von 12 Bit. Die letzte Ziffer bestimmt die Anzahl der möglichen Kanäle von 1 (3x01) bis 8 (3x08). Wie die Anbindung des Chips geschieht und dessen Auswertung läuft, ist im Abschnitt über den Potentiometer sichtbar.
AND-Gates MC14081BCP
Der MC14081BCP enthält vier 2-fach AND-Gates und arbeitet mit 5-15V. Bei 5V werden Werte unter 2.3V als Low und über 2.7 als High ausgewertet.
![](/mediawiki/images/a/ac/Pinbelegung_MC14081B_AND-Gate.png)
GPS-Modul
GPS-Module können fertig gekauft und ausgewertet werden. Der Anschluss an den Raspi geschieht entweder seriell oder über eine andere Schnittstelle. Um die Daten auszuwerten gibt es Dienste, welche auf dem Raspi installiert werden können. Ein Beispiel liefert das Rezept 11.10 im Raspi-Kochbuch.
Darlington-Treiber ULN280x
![](/mediawiki/images/thumb/4/44/ULN280x_Pinbelegung.png/200px-ULN280x_Pinbelegung.png)
Diese Motortreiberbaustein-Reihe unterscheidet sich in der letzten Ziffer, welche die Eingangsspannung und damit den Einsatz beschreibt. 1 = PMOS-CMOS (allgemeiner Einsatz mit Widerstand zur Strombegrenzung), 2 = 14-25V PMOS (10.5k mit Zener-Diode), 3 = 5V TTL/CMOS (mit 2.7k) und 4 = 6-15V CMOS/PMOS (10.5k).
Der Chip enthält neben dem Transistor eine Diode, um die Induktivitäten abzufangen.
Jeder Pin schaltet bis zu 50V und erlaubt 0.5A mit Peaks bis 0.6A. Die Outputs können parallel geschaltet werden, um grössere Ströme zu erlauben.
H-Brücke L293D
![](/mediawiki/images/thumb/5/57/Pinbelegung_L293D.png/200px-Pinbelegung_L293D.png)
Der L293D-Chip kann 2 Motoren gleichzeitig ansteuern. Dabei darf er mit max. 600mA Dauerstrom belastet werden (pro Kanal) und er verträgt Spitzen bis 1A. Bei einer H-Brücke werden die Anschlüsse über Transistoren so geschaltet, dass die Richtung gedreht wird, ohne einen Kurzschluss zu verursachen. Wenn man den Chip betrachtet, so kann man ihn links und rechts teilen. Einzig die Anschlüsse für die Spannungen sind gemeinsam auszuführen. Entsprechend wird nur die "linke" Seite beschrieben.
Die Einspeisung für den Motor (3V-36V) geschieht über Vs (Pin 8). Die Speisung des IC (5-36V) geschieht über Vss (Pin 16). Damit der IC arbeitet, muss man den Enable-Pin (1) setzen. Die Geschwindigkeit kann man ensprechend mit PWM auf diesen Pin steuern. Die Drehrichtung wird über die zwei Input-Pins (2+7) gesteuert. Hierbei muss für Uhrzeigersinn der Input1 (Pin 2) aktiv sein und für Gegenuhrzeigersinn der Input2 (Pin 7). Der Motor selber wird an Output1 und Output2 angeschlossen. Ist die Drehrichtung verkehrt, müssen die Kabel hier getauscht werden.
Damit die Masse stimmt, wird das Minus der Einspeisung und ein GND-Pin des Raspi auf einen der GND des L293D geführt (Pin 4,5,12,13).
Der Chip kann entsprechend für die Richtungsumschaltung bei Gleichstrommotoren oder bei bipolaren Schrittmotoren verwendet werden.
H-Brücken-Motorsteuerungs-Modul
Es gibt von verschiedenen Herstellern Module zum Ansteuern von Motoren. Je nach Modul müssen diese anders verdrahtet werden, doch das Prinzip bleibt gleich. Entsprechend muss man das Beiblatt der Schaltung studieren, auch was die Belastbarkeit des Moduls angeht.
NAND-Gates MC14093B
Der MC14093B enthält vier 2-fach NAND-Gates und arbeitet mit 5-15V. Bei 5V werden Werte unter 1.9V als Low und über 2.9 als High ausgewertet. Die Pinbelegung ist gleich wie beim MC14081B 2-Fach AND-Gate.
Timerbaustein 555
Der CA555E, NE555 oder ähnliche Timer-Bausteine bieten die Möglichkeit, Ausgänge in definierten Zeitabständen zu schalten, eine Weile beibehalten oder nach Vorgabe umzuschalten.
Pin | Name | Bedeutung |
---|---|---|
1 | GND | Masse |
2 | TRIG | Fällt der Pin unter 3V, so wird Pin 3 auf die Eingangsspannung gesetzt. |
3 | OUT | 0V oder VCC. Je nach Zustand des IC. |
4 | RESET | Wenn auf High, wird das Zeitintervall nicht zurückgesetzt. |
5 | CTRL | ? |
6 | THRES | Steigt die Sapnnung am Pin über 2/3 der Eingangsspannung, wird Pin3 auf 0V gesetzt. |
7 | Disc | ? |
8 | VCC | Eingangsspannung (4.5-15V) |
![](/mediawiki/images/thumb/4/41/Blinkschaltung_mit_555.jpg/200px-Blinkschaltung_mit_555.jpg)
Zähler
(4-Bit) MC74HC193N
Der MC74HC193N ist ein setzbarer binärer 4-Bit Auf-/Abwärts-Zähler mit Reset-Möglichkeit. Er ist pinkompatibel mit dem LS193. Wie man der Info entnehmen kann, ist es möglich, den Zähler zu kaskadieren, um grössere Bereiche zu zählen.
![](/mediawiki/images/thumb/5/5e/MC74HC193N_Belegung_und_Diagramm.png/200px-MC74HC193N_Belegung_und_Diagramm.png)
Dekadenzähler MC14017BCP
Dieser Zähler repräsentiert an seinen Ausgängen jeweils die 10er-Zahl. So können entsprechend dezimale Anwendungen angesteuert werden.
![](/mediawiki/images/thumb/4/4c/Verwendung_MC14017BCP.png/200px-Verwendung_MC14017BCP.png)
Sensoren
Ein Sensor liefert Daten. Dies kann entweder digital erfolgen oder analog. Da der Raspi keine analogen Eingänge hat, müssen diese über einen A/D-Wandler eingelesen werden. Wenn die Werte nicht exakt sein müssen, können die Werte auch digital mittels eines Kondensators und der resultierenden Sprungantwort berechnet werden.
Die Pegel an den Pins sollten unter 0.8V für Low und mindestens 1.3V für High haben, um undefinierte Zustände zu vermeiden.
Sprungantwort (analoge Werte an digitalem Pin)
![](/mediawiki/images/thumb/6/6b/Sprungantwort_Aufbau.jpg/200px-Sprungantwort_Aufbau.jpg)
# https://github.com/simonmonk/raspberrypi_cookbook_ed2/blob/master/pot_step.py import RPi.GPIO as GPIO import time, math C = 0.33 # uF R1 = 1000 # Ohms GPIO.setmode(GPIO.BCM) # Pin a charges the capacitor through a fixed 1k resistor and the thermistor in series # pin b discharges the capacitor through a fixed 1k resistor a_pin = 18 b_pin = 23 # empty the capacitor ready to start filling it up def discharge(): GPIO.setup(a_pin, GPIO.IN) GPIO.setup(b_pin, GPIO.OUT) GPIO.output(b_pin, False) time.sleep(0.1) # return the time taken (uS) for the voltage on the capacitor to count as a digital input HIGH # than means around 1.65V def charge_time(): GPIO.setup(b_pin, GPIO.IN) GPIO.setup(a_pin, GPIO.OUT) GPIO.output(a_pin, True) t1 = time.time() while not GPIO.input(b_pin): pass t2 = time.time() return (t2 - t1) * 1000000 # Take an analog reading as the time taken to charge after first discharging the capacitor def analog_read(): discharge() t = charge_time() discharge() return t # Convert the time taken to charge the cpacitor into a value of resistance # To reduce errors, do it 100 times and take the average. def read_resistance(): n = 10 total = 0; for i in range(1, n): total = total + analog_read() t = total / float(n) T = t * 0.632 * 3.3 r = (T / C) - R1 return r try: while True: print(read_resistance()) time.sleep(0.5) finally: GPIO.cleanup()
Beschleunigung
Bewegung
Mit einem PIR (Passive Infrarot) Bewegungsmelder kann man erkennen, falls eine Bewegung im Umfeld des Sensors stattgefunden hat. Je nach Sensor kann man mit einem Potentiometer die Empfindlichkeit des Sensors einstellen, wenn man etwa ein Aquarium mit Fischen hat und nicht möchte, dass der Sensor deswegen auslöst. Es gibt auch Sensoren, bei denen man einstellen kann, wie lange das Ausgangssignal aktiv bleiben soll, wenn der Sensor ausgelöst hat.
Es gibt verschiedene Sensoren auf dem Markt. Entsprechend muss man schauen, ob diese eine Einspeisung von 3.3V/5V oder eine andere Einspeisung brauchen. Zusätzlich ist auch wichtig, welche Ausgangsspannung sie generieren. Ist diese höher als 3.3V, so muss man entsprechend einen Spannungsteiler einsetzen, um den Pin zu schützen.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) while True: input_state = GPIO.input(18) if input_state == False: print('Bewegung entdeckt') time.sleep(0.5)
CO2
Drehung/Drehgeber
Um eine Drehung zu erfassen, gibt es mehrere Möglichkeiten. In diesem Abschnitt soll der Drehgeber betrachtet werden, welcher über ein Schaltmuster aufzeigt, in welche Richtung (und wie viel) er gedreht wird. Meist wird ein Quadratur-Verfahren verwendet mit zwei unterschiedlichen Spulen, so dass sich das Bewegungsmuster nach 4 Schritten wiederholt. Schlussendlich ergibt sich ein fixes 2-Bit-Muster mit definierten Übergängen, wodurch man erkennt, ob nach links oder rechts gedreht wurde. Damit keine Sprünge entstehen, muss man schneller einlesen, als der Drehgeber die übernächste Position erreicht hat. Im "schlimmsten" Fall detektiert man sonst einen Schritt nach links, obwohl man drei Schritte nach rechts (oder umgekehrt) gedreht hat. Zusätzlich sollte man aber auch beim Einlesen eine kurze Pause einlegen (von 1ms), damit bei Übergängen kein "Prellen" entsteht.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) input_A = 18 input_B = 23 GPIO.setup(input_A, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(input_B, GPIO.IN, pull_up_down=GPIO.PUD_UP) old_a = True old_b = True x = 0 def get_encoder_turn(): # return -1, 0, or +1 global old_a, old_b # globale Variablen müssen in der Funktion gekennzeichnet werden, wenn man sie nicht nur lesen, sondern beschreiben will result = 0 new_a = GPIO.input(input_A) new_b = GPIO.input(input_B) if new_a != old_a or new_b != old_b : # Logik für die Auswertung, ob vorwärts oder rückwärts gedreht wurde if old_a == 0 and new_a == 1 : result = (old_b * 2 - 1) elif old_b == 0 and new_b == 1 : result = -(old_a * 2 - 1) old_a = new_a old_b = new_b time.sleep(0.001) # Verhindert "prellen" return result while True: change = get_encoder_turn() if change != 0 : # Bei 0 wurde nichts geändert, daher nur zählen, wenn gedreht wurde x = x + change print(x)
Druck (Kraft)
Hier kann etwa der FlexiForce eingesetzt werden, welcher auf Druck reagiert. Auch wenn dieser WIderstand 3 Anschlüsse hat, muss man ihn je nachdem mit einem Spannungsteiler anschliessen. Weil der mittlere Anschluss je nachdem nicht belegt ist. Dies erfährt man im Datenblatt. Wie man den Spannungsteiler aufbaut, steht im Abschnitt Helligkeit und ein Programm zum Einlesen kann man beim Arduino nachschauen.
Entfernung
mit Infrarot
Hier gibt es zwei Varianten siehe beim Arduino. Die digitale schaltet, wenn etwas in den Bereich des Sensors kommt, während die analoge einen Wert für den Abstand liefert. Hier der Code für einen "Schalter".
import RPi.GPIO as GPIO import time def my_callback(channel): # selbst definierte Interrupt-Routine print('Gegenstand in der Nähe des Sensors!') GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.IN, pull_up_down = GPIO.PUD_UP) GPIO.add_event_detect(18, GPIO.FALLING, callback = my_callback, bouncetime = 100) # Aufruf der Interruptroutine "my_callback", sobald am Pin 18 die Flanke abfällt. # Um Prellen zu vermeiden, wird 100ms gewartet while True: i = i + 1 print(i) time.sleep(1) # Dank dem Interrupt wird die Flanke auch "im Schlafen" detektiert.
![](/mediawiki/images/thumb/4/47/Infrarot-Sensor.jpg/200px-Infrarot-Sensor.jpg)
Um die Signale sauber zu verarbeiten, wird hier mit einem Interrupt gearbeitet. Auf dem Bild aus dem Sensorbuch sieht man den Anschluss eines 5V-Sensors, der mittels eines Spannungsteilers angeschlossen wird. Da keine grossen Ströme fliessen sollen und der Raspi alles höher als 1.3V als HIGH erkennt, kann man 2 gleiche Widerstände verwenden, was die Spannung auf 2.5V halbiert. Damit die Verlustleistung nicht zu gross wird, kann man 1k oder 2.2k Widerstände der E-Reihe verwenden.
mit Schall
Hier kann etwa der Parallax PING (kostet 30$) oder der HC-SR04 eingesetzt werden, welcher wesentlich preisgünstiger ist. Je nach Sensor ist die Erkennung erschwert, wenn die Fläche abgewinkelt ist oder sehr weich/porös, so dass die Schallwellen verschluckt werden.
Mögliche Anwendungen sind neben den Abstandserkennungen auch Füllstandssensoren, wenn der Sensor die Flüssigkeit detektiert.
Mögliche Anwendungen für den Arduino finden sich auf der verlinkten Seite zum HC-SR04. Diese Sensoren senden kein analoges Signal mit der Entfernung, sondern man sendet einen Impuls, indem man die entsprechende Flanke auf den Trigger-Pin sendet und nachher schaut, wann das Modul den Echo-Pin aktiviert. Die entsprechend vergangene Zeit kann man dann für die Entfernungsberechnung verwenden. Beim Berechnen kann man entweder fixe Werte verwenden, oder man macht diese abhängig von der Höhe, der Temperatur und der Luftfeuchtigkeit, da diese die Schallgeschwindigkeit beeinflussen. Da die Werte für praktische Aufgaben und die Genauigkeit der Sensoren nicht relevant sind, kann man auch einfach eine entsprechende Konstante verwenden wie z.B. 58s pro cm für den HC-SR04.
Beim Arduino ist noch ein einfaches Beispiel aufgeführt, damit man sieht, wie die Werte berechnet werden.
GPS
Helligkeit (Licht)
![](/mediawiki/images/thumb/a/a9/Spannungsteiler_mit_Fotowiderstand.jpg/200px-Spannungsteiler_mit_Fotowiderstand.jpg)
Hier kann ein Fotowiderstand verwendet werden. Bei den meisten verringert sich der Widerstand mit zunehmender Lichtmenge. Da der Widerstand analog arbeitet, wird er über einen A/D-Wandler angeschlossen. Beim Arduino findet sich dazu ein Beispielcode. Man muss einfach statt einem Poti einen Spannungsteiler (etwa 10k bis 1M) mit dem Fotowiderstand bauen. Der Widerstand muss sich am Sensor orientieren, so dass der Teiler den ganzen Spektrumsbereich liefert. Beim Raspi ist es das gleiche und wird im Abschnitt vom Potentiometer gezeigt.
Möchte man auf den IC verzichten, so kann man die Bereiche (hell / dunkel) auch mit einem RC-Glied und der entsprechenden Sprungantwort auswerten.
Gas (CO2, Methan usw.)
Es gibt Sensoren, welche das Vorhandensein von entsprechenden Gasen (oder ähnlichen) detektieren können. Hierbei wird mit einem Heizelement und einem Katalysator der Widerstand an Hand des gewünschten Gases verändert. Sparkfun führt mehrere Gas-Sensoren. Die Sensoren können entsprechend je nach notwendiger Genauigkeit über ein A/D-Modul oder ein RC-Glied ausgewertet werden.
Kamera
Magnetismus (Hall-Sensor)
Dieser Sensor erkennt, wenn ein Magnet in seine Nähe kommt. Er schaltet dann den Ausgang um. Somit hat man einen digitalen Schalter, der etwa für eine Geschwindigkeitsmessung eingesetzt werden kann (Umdrehungen/Minute) oder als Einbruchsalarm (Fenster öffnet sich).
Bauteilbezeichnung: NJK-5002 A oder C. Der Unterschied besteht darin, dass schwarz bei A auf Plus und beim C auf Minus schaltet, wenn ein Magnet in die Nähe kommt. Sonst gibt es noch den braunen Anschluss für Plus und blau für Minus. Dieser Sensor besitzt eine eingebaute LED, welche dessen Funktion anzeigt.
Matrix-Tastatur (Pinpad/Code-Tastatur)
Diese Tastatur verfügen meist über ein 4x3 Eingabefeld für Zahlen und zwei Sonderzeichen, wobei dies nur eine mögliche Beschriftungsart darstellt da die Auswertung dem Programm überlassen wird, welches lediglich feststellt, welche Taste(n) gedrückt wurde(n). Da für die Erkennung der Spalte und Reihe die Pins korrekt angeschlossen sein müssen, damit man keinen Kurzschluss fabriziert, sollte man das Datenblatt genau lesen. Für die 4 Reihen und 3 Spalten braucht man gesamthaft 7 Pins. Hat die Tastatur einen IC oder ähnlichen Anschluss, sollte man natürlich diesen verwenden, um Pins zu sparen.
Im nachfolgenden Programm werden die Pins auf Grund der Verdrahtung des SparkFun-Zehnerblocks eingesetzt, doch wie erwähnt, muss man die Pins zwingend aus dem Datenblatt herausfinden. Um keinen Tastendruck zu verpassen, empfiehlt es sich, diese mittels Interrupt einzulesen.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rows = [17, 25, 24, 23] # Pins für die Reihen cols = [27, 18, 22] # Pins für die Spalten keys = [['1', '2', '3'], # Array für die einzulesenden Tasten ['4', '5', '6'], ['7', '8', '9'], ['*', '0', '#']] for row_pin in rows: # Die Reihen werden als Input definiert GPIO.setup(row_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) for col_pin in cols: # Die Spalten werden als Output definiert. GPIO.setup(col_pin, GPIO.OUT) def get_key(): key = 0 for col_num, col_pin in enumerate(cols): # Schlaufe durch die Spalten GPIO.output(col_pin, 1) # Spalte aktivieren for row_num, row_pin in enumerate(rows): # Schlaufe durch die Reihen if GPIO.input(row_pin): # Kontrolle, ob "Durchgang" key = keys[row_num][col_num] # Zeichen(Position) aus Array auslesen und speichern. GPIO.output(col_pin, 0) # Spalte deaktivieren return key while True: key = get_key() # Tastatur abfragen und Rückgabewert speichern. if key : # Wenn key = 0, dann false und somit keine Auswertung. print(key) # Zeichen ausgeben. Der Stringwert '0' ist etwas anderes als die Zahl 0. time.sleep(0.3) # Programm verlangsamen -> Mit Interrupt verpasst man keine Tasten und kann trotzdem länger schlafen
(USB)-Maus
Mit der pygame
-Bibliothek können auch Maus-Bewegungen und Klicks (MOUSEBUTTONDOWN/MOUSEBUTTONUP) ausgewertet werden. Dies allerdings nur auf der grafischen Oberfläche:
# https://github.com/simonmonk/raspberrypi_cookbook_ed2/blob/master/mouse_pygame.py import pygame import sys from pygame.locals import * pygame.init() screen = pygame.display.set_mode((640, 480)) pygame.mouse.set_visible(0) while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() if event.type == MOUSEMOTION: print("Mouse: (%d, %d)" % event.pos)
Die Referenzseite der Bibliothek ist pygame doc
Neigung
Potentiometer
![](/mediawiki/images/thumb/5/56/Poti_%C3%BCber_MCP_3002_einlesen.jpg/200px-Poti_%C3%BCber_MCP_3002_einlesen.jpg)
Dieser Drehwiderstand besitzt meist 3 Pins, wobei sich Links/Mitte und Mitte/Rechts ergänzend verhalten und Links/Rechts immer den maximalen Widerstand liefern. Ein Beispiel findet sich auch beim Arduino. Im Gegensatz zu diesem müssen wir beim Raspi einen AD-Wandler einsetzen wie etwa den MCP 3002. Damit dieser angesprochen werden kann, muss SPI freigschaltet sein.
# botbook_mcp3002.py - read analog values from mcp3002 # (c) BotBook.com - Karvinen, Karvinen, Valtokari import spidev import time def readAnalog(device = 0, channel = 0): # Funktion, um Daten über SPI vom MCP 3002 auszulesen. Der channel ist der gewünschte Kanal. Der 3002 hat zwei Kanäle. assert device in (1, 0) # Test, dass das device 0 oder 1 ist -> sonst Abbruch assert channel in (1, 0) # Test auf den Kanal. Bei mehr Kanälen z.B. MCP 3008 müsste man erweitern spi = spidev.SpiDev() # spi-Objekt generieren spi.open(0, device) # spi-Verbindung öffnen command = [1, (2 + channel) << 6, 0] # Es wird ein 3 * 8Bit Array gesendet. Im ersten Array kommt das Startbit (letzte Stelle). Im zweiten folgen die Modi für den Austausch. # Das erste Bit sagt, ob das Signal selber (1) oder die Differenz (0) gesendet werden soll. Das zweite Bit ist abhängig vom ausgelesen Kanal. # Danach könnte man noch sagen ob MSB oder LSB aktiv sein soll. Dies bleibt aber 0. Entsprechend # ergeben sich nach dem Shift um 6 Stellen und dem letzten Byte 0 -> 0000 0001 1x00 0000 0000 0000 (das x ist 0 oder 1 je nach Kanal). reply = spi.xfer2(command) # Es wird ein 3 * 8Bit Array zurückgeliefert. value = reply[1] & 31 # Das erste Paket (reply[0]) wird nicht verwendet. Beim zweiten Paket werden nur die hinteren 5 Bit verwendet (31 = 0000 0001 1111). value = value << 6 # Nun werden die Bits um 6 Positionen nach vorne geschoben, damit diese nicht vom Inhalt # des dritten Paketes überschrieben werden (0000 000D DDDD << 6 = 0DDD DD00 0000). value = value + (reply[2] >> 2) # Vom letzten Paket braucht es nur die höheren 6 Bits. Da die letzten 2 Bits nicht relevant sind (Der MCP 3002 liefert nur 10 Bits Auflösung), # schiebt man daher die Bits nach rechts (DDDD DDXX >> 2 = 00DD DDDD) und fügt diese dann an (0DDD DD00 0000 + 0000 00DD DDDD = 0DDD DDDD DDDD). spi.close() # spi-Verbindung schliessen return value while(True): print(readAnalog(0, 0) time.sleep(0.5)
Weitere Beispiele für die Anbindung des Wandlers im Netz.
Schalter
Der Schalter behält im Gegensatz zum Taster seine Position. Je nach Ausführung gibt es Schalter mit 2 oder mit mehr Positionen. Manche Schalter haben auch eine "Tasterposition", welche man zwar anwählen kann, die dann aber wieder "zurückspringt", so dass diese Position nicht dauerhaft beibehalten wird.
Je nach Einsatz besitzen Schalter statt 2 3 Pins, wodurch eine Umschaltung erreicht wird, wenn etwa mehrere Schalter in Reihe einen Gesamtzustand schalten sollen (Licht im Treppenhaus mit mehreren Schaltern).
Je nach Ausführung kann der Schalter eine gewisse Spannung und Leistung schalten, die man aus dem Datenblatt entnimmt. Die Überwachung eines Schalters geschieht programmtechnisch gleich wie beim Taster.
(USB)-Tastatur
Um Tastendrücke einzulesen gibt es die Systemfunktion sys.stdin.read()
oder die grafische Bibliothek pygame
.
import sys, tty, termios def read_ch(): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch while True: ch = read_ch() if ch == 'x': break print("Taste: " + ch)
Die grafische Ausgabe mit pygame. In diesem Programm werden nur ASCII-Zeichen ausgegeben. Steuerzeichen werden entsprechend nicht ausgegeben.
import pygame import sys from pygame.locals import * pygame.init() screen = pygame.display.set_mode((640, 480)) pygame.mouse.set_visible(0) while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() if event.type == KEYDOWN: print("Code: " + str(event.key) + " Zeichen: " + chr(event.key))
Taster
Im Gegensatz zum Schalter verbleibt der Taster nicht in seiner geschalteten Position, sondern kehrt selbständig wieder in seine Ruheposition zurück. Normalerweise besitzt ein Taster nur 2 Postionen, wobei auch hier mehrere Positionen möglich sind.
Damit der Raspi sauber entscheiden kann, ob der Taster gedrückt ist oder nicht, braucht es einen Widerstand, welcher das Signal bei einer ungedrückten Taste entweder nach +5V oder GND zieht. Dafür besitzt der Raspi interne Pull-Widerstände, welche man bei der Pin-Definition mitgeben kann. So braucht es keinen externen Widerstand, um das Signal sauber zu halten. Je nach Leitungslänge ist ein solcher trotzdem notwendig, da die internen Widerstände relativ hoch sind (etwa 40k dies ergibt einen Strom von nur 82A). Falls es aber mehr Strom braucht, so kann man einfach einen externen Widerstand verwenden. Bei einem 100 Widerstand fliessen 33mA, was noch innerhalb der erlaubten 50mA pro Pin liegt, doch sollte man nach Möglichkeit den Verluststrom so tief als möglich halten.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Den Widerstand als "Pull up" definieren. Dies, damit möglichst kleine Verlustströme auftreten. while True: input_state = GPIO.input(18) if input_state == False: # "Pull up" zieht im nicht gedrückten Zustand nach High, so dass gedrückt == False bedeutet. print('Button Pressed') time.sleep(0.2) # In einem richtigen Programm sollte zur Überwachung statt einer "Schlafroutine" ein Interrupt verwendet werden.
Temperatur
Für die Temperaturmessung gibt es den LM35 im Transistorgehäuse, der sich direkt als analoger Sensor anschliessen lässt und nicht einmal einen Pull-Up Widerstand braucht. Der gelesene Wert kann direkt mittels gelesene Spannung * 100°C/V umgerechnet werden.
Wenn man ihn von vorne anschaut (flache Seite), so befinden sich links die Referenzspannung (5V (4-30V)) und rechts GND, während die Mitte an den analogen Anschluss geführt wird. Da der LM35 macx. 155°C messen kann und dabei 1.5V abgibt, ist dessen Verwendung problemlos. Es gibt auch Sensoren, welche direkt für 3.3V ausgelegt sind, wie den TMP36. Ein Programm zum Verarbeiten der Werte gibt es beim Arduino. Für den Raspi nur die folgenden Zeilen zum umrechnen der Werte in eine Temperatur.
percent = data / 1023.0 volts = percent * 3.3 celsius = 100.0 * volts
Aktoren
Lautsprecher / Piezo-Summer
Kleine Summer können direkt an einen Pin angeschlossen werden. Wenn man nicht sicher ist, ob nicht doch zu viel Strom fliesst, kann wie bei einer LED ein 470 Widerstand angeschlossen werden.
import RPi.GPIO as GPIO import time buzzer_pin = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(buzzer_pin, GPIO.OUT) dev buzz(pitch, duration): # pitch = Tonhöhe, duration = Tonlänge period = 1.0 / pitch delay = period / 2 cycles = int(duration * pitch) for i in range(cycles): GPIO.output(buzzer_pin, True) time.sleep(delay) GPIO.output(buzzer_pin, False) time.sleep(delay) while True: pitch_s = input("Tonhöhe eingeben (200 bis 2000 Hz): ") pitch = float(pitch_s) duration_s = input("Tonlänge eingeben (in Sekunden): ") duration = float(duration_s) buzz(pitch, duration)
Diese Summer haben keine gute Tonqualität und auch die Tonhöhe ist nur relativ. Das Programm dient daher nur zu Demonstationszwecken und kann keinen Lautsprecher ersetzen. Es stammt von Simon Monk und kann auf [github heruntergeladen werden.
LED
LED anschliessen
Um die LED und den RasPi zu schützen, muss jeweils ein [Vorwiderstand] angeschlossen werden. Im Link steht, wie man die [Farbcodes] liest, wenn man kein Multimeter zur Verfügung hat. Je nach Leuchtstärke und [Farbe der LED] ergeben sich sich folgende Werte:
LED-Farbe | Widerstand | Stromfluss (mA) |
---|---|---|
rot | 470 | 2.7-3.5 |
rot | 680 | 1.9-2.2 |
rot | 1 k | 1.3-1.5 |
orange / gelb / grün | 470 | 2 |
orange / gelb / grün | 1 k | 1 |
blau / weiss | 470 | 3 |
blau / weiss | 1 k | 1 |
Im oben verlinkten Artikel zum Vorwiderstand wird auf die Vorwärtsspannung der LED hingewiesen, welche dem Datenblatt entnommen werden muss, da die LED bauartbedingt unterschiedliche Spannungen haben und damit auch unterschiedliche Widerstandswerte brauchen. Die Widerstandswerte sind der [E6-Widerstandsreihe] entnommen.
Da LEDs Dioden sind, besitzen sie eine Sperr- und eine Durchgangsrichtung. In Sperrrichtung vertragen sie eine Spannung von 25V bis zu 30V. Somit geschieht bei Experimenten mit dem RasPi nichts, wenn man diese falsch gepolt einsetzt. Damit sie leuchtet, muss die Anode am Plus und die Kathode am GND angeschlossen werden. Die Kathodenseite ist normalerweise abgeflacht, kürzer und manchmal auch "abgeknickt".
LED blinken lassen
Das folgende Python-Programm verwendet die RPi.GPIO Bibliothek. Hier wird mit sleep gearbeitet, was man in einem "richtigen" Programm vermeiden sollte, da etwa Tastendrücke damit nicht eingelesen werden. Hier sollten besser Interrupts eingesetzt werden.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BPM) # Die Nummerierung der Pins nach dem BPM-Schema verwenden GPIO.setup(18, GPIO.OUT) # Pin 18 als Output definieren while(True): GPIO.output(18, True) # Pin einschalten time.sleep(0.5) # 1/2 Sekunde warten GPIO.output(18, False) # Pin ausschalten time.sleep(0.5)
Es ist auch möglich, die LED manuell über ein GUI mit tkinter anzusteuern. Das Programm stammt von Simon Monk und kann auf [github heruntergeladen werden.
LED dimmen
Durch Pulsweitenmodulation lässt man eine LED in hoher Frequenz ein- und ausschalten, so dass es für das Auge aussieht, als sei die LED dunkler oder heller. Bei der [PWM] wird ein Puls nur zu % Prozenz der Pulslänge aktiviert.
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BPM) # Die Nummerierung der Pins nach dem BPM-Schema verwenden GPIO.setup(18, GPIO.OUT) # Pin 18 als Output definieren pwm_led = GPIO.PWM(18, 500)# PWM-Frequenz vom Pin 18 auf 500 Hertz setzen pwm_led.start(100) # mit 100% starten? while(True): arg = input("Helligkeit in %:") # Wert einlesen arg = int(arg) # nach int konvertieren pwm_led.ChangeDutyCycle(arg) # Prozentwert übergeben time.sleep(0.5)
Das Programm stammt von Simon Monk und kann auf github heruntergeladen werden.
Je nach Chip und Frequenz weicht die effektive Frequenz von der übergebenen Frequenz ab. Je schneller die gewünschte Freq. umso grösser ist der Abstand. Bei 10kHz kann es sein, dass es effektiv nur 4.4kHz sein. Dies könnte mit einem [Oszilloskop] gemessen werden. Im tieferen Frequentbereich wie bei 500 Hz sind es etwa 470 Hz, was völlig ausreichend ist. Wenn man die entsprechende Abweichungskurve kennt, kann man dieser natürlich entgegenwirken, indem man die Vorgabe entsprechend erhöht.
Im Kapitel Timerbaustein 555 sieht man eine alternative Möglichkeit der Dimmung mit einem Transistor.
Wenn man PWM grafisch einsetzen möchte, kann man dies auch mit tkinter umsetzen.
Hochleistungs-LED-Feld
Um grössere Leistungen schalten zu können, wie etwa ein ganzes LED-Feld mit Hochleistungs-LEDs genügt der maximale Strom eines GPIO-Pins nicht mehr. Hier braucht es einen Transistor, welcher die Leistung durchlässt und mit dem Ausgang des GPIO geschaltet wird. Für die Einspeisung der LED muss je nach Leistung eine externe Spannungsquelle (5V / 12V) verwendet werden.
![](/mediawiki/images/thumb/2/2f/LED-Feld_mit_Transistor_ansteuern.png/200px-LED-Feld_mit_Transistor_ansteuern.png)
- Die programmtechnische Ansteuerung (Ein/Aus, Dimmung) geschieht genau gleich wie bei einer einzelnen LED.
- Als Transistor wird ein MOSFET wie der FQP30N06 verwendet, der bis zu 30 Ampere durchschalten kann.
- Als Vorwiderstand für die Basis genügt ein 1k Widerstand.
Mit dieser Anordnung können auch andere Niederspannungsgeräte angesteuert werden. Ausnahmen sind Relais und Motoren, die auf Grund von Spannungsspitzen und/oder spezieller Ansteuerung gesondert angesteuert werden müssen.
RGB-LED
Eine RGB-LED besteht aus einzelnen LEDs und braucht daher 3 PINs, welche dann kombiniert werden. Um mehr als nur die Grundfarben zu kombinieren, kann man mit PWM auch Zwischenfarben und Farbverläufe erziehlen. Im Artikel zu Python ist ein Beispielprogramm mit Schiebereglern zu finden.
Bei einer RGB-LED verwendet man die gleichen Vorwiderstände (1k) wie bei einer normalen LED. Bei gemeinsamer Kathode schliesst man diese an GND und die Anoden über die Widerstände an die jeweiligen PINs. Die Belegung der LED ist dem Datenblatt zu entnehmen. Wenn die Beinchen nicht gekürzt wurden, ist die Kathode etwas länger als die Anoden.
Motor
Gleichstrommotor
![](/mediawiki/images/thumb/a/af/Anschluss_Gleichstrommotor.jpg/200px-Anschluss_Gleichstrommotor.jpg)
Diese Motorart kann man entweder digital (Ein/Aus) ansteuern oder man bestimmt die Geschwindigkeit über PWM. Hierbei muss man aber berücksichtigen, dass sich die Leistung nicht linear verhält. Vielfach werden die kleinen Motoren daher mit einem Getriebe untersetzt. Um die Elektronik vor Stromspitzen beim Abschalten des Motors durch die Induktion zu schützen, wird eine Freilauf-Diode (1N4001) zwischengeschaltet, welche auf den Motor abgestimmt sein sollte. Zusätzlich wird auch der Pin des Raspi über einen Widerstand (1k) angeschlossen, so dass nicht zu viel Strom fliesst.
Je nach Motor kann dieser direkt über den Raspi eingespeist werden. Zieht er zu viel Strom, so dass dieser abstürzt oder sonstwie unstabil wird, muss er extern gespiesen werden. Als Steuerungstransistor kann der 2N3904 oder einer mit ähnlicher Spezifikation verwendet werden. Wichtig ist hier vor allem die Hitze-Entwicklung, da der Strom des Motors auch durch den Transistor fliesst.
Richtung steuern mit H-Brücken-Modul (L293D-Chip)
Die Drehrichtung wird über den Anschluss gesteuert. Je nachdem, wie + und GND angeschlossen werden, dreht der Motor nach links oder nach rechts. Da die hardwaremässige Umverdrahtung natürlich nicht gewünscht ist, wurden entsprechende Module entwickelt, welche auf entsprechenden Steuerimpuls die Richtung umschalten. Die Ansteuerung der Geschwindigkeit geschieht weiterhin transparent über PWM. Ein entsprechender Baustein ist der L293D.
import RPi.GPIO as GPIO import time enable_pin = 18 # Aktiviert den Chip. Durch PWM auf diesem Pin wird auch die Geschwindigkeit festgelegt in1_pin = 23 # Drehrichtung Uhrzeigersinn in2_pin =24 # Drehrichtung Gegenuhrzeigersinn GPIO.setmode(GPIO.BCM) GPIO.setup(enable_pin, GPIO.OUT) GPIO.setup(in1_pin, GPIO.OUT) GPIO.setup(in2_pin, GPIO.OUT) pwm = GPIO.PWM(enable_pin, 500) # PWM auf 500 Hz setzen pwm.start(0) def clockwise(): GPIO.output(in1_pin, True) GPIO.output(in2_pin, False) def counter_clockwise(): GPIO.output(in1_pin, False) GPIO.output(in2_pin, True) while True: cmd = input("Befehl (vorwärts(v), rückwärts(r), Geschwindigkeit 0-9 -> r7 oder v3:") # Richtung und Geschwindikeit einlesen direction = cmd[0] # Das erste Zeichen ist die Richtung if direction == "v": # Nur bei v geht es vorwärts clockwise() else: counter_clockwise() # Bei einer richtigen Auswertung müsste man natürlich auch auf r prüfen und sonst den Motor anhalten speed = int(cmd[1]) * 11 # Berechnet zu wieviel Prozent der Motor angesteuert werden soll pwm.ChangeDutyCycle(speed) # Geschwindigkeit setzen # Bei einem richtigen Programm müssten bei einem Abbruch noch alle Pins rückgesetzt werden
Schrittmotor
Schrittmotoren haben mehrere Wicklungen. Die Art der Magnetisierung dieser Wicklungen bestimmt, ob es sich um einen unipolaren oder bipolaren Schrittmotor handelt. Die folgenden Links zeigen detailliert die Ansteuerung und Unterschiede auf:
Beide Motorarten können mit PWM angesteuert werden, doch Halb- und Viertelschritt beherrscht nur der bipolare Schrittmotor. Vielfach werden 2-phasige Schrittmotoren verwendet, wobei es aber auch 3- oder 5-phasige gibt, welche entsprechend genauere Positionen erlauben (Schrittwinkel tiefer). Durch elektonische Beeinflussung des Ansteuerungssignals sind neben Halb- und Viertelschritt auch Mikroschritte möglich. Dies geht soweit, dass man mit einem Drehfeld arbeitet und so einen Drehstrommotor simuliert. Hierbei ist zwar die Laufruhe extrem gross, doch die Positionsmessung ohne externe Rückmeldung ist nicht mehr einfach möglich.
unipolar
![](/mediawiki/images/thumb/7/75/Darlington-Unipolarer_Schrittmotor.jpg/200px-Darlington-Unipolarer_Schrittmotor.jpg)
Die Ansteuerung dieser Variante ist einfacher und wird daher häufig im Niedrigpreis-Segment verwendet. Unipolare Schrittmotoren haben 5 oder 6 Kabel für den Anschluss. Beim 5 kabligen Anschluss wurden die Mittelabgriffe zusammengefasst. Entsprechend kann dieser Motor nur unipolar betrieben werden. Beim Motor mit einer geraden Anzahl Kabel (4, 6, 8) kann man die Ansteuerung auch bipolar gestalten. Durch die Art der Ansteuerung wird immer nur die eine Hälfte der Wicklungen bestromt, wodurch der Wirkungsgrad bei tiefer Drehzahl viel tiefer ist als bei bipolaren Motoren. Bei der Ansteuerung wird der Mittelteil der Spulen an die Bestriebsspannung angeschlossen und anschliessend werden abwechselnd die Enden der Spulen auf Masse geschaltet, so dass das Magnetfeld sich bewegt und sich der Motor in die entsprechende Richtung bewegt. Dadurch, dass nur die halbe Spule verwendet wird, ist aber bei hohen Drehzahlen ein grösseres Moment möglich.
Mit einem Multimeter lassen sich die Anschlüsse (Mittelabgriff, Spulenenden) schnell bestimmen, wenn kein Datenblatt vorhanden ist. Die Ansteuerung kann mit einem Darlington-Chip erfolgen. Der Chip ist für die Ansteuerung von 2 Motoren ausgelegt oder man kann ihn für einen grösseren Strombedarf parallel schalten.
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) coil_A_1_pin = 18 coil_A_2_pin = 23 coil_B_1_pin = 24 coil_B_2_pin = 17 GPIO.setup(coil_A_1_pin, GPIO.OUT) GPIO.setup(coil_A_2_pin, GPIO.OUT) GPIO.setup(coil_B_1_pin, GPIO.OUT) GPIO.setup(coil_B_2_pin, GPIO.OUT) forward_seq = ['1010', '0110', '0101', '1001'] # Ansteuerungsreihenfolge der Spulen für einen Vollschritt reverse_seq = list(forward_seq) # Liste kopieren reverse_seq.reverse() # Dreht die Reiehenfolge der Ansteuerung um def forward(delay, steps): for i in range(steps): for step in forward_seq: set_step(step) # Schritt ausführen -> wie viele Schritte es für eine Umdrehung braucht, ist von der Verzahnung abhängig time.sleep(delay) # Wartezeit (sollte je nach Motor um die 2 ms betragen. Wenn zu klein dreht sich der Motor nicht.) def backwards(delay, steps): for i in range(steps): for step in reverse_seq: set_step(step) time.sleep(delay) def set_step(step): GPIO.output(coil_A_1_pin, step[0] == '1') GPIO.output(coil_A_2_pin, step[1] == '1') GPIO.output(coil_B_1_pin, step[2] == '1') GPIO.output(coil_B_2_pin, step[3] == '1') while True: set_step('0000') # Spulen ausschalten, damit kein Strom fliesst delay = input("Wartezeit zwischen den Schritten in ms?") steps = input("Wie viele Schritte vorwärts? ") forward(int(delay) / 1000.0, int(steps)) set_step('0000') steps = input("Wie viele Schritte rückwärts? ") backwards(int(delay) / 1000.0, int(steps)) set_step('0000')
bipolar
![](/mediawiki/images/thumb/f/f5/Ansteuerung_bipolarer_Schrittmotor.jpg/200px-Ansteuerung_bipolarer_Schrittmotor.jpg)
Hier werden die Spulen abwechselnd nicht nur ein- und ausgeschaltet, sondern die Ansteuerung wird auch noch umgedreht. Dadurch wird vor allem bei tiefer Drehzahl ein hohes Drehmoment ermöglicht. Weil aber die ganze Spule eingesetzt wird, ist auch die Impendanz höher, was sich bei hoher Drehzahl auswirkt, weil dann die Magnetisierung nicht mehr komplett abgebaut werden kann und so die Leistung abnimmt. Durch Nutzung der ganzen Wicklung, kann aber eine höhere Leistung bei gleicher Baugrösse oder eine kleine Baugrösse bei gleicher Leistung erreicht werden. Um eine möglichst hohe Effizienz zu erreichen, wird wenn möglich mit Konstantstrom gearbeitet, was aber eine entsprechende Logik voraussetzt, da hierbei gemessen werden muss, wie viel Strom fliesst und diesen dann rechtzeitig abzustellen, um ihn nachher wieder anzustellen, sobald dies auf Grund der Motoreigenschaften wieder notwendig ist. Diese Art der Ansteuerung wird von Motortreiber-Bausteinen übernommen, wodurch die Komplexität der Schaltung gekapselt wird, wobei man "von aussen" nur noch die Signale für die Drehrichtung und die Geschwindigkeit einspeisen muss.
Um die Ansteuerung umzukehren, werden H-Brücken eingesetzt. Der maximale Strom wird meist für den unipolaren Betrieb angegeben (wenn nicht explizit vermerkt) und muss für den bipolaren Betrieb um den Faktor (0.7) verringert werden.
Um Halb- und Viertelschritt zu erreichen, werden neben den unterschiedlichen Ansteuerungen beim Vollschritt noch Zwischenschritte eingebaut, bei denen jeweils nur eine Spule angesteuert wird. Durch die Zwischenschritte ergeben sich zwar genauere Positionen, doch dies wird mit einem kleineren möglichen Drehmoment erkauft. Da die Leistung je nach Ansteuerung der Stulen unterschiedlich ist, ergibt sich bei niedriger Drehzahl ein unruhiger Lauf, der durch gute Motorsteuerungen mit entsprechendem Anstieg des Stromes automatisch kompensiert wird.
Ohne Datenblatt kann man die Kabel ausmessen, um die Spulen zu bestimmen. Hat der Motor 8 Anschlüsse, so sind 2 Spulenpaare vorhanden, welche je nach gewünschter Eigenschaft in Reihe oder parallel angeschlossen werden können. Beim Parallelbetrieb ergibt sich mehr Drehmoment im oberen Drehzahlbereich, doch dafür muss der Stromregler höheren Anforderungen gerecht werden.
Für die Ansteuerung kann durch die Verwendung des L293D das gleiche Programm wie beim unipolaren Motor verwendet werden. Möchte man Halb- oder Viertelschritt implementieren, so muss man die Schrittsequenz verfeinern. Die notwendigen Tabellen finden sich in den Links zum Schrittmotor.
Für die Ansteuerung von bipolaren Schrittmotoren kann auch das RasPi Robot Board verwendet werden. Wichtig ist dort, dass man nur das Robot-Board einspeist und nicht zusätzlich den Raspi, damit keine Ausgleichsströme fliessen, welche die Elektronik zerstören könnten. Bei Verwendung des Boards muss man das Programm etwas modifizieren, da der Chip etwas anders verdrahtet wird. Auf der Webseite ist es das Programm stepper_rrb.py.
Stellmotor / Servo
Diese Motorart beschreibt eine Motoranwendung. Daher ist sie nicht an einen bestimmten Motortyp gebunden, sondern kann aus verschiedenen Motortypen gebildet werden. Wichtig ist dabei nur, dass die Ansteuerung über PWM geschieht und die Motorstellung über eine Messeinrichtung kontrolliert wird. Entsprechend kann der gewünschte Stellwinkel über das PWM-Signal definiert werden. Dies bedeutet aber auch, dass der Motor nicht mehrere (unendliche) Umdrehungen macht, sondern sich nur im Bereich seines Endanschlags bewegt (z.B. 0°-180°). Es gibt aber auch Möglichkeiten, die Servo-Einheit zu modifizieren, so dass er sich wie ein Getriebemotor verhält: Servomodifikation.
Für den Anschluss an den Raspi sollte man eine externe Stromquelle verwenden, um den Raspi nicht zu überlasten. Um Spannungsspitzen beim Anlauf zu vermeiden, sollte der Steuer-Pin mit einem 1k Widerstand geschützt werden. Die Verdrahtung selbst ist simpel, da der Motor nur 3 Anschlüssel hat. 1 wird für die Einspeisung verwendet und der andere für GND und der dritte wird über den Widerstand an den gewünschten GPIO-Pin angeschlossen, welcher das PWM-Signal liefert. Beim Raspi ist dies der Pin 18. Das Programm kann natürlich auch ohne GUI eingesetzt werden.
from tkinter import * # grafische Bibliothek tkinter laden import RPi.GPIO as GPIO # RPi-Bibliothek laden import time # Zeit-Bibliothek laden GPIO.setmode(GPIO.BCM) # BCM-Modus einschalten GPIO.setup(18, GPIO.OUT) # Pin 18 als Output definieren pwm = GPIO.PWM(18, 100) # Frequenz auf 100 Hz setzen pwm.start(5) # Startstellung ist bei 5%? class App: # Klasse definieren def __init__(self, master) : # Konstruktor generieren frame = Frame(master) # Vaterklasse aufrufen frame.pack() # Layoutmanager pack verwenden scale = Scale(frame, start = 0, end = 180, orient = HORIZONTAL, command = self.update) # Schieberegler definieren scale.grid(row=0) # Schieberegler positionieren def update(self, winkel): # Funktion zur Anpassung des Winkels erstellen position = float(winkel) / 10.0 + 2.5 # PWM-Signal aus Position berechnen pwm.ChangeDutyCycle(position) # Neues Signal an den Pin übergeben root = Tk() # Fenster generieren root.wm_title('Servo Control') # Titel setzen app = App(root) # App-Abjekt aus der Klasse erstellen root.geometry("200x50+0+0") # Fenstergrösse festlegen root.mainloop() # Start der Routine
Das Programm stammt von Simon Monk und kann auf github heruntergeladen werden.
mehrere Stellmotoren ansteuern
Für die genaue Ansteuerung von (mehreren) Servo-Motoren gibt es von Adafruit ein entsprechendes Modul, das über I2C angesprochen wird.
Relais
Da beim Relais beim Ausschalten eine hohe Spannungsspitze entsteht, muss diese mit einer Diode abgefangen werden, da sonst die gekoppelten elektronischen Bauteile zerstört werden. Da Relais mechanische Bauteile sind, unterliegen sie einer entsprechenden Abnutzung und können auch nicht für hochfrequente Schaltvorgänge benutzt werden. Der Vorteil liegt in getrennten Stromkreisen, so dass man auch eine Wechselspannung (230V) schalten kann, ohne dass diese mit der Schaltung gekoppelt würde. Für grosse Leistungen werden hingegen die verwandten Schütze verwendet. Im Gegensatz zu einem Schalter arbeiten Relais wie Taster, das heisst, sie sind monostabil, wobei es auch bistabile Relais mit zwei Spulen gibt. Da ein Relais rund 50mA Strom benötigt, um den Schalter zu schliessen, muss ein Transistor den Ausgang des Raspi unterstützen.
![](/mediawiki/images/thumb/4/42/Relais_ansteuern.jpg/200px-Relais_ansteuern.jpg)
- Für den Schutz des GPIO-Pins wird ein 1k Widerstand eingesetzt.
- Als Schalter genügt ein 2N3904 Transistor ( 200mA, 40V, 625mW).
- Als Diode wird eine 1N4001 eingesetzt, welche 1A bei bis 50V verträgt. Die letzte Ziffer bestimmt hier die Sperrspannung, welche bei der 1N4007 1000V beträgt.
- Als Relais kann ein beliebiges 5V Exemplar verwendet werden. Je nach Belegung muss der Aufbau auf dem Steckbrett angepasst werden. Bei der gezeigten Schaltung ist +5V oben links und GND unten links, während sich der geschaltete Ausgang unten rechts und mittig links befindet.
- Als Ansteuerung kann das gleiche Programm wie bei "LED blinken" verwendet werden. PWM ist wegen der Mechanik aber nicht möglich.
Wechselspannung schalten
Um gefahrlos Wechselspannung zu schalten, gibt es Bausätze oder fertige Elemente, welche ein Relais mit einem Optokoppler verwenden, so dass man den GPIO-Pin direkt ans Gerät anschliessen kann. Solche Produkte und/oder Bausätze sind unter der Bezeichnung "Powerswitch tail" oder "IoT Power Relay" zu finden.