Raspberry Pi

Weiter geht's im Text…

… mit dem Raspberry. Hierbei ist es egal welcher, das betrifft alle Versionen gleichermaßen. Egal ob Zero, 1 oder 2, egal ob A(+) oder B(+).

Grundinstallation

Ich denke mal die Grundinstallation sollte jedem klar sein. Ich persönlich verwende ausschließlich Raspbian. Bekommen kann man das auf der offiziellen Homepage in 2 Versionen – Normal mit grafischer Oberfläche oder Light ohne. Ich bevorzuge letzteres und installiere mir ggf. die grafische Oberfläche später dazu. Ist ja möglich. Auf der Seite stehen auch Installationsanweisungen.

Ab jetzt gehe ich also von einem lauffähigem System aus.

Vergesst nicht mittels

sudo raspi-config

das Dateisystem auf die Größe der SD Karte zu expandieren. Es ist gleich der erste Punkt.

Updates

Linuxer kennen es genau so wie Windows und Mac Benutzer. Betriebssysteme werden gelegentlich aktualisiert – so auch Raspbian. Um die aktuellsten Updates zu bekommen gebt in der Konsole folgende Befehle ein:

sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get upgrade
sudo shutdown -r now

Damit werden alle Updates geladen und installiert Das dauert ein Weilchen, je nachdem wie schnell eure Internetverbindung ist und welchen Raspberry Pi ihr nutzt.

Tendenziell wäre es eine gute Idee jetzt von der Karte noch mal ein Backup zu machen. Sonst müsst ihr das alles noch mal durchlaufen solltet ihr euer System zerbasteln.

SPI und TWI/I2C freischalten

Diese Funktionen sind standardmäßig deaktiviert, die Pins können also als normale IO Pins verwendet werden. Da der Raspberry davon aber genug hat und ich beide Bussysteme häufig nutze ist es das Erste was ich aktiviere. Gebt hierzu in der Konsole ein:

sudo raspi-config

In diesem Config Tool schaut mal unter "Advanced options". Hier sind 2 Menüpunkte relevant, nämlich I2C und SPI. Aktiviert hier beide Funktionen (inklusive automatischem Laden der Module falls ihr gefragt werdet). Nach einem Neustart sollten dann die Module geladen sein und zur Verfügung stehen. Zumindest für das System.

Python und Module installieren

Weiter geht es mit der Installation von Python und dessen Modulen für SPI und TWI/I2C. Ich bleibe eben dem Namen treu (Raspberry PI, PI=Python Interpreter) und nutze Python. Wieder in der Konsole gebt folgende Befehle ein (# sind Kommentare und können weg gelassen werden):

# Python 2 und 3 installieren
sudo apt-get install python-dev python3-dev
sudo apt-get install python-pip python3-pip

# GPIO Support
sudo apt-get install python-rpi.gpio python3-rpi.gpio

# I2C Support
sudo apt-get install python-smbus python3-smbus libi2c-dev

# SPI Support
wget https://github.com/Gadgetoid/py-spidev/archive/master.zip
unzip master.zip
rm master.zip
cd py-spidev-master
sudo python setup.py install
sudo python3 setup.py install
cd ..
sudo rm -f -r py-spidev-master

Jetzt ist Python 2 und 3 installiert und kann auf die GPIO, TWI/I2C und SPI Funktionen zugreifen.

Es gibt auch noch ein weiteres Plugin, namentlich WiringPi, mit dem ich selbst noch nichts gemacht habe. Die Installation sollte so gehen:

# WireingPi (bisher noch nichts mit gemacht, klingt aber nicht schlecht)
sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
# Muss hier noch was installiert oder kopiert werden?
cd ..
rm -f -r wiringPi

Das aber ohne Gewähr, lediglich der Vollständigkeit halber.

Verwendung von Python

Python ist nur eine Programmiersprache, keine grafische Oberfläche zum Programmieren wie z. B. Microsoft Visual Studio, AVR Studio (Atmel), …. Den Quelltext kann man in jedem x-beliebigen Texteditor erstellen (ich verwende hier nano), es gibt aber auch komfortablere Editoren wie z. B. Geany.

Ansich ist Python leicht zu verstehen, da es ähnlich wie Basic auf englischen Sprache basiert. Nichts kryptisches. Ganz wichtig bei Python ist das korrekte Einrücken der Quelltext Zeilen! Sollte man beim Programmieren eh immer drauf achten. Wer das eh tut wird keine Probleme haben, wer nicht wird fluchen. Aber über sich selbst.

Starten wir mit dem klassischem Beispiel HalloWelt.

Wieder in der Konsole öffnet nano und gebt schon mal den Dateinamen vor:

nano hallo.py

Jetzt seit ihr in nano, dem Texteditor, mit einer leeren Datei namens hallo.py. Sollte die Datei nicht leer sein existierte sie bereits ;)

Gebt hier folgenden Code ein:

#!/usr/bin/env python

print("Hallo Welt!")

Die erste Zeile ist Linux typisch. Anders als z. B. bei Windows, wo die Dateierweiterung (wie .txt, .mp3, …) festlegt welche Anwendung die Datei öffnen kann oder soll ist es hier so dass es die Datei selbst sagt (optional). Kann man weg lassen, sollte man aber einbinden. Hier besagt die Zeile dass die Datei mit Python (2) geöffnet werden soll.

Die zweite Zeile gibt ein "Hallo Welt!" auf der Konsole aus. Da danach nichts mehr folgt ist das Programm somit abgelaufen und beendet.

Speichern könnt ihr das Werk mit [STRG]+[O] und Enter, Beenden könnt ihr nano dann mit [STRG]+[X].

Jetzt soll das Programm natürlich gestartet werden. Es gibt mehrere Möglichkeiten. Die einfachste wäre einfach das Script mit Python zu starten:

python hallo.py

Eine andere Alternative wäre die Datei als ausführbar zu markieren und so zu starten. Da wird dann die erste Zeile im Script ganz wichtig.

chmod +x hallo.py
./hallo.py

Egal wie, es wird das Hallo Welt ausgegeben. Gratulation zum ersten Schritt :)

Auf GPIO zugreifen

 Hier geht es schon etwas los. Aber es ist alles recht einfach. Bevor wir los legen sagen wir welche Module wir verwenden wollen. Ich zeige hier auch noch ein paar Informationen an über das System. Das ist natürlich optional.

#!/usr/bin/env python
#
# Import sys (for version & error info) and time (for sleep) modules
import sys
import time

# Import GPIO module
try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO! This is probably because you need " + \
          "superuser privileges. You can achieve this by using 'sudo' to " + \
          "run your script.")
except:
    print("Unexpected error: ", sys.exc_info()[0])
#end try

# Print some version info
print("")
print("Using Python version:   %s.%s.%s" % sys.version_info[:3])
print("Installed GPIO Version: " + GPIO.VERSION)
print("Raspberry PI revision:  " + str(GPIO.RPI_REVISION))
print("")

# Set up pin numbering. BCM=Pin number from the controller, BOARD=Pin number from the header.
GPIO.setmode(GPIO.BCM)

# Set warnings on (if a pin is already used by another script). It's the default anyway.
GPIO.setwarnings(True)

Das Wichtigste hier ist das Einbinden von GPIO. Das kann bei manchen Distributionen fehlschlagen wenn das Script nicht als root läuft (z. B. mittels sudo), daher die Abfrage mittels try. Hier sieht man auch wie Python arbeitet, es nutzt das Einrücken aus um die Blöcke zu erkennen. Aus (Visual) Basic kenne ich das so dass es zu jedem If / try / … auch ein end if / try / … gibt, daher schreibe ich es auch in Python immer hin (als Kommentar). Ich finde es übersichtlicher. C ähnliche Sprachen nutzen die geschweiften Klammern, Python eben die Leerzeichen. Mal was Anderes.

Sollte euch eine Zeile mal zu lang geraten könnt ihr diese an bestimmten Stellen mit \ umbrechen. Habe ich hier in der Fehlermeldung gemacht.

So. Der Code oben macht aber eigentlich noch nichts, außer das bisschen Status auszugeben. Jetzt geht es weiter mit dem Code:

try:

    # Set pin as output
    GPIO.setup(26, GPIO.OUT)

    # Let the state change at 1hz
    while True:
        GPIO.output(26, True)
        time.sleep(0.5)
        GPIO.output(26, False)
        time.sleep(0.5)
    #end while

except KeyboardInterrupt:

    GPIO.output(26, False)
    pass

finally:

    # Ctrl+C pressed, cleanup
    GPIO.cleanup()

#end try

Hier wird erst der Pin 26 als Ausgang definiert. Dann wird in einer Schleife dieser High gesetzt, 0,5 Sekunden gewartet, auf Low gesetzt, wieder 0,5 Sekunden gewartet und alles von vorne.

Das ganze läuft in einem Try Block. So können wir abfangen wenn der Benutzer [STRG]+[C] drückt um das Script abzubrechen (es würde sonst unbegrenzt weiter laufen) um den Ausgang sicher auf Low zu setzen. Ebenfalls wichtig ist der Finally Block, der immer ausgeführt wird, egal ob ein Fehler aufgetreten ist oder nicht. Das ist hier wichtig, da wir bei Script Ende auch alle Bezüge zum GPIO entfernen wollen die wir erstellt haben. Somit ist nach Ablauf des Scripts wieder alles wie es vorher war.

Ziemlich einfach, oder? ;)

Mit Eingängen wird es etwas komplizierter, schlimm ist es aber nicht. Das Grundkonzept wie hier bleibt bestehen. Eingänge können verschieden definiert werden, mit internem PullUp oder PullDown. Da ich die Atmel AVRs gewöhnt bin welche ausschließlich PullUps besitzen nehme ich eher dieses, das ist aber Geschmackssache. Bei PullUp muss der Eingang eben auf Masse gezogen werden (beispielsweise mit einem Taster), bei PullDown gegen VCC. Seid hier vorsichtig! Die I/O Pins sind nicht abgesichert und verkraften nur maximal VCC, also 3,3V! Legt ihr ein 5V Signal an kann es das schon gewesen sein, mit etwas Glück für den Pin, mit Pech für den ganzen Pi. Dauerhaft. Durchgebrannt. Tot.

Nicht nur dass es PullUp und PullDown gibt, es gibt (wie überall) auch mehrere Arten den Pin auszulesen. So kann man ihn Pollen (direkt den Wert auslesen) was meistens aber nicht sinnvoll ist da es die CPU Last unnötig erhöht, oder man kann sich benachrichtigen lassen wenn sich der Zustand ändert (Interrupts).

Dieser Code zeigt wie man die GPIO's per Interrupt einliest. Vieles ist wie oben bereits beschrieben und erklärt, der Rest ist eigentlich selbsterklärend.

#!/usr/bin/env python
#
# Example script how to use GPIO on Raspberry PI (and to use Python).
#
# Wireing for this example:
#   Pin  7: Duo-LED Red
#   Pin  9: Duo-LED Kathode
#   Pin 11: Duo-LED Green
#   Pin 14: Switch 1, a
#   Pin 16: Switch 1, b
#   Pin 17: Switch 2, a
#   Pin 18: Switch 2, b
#
# Switch 1 turns on the green LED, Switch 2 turns it off while the red LED is flashing with 1hz.

#Import sys (for version & error info) and time (for sleep) modules
import sys
import time

# Import GPIO module
try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO! This is probably because you need " + \
          "superuser privileges. You can achieve this by using 'sudo' to " + \
          "run your script.")
except:
    print("Unexpected error: ", sys.exc_info()[0])
#end try

# Print some version info
print("Installed Python version: %s.%s.%s" % sys.version_info[:3])
print("Installed GPIO Version:   " + GPIO.VERSION)
print("Raspberry PI revision:    " + str(GPIO.RPI_REVISION))

# Set up pin numbering. BCM=Pin number from the controller, BOARD=Pin number from the header.
GPIO.setmode(GPIO.BCM)

# Set warnings on (if a pin is already used by another script). It's the default anyway.
GPIO.setwarnings(True)

# Setup two pins as input.
# Port 23 (pin 16) will be pulled up (3.3V), Port 24 (pin 18) down.
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

# Setup two pins as output.
GPIO.setup(17, GPIO.OUT)        # GPIO 17 (pin 11)
GPIO.setup(4, GPIO.OUT)         # GPIO 4  (pin 7)

# Callback if button 1 is pressed
def key1_down(channel):

    GPIO.output(17, True)

#end def

# Callback if button 1 is pressed
def key2_down(channel):

    GPIO.output(17, False)

#end def

# Subroutine which is called in the main application loop that simply turns an LED
# on GPIO4 (pin 7) on and off. Also demonstrates the sleep command.
def led_blink():
    GPIO.output(4, True)
    time.sleep(0.5)
    GPIO.output(4, False)
    time.sleep(0.5)
#end def

# Add event listeners to the 2 input signals (like interrupt service routines)
GPIO.add_event_detect(23, GPIO.FALLING, callback=key1_down)
GPIO.add_event_detect(24, GPIO.RISING, callback=key2_down)

# Main application loop
try:
    while True:
        led_blink()
    #end while
except KeyboardInterrupt:
    # Ctrl+C pressed
    pass
finally:
    GPIO.cleanup()
#end try

In einem späteren Beitrag erfahrt ihr wie man auf SPI und TWI/I2C zugreift, für heute reicht es erstmal :)