Anwendung des Raspberry Pi in Forschung und Lehre
Transcription
Anwendung des Raspberry Pi in Forschung und Lehre
Anwendung des Raspberry Pi in Forschung und Lehre Bachelor-Thesis Nico Maas Erstgutachter: Prof. Dr. Helmut G. Folz Einreichung: 30. September 2014 Selbständigkeitserklärung Ich versichere, dass ich die vorliegende Arbeit (bei einer Gruppenarbeit: den entsprechend gekennzeichneten Anteil der Arbeit) selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Ich erkläre hiermit weiterhin, dass die vorgelegte Arbeit zuvor weder von mir, noch von einer anderen Person an dieser oder einer anderen Hochschule eingereicht wurde. Darüber hinaus ist mir bekannt, dass die Unrichtigkeit dieser Erklärung eine Benotung der Arbeit mit der Note „nicht ausreichend“zur Folge hat und einen Ausschluss von der Erbringung weiterer Prüfungsleistungen zur Folge haben kann. Saarbrücken, 30. September 2014 Nico Maas iii Zusammenfassung Linux Einplatinen Computer sind seit dem Erscheinen des Raspberry Pi in 2012 immer präsenter in der IT und ermöglichen die schnelle und unkomplizierte Verbindung und Steuerung realer Hardware mittels modernen Hochsprachen wie C, Python oder Java. Die nachfolgende Arbeit soll an konkreten Beispielen versuchen, die Möglichkeiten des damit eröffneten „Physical Computing“, zur leichteren Darstellung komplexerer Lehrinhalte zu verwenden und damit den Lernerfolg nachhaltig zu steigern. v Any sufficiently advanced technology is indistinguishable from magic. — Arthur C. Clarke [4] Danksagung Für die geleistete Hilfe möchte ich mich in aller Form bei meinem Betreuer, Prof. Dr. Helmut G. Folz, dem Labor der Elektrotechnik, namentlich Dipl.-Ing. Thomas Bertel, sowie Prof. Dr. Peter Sturm, dem Team der PiAndMore und meiner Familie bedanken. vii Inhaltsverzeichnis Inhaltsverzeichnis 1 Einleitung 2 Plattform Evaluation 2.1 Raspberry Pi und BeagleBone Black . 2.1.1 Raspberry Pi Modell B+ . . . . 2.1.2 BeagleBone Black Revision C . 2.1.3 Vergleich . . . . . . . . . . . . . 2.2 Raspberry Pi Modelle . . . . . . . . . . 2.2.1 Unterschiede Modell A und B . 2.2.2 Modell B pre 2.0 . . . . . . . . . 2.2.3 Modell A/B 2.0 . . . . . . . . . 2.2.4 Compute Module . . . . . . . . 2.2.5 Modell A+/B+ . . . . . . . . . 3 ix 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 4 5 7 7 7 7 7 8 Grundlagen und Installation 3.1 Peripherie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 SD Karte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2 Netzteil mit Micro USB Anschluss . . . . . . . . . . . . . . 3.1.3 Netzwerkkabel . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.4 HDMI auf DVI Adapterkabel / Display mit DVI Eingang 3.1.5 Weitere Komponenten . . . . . . . . . . . . . . . . . . . . . 3.2 Anschluss des Raspberry Pi . . . . . . . . . . . . . . . . . . . . . . 3.3 Raspbian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Installation mittels Image . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Image downloaden . . . . . . . . . . . . . . . . . . . . . . . 3.4.2 Formatieren . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.3 Image kopieren . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.4 Backup und Wiederherstellung . . . . . . . . . . . . . . . . 3.5 Installation mittels noobs . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 noobs downloaden . . . . . . . . . . . . . . . . . . . . . . . 3.5.2 Formatieren . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.3 noobs kopieren . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.4 Raspbian mit noobs installieren . . . . . . . . . . . . . . . . 3.5.5 Vorteile von noobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 10 10 10 11 11 11 11 12 12 14 14 15 15 15 16 16 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix 4 5 6 x Konfiguration von Raspbian 4.1 Erster Boot . . . . . . . . . . . . . . . . . . . . . 4.1.1 raspi-config . . . . . . . . . . . . . . . . 4.2 WLAN Zugriff / eduroam . . . . . . . . . . . . 4.3 Updates . . . . . . . . . . . . . . . . . . . . . . 4.3.1 rpi-update . . . . . . . . . . . . . . . . . 4.3.2 apt-get . . . . . . . . . . . . . . . . . . . 4.4 Einrichtung Hardware . . . . . . . . . . . . . . 4.4.1 Vorbereitung des I²C / SPI Bus . . . . . 4.4.2 Vorbereitung der seriellen Schnittstelle 4.5 Einrichtung Software . . . . . . . . . . . . . . . 4.5.1 Installation von wiringpi2 . . . . . . . . 4.5.2 Installation von wiringpi2-python . . . 4.5.3 Test des SPI Bus (Optional) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 19 19 22 23 23 24 25 25 26 27 27 28 29 GPIO Schnittstelle 5.1 Aufbau . . . . . . . . . . . . . . . . . . . . . . . 5.2 Sicherheitshinweise . . . . . . . . . . . . . . . . 5.2.1 Logik Level . . . . . . . . . . . . . . . . 5.2.2 Sicherungen . . . . . . . . . . . . . . . . 5.2.3 Belastbarkeit der Pins / 3,3 Volt Schiene 5.2.4 Belastbarkeit der 5 Volt Schiene . . . . . 5.2.5 Zusammenfassung . . . . . . . . . . . . 5.3 GPIO . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 GPIO . . . . . . . . . . . . . . . . . . . . 5.3.2 PWM . . . . . . . . . . . . . . . . . . . . 5.3.3 I2C . . . . . . . . . . . . . . . . . . . . . 5.3.4 I2S . . . . . . . . . . . . . . . . . . . . . 5.3.5 SPI . . . . . . . . . . . . . . . . . . . . . 5.3.6 Serial . . . . . . . . . . . . . . . . . . . . 5.4 Das Erweiterungsboard . . . . . . . . . . . . . 5.4.1 Design . . . . . . . . . . . . . . . . . . . 5.4.2 Routing . . . . . . . . . . . . . . . . . . 5.4.3 Testprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 31 32 32 32 32 32 33 33 33 34 35 36 36 37 38 38 38 40 Bash Programmierung 6.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . 6.1.1 Simon . . . . . . . . . . . . . . . . . . . . 6.1.2 Ablaufdiagramm . . . . . . . . . . . . . . 6.2 Programmierung . . . . . . . . . . . . . . . . . . 6.2.1 Erweiterungsboard und Hilfsfunktionen 6.2.2 LED Ausgabe . . . . . . . . . . . . . . . . 6.2.3 Switch Eingabe . . . . . . . . . . . . . . . 6.3 Abschluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 43 43 44 44 45 46 46 47 7 8 9 Python Programmierung 7.1 Arbeiten auf dem Raspberry Pi . . . . . . . . . . . . . 7.1.1 Python 2 / Python 3 . . . . . . . . . . . . . . . 7.1.2 Programmierung mittels IDLE . . . . . . . . . 7.1.3 Programmierung mittels CLI . . . . . . . . . . 7.2 Grundlagen der Python Programmierung . . . . . . . 7.2.1 Ausführung . . . . . . . . . . . . . . . . . . . . 7.2.2 Variablen . . . . . . . . . . . . . . . . . . . . . . 7.2.3 Operatoren . . . . . . . . . . . . . . . . . . . . 7.2.4 Vergleiche und Schleifen . . . . . . . . . . . . . 7.2.5 Funktionen . . . . . . . . . . . . . . . . . . . . 7.2.6 Bibliotheken . . . . . . . . . . . . . . . . . . . . 7.3 Verwendung der GPIO mittels Python . . . . . . . . . 7.3.1 Digitale Ausgabe: LEDs . . . . . . . . . . . . . 7.3.2 Übungsaufgabe zur digitalen Ausgabe . . . . 7.3.3 Digitale Eingabe: Schalter . . . . . . . . . . . . 7.3.4 Übungsaufgabe zur digitalen Eingabe . . . . . 7.3.5 Abschlussprojekt GPIO: Binärzähler . . . . . . 7.4 Verwendung des I2C Bus mittels Python . . . . . . . . 7.4.1 Adressierung . . . . . . . . . . . . . . . . . . . 7.4.2 Register des Sensors . . . . . . . . . . . . . . . 7.4.3 Interpretation des Temperaturwertes . . . . . 7.4.4 Übungsaufgabe zur Verwendung des I2C Bus 7.5 Verwendung des SPI Bus mittels Python . . . . . . . . 7.5.1 Adressierung . . . . . . . . . . . . . . . . . . . 7.5.2 Kommunikation . . . . . . . . . . . . . . . . . 7.5.3 Übungsaufgabe zur Verwendung des SPI Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 49 49 49 50 50 50 50 50 53 54 56 57 57 58 58 58 59 60 60 61 62 62 63 63 64 66 Mathematica 8.1 Grundlagen . . . . . . . . . . . . . . . . 8.2 Benutzung . . . . . . . . . . . . . . . . . 8.2.1 Beispiele Free-form input . . . . 8.2.2 Beispiele Wolfram Alpha query . 8.3 Verwendung mittels Erweiterungsboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 69 69 70 70 72 Fazit 9.1 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 75 76 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Literatur 77 Abbildungsverzeichnis 79 Tabellenverzeichnis 80 xi Listings 81 Abkürzungsverzeichnis 82 A Vorgefertigtes Raspbian Image A.1 Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Zusätzlich installierte Pakete . . . . . . . . . . . . . . . . . . . . . . . . . 85 85 85 B Raspberry Pi Hardware HTW B.1 Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 87 C Erweiterungsboard 89 D Code Listings D.1 boardTest.c . . . . . D.2 gpio.sh . . . . . . . D.3 demoLed.sh . . . . D.4 demoSwitch.sh . . D.5 simon.sh . . . . . . D.6 uebungAusgabe.py D.7 uebungEingabe.py D.8 binaryCounter.py . D.9 lm75b.py . . . . . . D.10 uebungI2C.py . . . D.11 mcp3002.py . . . . D.12 mcp3002lib.py . . . D.13 uebungSPI.py . . . D.14 wpi.c . . . . . . . . D.15 wpi.tm . . . . . . . xii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 91 95 97 98 99 102 103 104 105 106 108 109 109 110 112 1 Einleitung Mit dem Erscheinen des Raspberry Pi im Februar 2012 war zum ersten Mal ein kleiner, kostengünstiger und dennoch leistungsfähiger Linux Einplatinen Computer verfügbar. Der ursprünglich zur Fortbildung von Kindern, im IT Bereich gedachte Rechner, etablierte sich in kürzester Zeit im Umfeld von Universitäten, Industrie sowie im Hobby und Freizeit Bereich. Andere Firmen entdeckten die potenziellen Möglichkeiten des neuen Absatzmarktes und entwickelten konkurrierende Plattformen mit teils unterschiedlichen Zielsetzungen und Möglichkeiten. Dazu zählen der BeagleBone Black, Intels Galileo, SECO / Aidilabs UDOO, Hardkernels Odroid sowie Adaptevas Parallella - um nur einige wenige zu nennen. All diese Plattformen haben gemeinsam, dass sie dazu genutzt werden können, als Lehrplattform für den Bereich des sogenannten „Physical Computing“ zu dienen. Beim Physical Computing ist die Software in der Lage durch eine spezielle Hardware Schnittstelle (General-purpose input/output (GPIO)) sowohl Eingaben aus der Umwelt zu empfangen, als auch selbst Ausgaben zu erzeugen. Dies könnte z.B. die Verwendung eines Schalters, Ultraschallsensors oder einer Lichtschranke für die Eingabe, und einer LED, einem Display oder eines Motors für die Ausgabe sein. Da durch verschiedene Frameworks und Libraries diese Schnittstellen nicht nur mittels spezieller Kommandos bedient werden können, sondern auch in Standardsprachen wie z.B. Bash, C, Java oder Python verfügbar sind, ergibt sich damit die Möglichkeit einer professionellen Entwicklung und die Integration dieser Einplatinen Computer in ganze Produkte und Automaten. In der nachfolgenden Arbeit soll aufgezeigt werden, wie ein solcher Linux Einplatinen Computer im Bereich der Forschung und Lehre dazu genutzt werden kann, um Studenten konkrete Lerninhalte leichter zu vermitteln. Dies beinhaltet die Evaluation des geeigneten Produktes aus der Vielzahl der konkurrierenden Systeme, die korrekte Installation und Konfiguration sowie die konkrete Nutzung in verschiedenen Projekten mit Verknüpfung zu den Vorlesungen an der HTW Saar. Um diese Umsetzung einfacher zu gestalten, wurden im Rahmen dieser Thesis eine eigene Erweiterungsplatine für den Raspberry Pi entworfen und gefertigt, wodurch auch die Lehre im Bereich Hardware naher Anwendungen, wie z.B. dem Inter-Integrated Circuit (I2C) oder Serial Peripheral Interface (SPI) Bus möglich wird. Verwendung finden sollen die vorgestellten Aufgaben in einem breitgefächerten Spektrum an Vorlesungen: „Betriebssystem Einführung“ (Bash Programmierung), „Systemsicherheit und Management“ (Python Einführung), „Digitaltechnik“ (Python: 4-bit Zähler), „Rechnerarchitektur“ und „Mikroprozessortechnik“ (SPI und I2C), „Mathematik 1-3“, „Informatikgrundlagen“ und „Graphentheorie“ (Mathematica). Obwohl bereits einige Vorlesungsbereiche damit aufgegriffen werden, sind die Möglichkeiten die dieser Einplatinen Computer bietet damit keinesfalls erschöpft und könn- 1 1 Einleitung ten in Arbeiten anderer Studenten fortgeführt und ergänzt werden. 2 2 Plattform Evaluation 2.1 Raspberry Pi und BeagleBone Black Wie bereits erwähnt gibt es neben dem Raspberry Pi noch zahlreiche weitere Konkurrenzprodukte welche ähnliches leisten. Der direkte Konkurrent allerdings ist das von Texas Instruments vorgestellte BeagleBone Black. Nachfolgend werden die beiden Plattformen mit ihren Vor- und Nachteilen verglichen und auf die besondere Eignung im Bereich der Lehre untersucht. 2.1.1 Raspberry Pi Modell B+ Der Raspberry Pi ist ein Einplatinen Computer mit der ungefähren Grundfläche einer Kreditkarte, nutzt Linux als Betriebssystem und ist zum Preis von knapp 33 e erhältlich. Er verwendet ein Broadcom BCM2835 System on a chip (SoC), welches einen 700 MHz starken ARM1176JZFS (ARM11/ARMv6) Prozessor beinhaltet sowie die 24 GFlops starke Videocore IV Grafikeinheit und 512 MB Arbeitsspeicher. Trotz des geringen Preises verfügt der Raspberry Pi über 4 USB Anschlüsse, einen 100 MBit Netzwerkanschluss, einen Full HD fähigen HDMI Anschluss, sowie einen analogen Audio und Cinch Video Ausgang (über ein Adapterkabel). Insgesamt stehen 40 GPIO Pins zur Verfügung, welche neben generischen Ein- und Ausgängen auch als spezielle Schnittstellen wie Serial, I2C, Inter-Integrated Sound (I2S) und SPI genutzt werden können. Eine Besonderheit bietet der Raspberry Pi mit den Camera Serial Interface (CSI) bzw. Display Serial Interface (DSI): Diese Schnittstellen bieten direkten Anschluss einer speziellen Kamera beziehungsweise eines demnächst verfügbaren TFT Displays an die Videocore IV Grafikeinheit. Durch den Anschluss der eigens entwickelten Kamera können trotz der vergleichsweise geringen CPU Leistung Photos in 2592 x 1944 Pixel, respektive Video ins Full HD Auflösung (1920 x 1080 Pixel) aufgezeichnet und mit Filtern versehen werden. Weiterhin kann die GPU auch in begrenztem Umfang zur Beschleunigung von eigenem Programmcode verwendet werden. Eine Micro SD Karte dient als Massenspeicher und die Stromversorgung erfolgt mittels Micro USB Netzteil. Als Betriebssystem kommt hauptsächlich Raspbian, eine für den ARMv6 optimierte Version von Debian zum Einsatz. Weiterhin sind Versionen von Arch Linux (Arch), Fedora (Pidora), XBMC (XBian, OpenElec, Raspbmc), RiscOS, Android und zahlreichen anderen Betriebssystemen zum Download verfügbar. Die Verwendung des Echtzeitbetriebssystems QNX ist allerdings wegen des fehlenden Board Support Packages nicht möglich. Die Entwicklung des Einplatinen Computers wurde von Eben Upton geleitet. Die Idee zu diesem Projekt kam ihm während seiner Zeit als Director of Studies in Compu- 3 2 Plattform Evaluation ter Science am St John’s College (Universität Cambridge). Er stellte mit seinen Kollegen fest, dass die Anzahl der Studienbewerber im Bereich der Informatik seit dem Beginn des Jahrtausend stetig rückgängig waren. Die heutigen Jugendlichen und Kinder würden sich zwar immer intensiver mit IT befassen, diese aber nur noch passiv Konsumieren anstatt aktiv damit zu arbeiten. Er sah die Begründung darin, dass eine günstige, „hackbare“ Plattform fehlen würde, sowie er sie selbst in seiner Kindheit in Form des BBC Micro erlebt hatte. [2] Der erste Entwurf des Raspberry Pi war daher nicht der Computer wie er heute verkauft wird, sondern eine Art Klone des BBC Micro auf Basis eines Atmel ATMega 644 (22.1 MHz, 512K SRAM, 320x240 Pixel). Dieser wurde von Eben Upton 2006 während seiner Zeit an der Universität Cambridge entworfen, das Projekt aber schnell eingestellt. Im gleichen Jahr wechselte Eben Upton zum Chiphersteller Broadcom und arbeitete am BCM2835, welcher später auch die Basis für den heutigen Raspberry Pi werden sollte. Insbesondere die Tatsache der guten Multimedia Unterstützung dieses SoC bewog Upton die Arbeit am Raspberry Pi wiederaufzunehmen. Er befürchtete dass der BBC Micro Klone bei der heutigen, mit Facebook und anderen grafischen Anwendungen vertrauten Jugend keinen Anklang finden könnte - ein Computer mit dem BCM2835 hingegen doch. Er gründete die Raspberry Pi Foundation, welche auf Basis des Einplatinen Computers auch Materialien für die Nutzung im Unterricht und der Fortbildung von Kindern und Jugendlichen in den sogenannten MINT Fächern erstellte. Damit ging der erste Raspberry Pi im Februar 2012 in den Verkauf und wurde seither mehr als 3 Millionen mal verkauft [24]. 2.1.2 BeagleBone Black Revision C Das BeagleBone Black entstammt einer Reihe von verschiedenen Einplatinen Computern, welche ihre Entwicklung 2008 in Form des BeagleBoard, einem 150 US Dollar teuren, 600 MHz schnellen Cortex-A8 Linux Boards begannen. Alle diese Entwicklungsboards haben die Gemeinsamkeit, dass sie von Texas Instruments Entwicklern entwickelt wurden und jeweils als SoC den aktuellen Kern aus dem Portfolio der genanten Firma beinhalteten. Der aktuelle BeagleBone Black (53 e) verwendet ein Texas Instruments AM335X SoC, welches eine 1 GHz starke ARM Cortex A8 CPU beinhaltet, sowie eine PowerVR SGX530 Grafikeinheit mit 1,6 GFlops und 512 MB Arbeitsspeicher. Die Konnektivität nach außen geschieht beim Bone über einen USB Host Port, einen USB Client Port, einen 100 Mbit Netzwerkanschluss sowie einen Micro HDMI Port. Der BeagleBone Black bietet 92 GPIO Pins, welche sich auf zwei Pinleisten verteilen, allerdings je nach verwendeter Peripherie (z.B. dem HDMI Ausgang, oder dem Onboard Speicher) nicht alle verfügbar sind. Als Protokolle dienen dort gleich mehrere Serial Schnittstellen, I2C und SPI Busse sowie ein Controller Area Network (CAN) und I2S Bus zur Verfügung. Als Massenspeicher dienen entweder die verbauten 4 GB eMMC Flashspeicher oder eine Micro SD Karte. Die Stromversorgung erfolgt über den USB Client Port oder über ein 5 Volt, 1 Ampere Netzteil. Als Besonderheit existieren 4 2.1 Raspberry Pi und BeagleBone Black beim BeagleBone Black zwei Programmable Realtime Unit (PRU), welche jeweils mit 200 MHz getaktet sind und unabhängig von der ARM CPU funktionieren. Diese 32 bit Microcontroller sind mit hoher Bandbreite, sowohl an den eigenen, als auch an den Arbeitsspeicher der ARM CPU angeschlossen und können dazu verwendet werden, rechenintensive oder zeitkritische Aufgaben zu übernehmen, ohne die CPU zu belasten. Alle Geräte der BeagleBoard und BeagleBone Reihe verwendeten Anfangs ein speziell angepasstes Ångström Linux, seit Anfang des Jahres wird das neue BeagleBone Black allerdings mit einer Anpassung von Debian vorinstalliert verkauft. Weiterhin stehen Ubuntu und Android sowie das Echtzeitbetriebssystem QNX zur Wahl. 2.1.3 Vergleich Raspberry Pi und BeagleBone Black scheinen auf den ersten Blick beide gleich gut zur Verwendung im Bereich der Lehre geeignet zu sein, jedoch gibt es bei genauerer Betrachtung einige wesentliche Unterschiede. Der größte und wesentliche, welcher sich sowohl im Design der Hardware, Software und verfügbaren Materialien widerspiegelt, ist die angepeilte Zielgruppe. Während der Raspberry Pi von Anfang an darauf ausgelegt war im Bereich der Lehre verwendet zu werden und erst später aufgrund des günstigen Preises von Hobbyisten und der Industrie aufgegriffen wurde, war das BeagleBone Black als ein Entwicklungs- und Demoboard für das entsprechende, frei zu erwerbenden SoC gedacht: Beide Hersteller haben die Baupläne ihres Produktes offengelegt, was die eigene Produktion eines solchen Boards ermöglichen würde. Allerdings ist nur der Kern des BeagleBone Black in kleinen, und nicht industriell üblichen Mengen erhältlich. Damit wird schnell klar, dass die Zielsetzung des BeagleBone Black ebenfalls das eines Referenzdesigns zur Integration in die eigene Schaltung ist. Weiterhin unterstützt wird diese These durch die Ausstattung in Hardware und Software: Während der Raspberry Pi mittels digitalem HDMI, sowie analogem Video und Audioanschlüssen, sowie vier USB Ports direkt als Standalone Rechner in fast allen Situationen eingesetzt werden kann, bietet der BeagleBone Black nur den digitalen HDMI Anschluss im unüblichen Micro HDMI Format, sowie einen USB Port - zu wenig um die übliche Kombination aus USB Maus, Tastatur und WLAN Dongle ohne zusätzliches Zubehör anschließen zu können. Dies gilt allerdings nicht nur für den Bereich der Hardware, sondern auch der Software: Während der Raspberry Pi mit einer Fülle von Entwicklungswerkzeugen und Software (Python, Mathematica, Scratch, Verweis auf Unterrichtsmaterialien uvm.) vorinstalliert kommt, verfügt der BeagleBone Black neben verschiedenen Systemprogrammen ausschließlich über einen Texteditor, Terminal, File Browser, Chrome sowie ein IRC Chat Tool. Zusammengefasst lässt sich also festhalten, dass der BeagleBone Black sicherlich ein gutes Werkzeug für die industrielle Entwicklung auf Basis des verwendeten Chips ist, allerdings für den Einsatz in der Lehre und der Verdeutlichung des Zusammenspiels von Hard- und Software nur bedingt geeignet ist. Nicht zuletzt auch wegen des mehr als anderthalbfach so hohen Preises und der bestehenden Lieferengpässe (Juli 2014), wurde der Raspberry Pi als Basis für die folgende Arbeit gewählt. 5 2 Plattform Evaluation Tabelle 2.1: Übersicht [6] Raspberry Pi Modell B+ BeagleBone Black Rev. C SoC Broadcom BCM2835 Texas Instruments AM3358 CPU ARM1176 / ARMv6 ARM Cortex-A8 / ARMv7 700 MHz, Hardware FPU 1 GHz, Hardware FPU RAM 512 MB 512 MB GPU Broadcom VideoCore IV PowerVR SGX530 24 GFlops 1,6 GFlops Int. Speicher - 4 GB Ext. Speicher Micro SD Micro SD Netzwerk 10/100 Mbit 10/100 Mbit Stromversorgung 5 V @ 2 A USB Micro 5 V @ 1 A USB Mini 5V @ 2.1mm Stecker Abmessungen 85.6 mm x 56 mm 86.4 mm x 53,3 mm Gewicht 45 g 40 g Preis 33 e 53 e Tabelle 2.2: I/O und Peripherie [6] 6 Raspberry Pi Modell B+ BeagleBone Black Rev. C Digitale I/O Pins 28 @ 3,3V 65 @ 3,3V Analoge Eingänge - 7 @ 12-bit ADC (0-1,8V) PWM Ausgänge 2 8 Serial 1 4 SPI 2 2 I2C 1 2 USB Host 4 USB A Anschlüsse 1 USB A Anschluss USB Client - 1 Mini B Anschluss Video Eingang CSI - Video Ausgang HDMI, Cinch, DSI Micro HDMI Audio Ausgang HDMI, Analog Micro HDMI Stromversorgung 3,3V @ 50 mA, 5V @ 1,2 A 3,3V @ 250 mA, 5V @ 1 A Besonderheiten - PRU, CAN Bus 2.2 Raspberry Pi Modelle 2.2 Raspberry Pi Modelle Seit Beginn der Entwicklung sind einige, verschiedene Modelle des Raspberry Pi erschienen. Am weitesten verbreitet ist das Modell B in der Version 2.0, weshalb auch der Hardware Anteil dieser Bachelor Thesis mit diesem Raspberry Pi durchgeführt wurde. Das neuste Modell, welches zukünftig als Standard dienen soll, ist der Raspberry Pi Modell B+. Die Unterschiede der einzelnen Plattformen sollen nachfolgend kurz erläutert werden. 2.2.1 Unterschiede Modell A und B Der prinzipielle Unterschied zwischen Modell A und B liegen in der Bestückung der Platinen. Das Modell A verfügt mit 256 MB nur über die Hälfte des Arbeitsspeichers des Modell B. Weiterhin wurde der SMSC LAN9512 entfernt. Dieser Chip diente zeitgleich als USB Hub für die beiden Ports des Modell B, wie auch als Netzwerkinterface. Damit verfügt das Modell A über nur einen USB Port und keinen Netzwerkanschluss. Dadurch wurde zum einen das Gewicht, der Stromverbrauch und schließlich der Preis auf 25 e reduziert. Besonders für mobile Anwendungen ist dieses Modell daher sehr geeignet. 2.2.2 Modell B pre 2.0 Das Modell B in der Version pre 2.0 war der erste erschiene Raspberry Pi im Februar 2012 und verfügte über 256 MB Arbeitsspeicher, da für das Modell A ursprünglich 128 MB Arbeitsspeicher geplant waren. 2.2.3 Modell A/B 2.0 Beim Übergang zu Revision 2.0 gab es einige Detailänderungen, so wurden z.B. wenige Pins inklusive des I2C Bus auf der GPIO Leiste um rangiert. Zum ersten Mal gab es auch das funktionsreduzierte Modell A. 2.2.4 Compute Module Das Compute Module entstand aus der Notwendigkeit eine kleinere, besser in industrielle Systeme und kommerzielle Produkte integrierbare Plattform zu entwickeln. Das Compute Module wurde daher im Format eines DDR2 SODIMM Riegels entworfen, und lässt sich damit leicht und platzsparend integrieren. Zusätzlich zu dem Compute Module wurde weiterhin ein Referenzdesign zur Verfügung gestellt, welches die notwendige Hardware zum Betrieb des Moduls enthielt. Aufgrund des kleinen Formfaktors und der hohen Anzahl an ausgeführten Ports über die SODIMM Leiste, konnte die Anzahl der nutzbaren GPIO Ports von 17 (Modell A/B 2.0) auf 46 gesteigert werden. Zusätzlich erhielt das Compute Modul jeweils zwei Anschlüsse für die CSI und DSI Systeme, was das Modul zur Anbindung von zwei speziellen Displays, sowie dem 7 2 Plattform Evaluation Einsatz im Bereich von stereoskopischen Kameraanwendungen befähigte. Das Compute Module verwendet, ähnlich wie der BeagleBone Black (Rev. C), einen 4 GB großen eMMC Flashspeicher. 2.2.5 Modell A+/B+ Das Modell B+ wurde im Juli 2014 vorgestellt und beinhaltete einige Verbesserungen im Vergleich zur Revision 2.0. So verfügt der Raspberry Pi über eine neue, energiesparendere Stromversorgung, einen rauschärmeren analogen Audioausgang, vier statt zwei USB Ports sowie anstatt der bisherigen 26, 40 GPIO Pins. Von diesen 40 Pins sind 28 (vorher 17) für eigene Projekte nutzbar, beim Rest handelt es sich um verschiedene Spannungsschienen (3,3V / 5V), Masse oder die neue Schnittstelle für Erweiterungsmodule (Pi Hats). Das Modell A+ wurde noch nicht veröffentlicht, jedoch ist geplant ähnlich wie beim Übergang von Modell B, Revision 2.0 eine neue Version des Modell A herauszubringen, welche vermutlich ebenfalls die Verbesserungen im Bereich Stromversorgung und GPIO Erweiterung enthalten wird. 8 3 Grundlagen und Installation In dem nachfolgenden Kapitel werden die Grundlagen zur Nutzung des Raspberry Pi gelegt. Dies umfasst das benötigte Zubehör zum Betrieb, sowie die Vorbereitung der SD Karte mittels der noobs Software beziehungsweise eines Images. Am Ende dieses Kapitels wird der Raspberry Pi angeschlossen sein und zum ersten Mal booten. 3.1 Peripherie Um den Raspberry Pi das erste Mal einzusetzen, ist es empfehlenswert diesen wie einen handelsüblichen Personal Computer anzuschließen. Neben dem Raspberry Pi ist dazu folgende Hardware nötig: • SD Karte • Netzteil mit Micro USB Anschluss • USB Maus • USB Tastatur • Netzwerkkabel • HDMI auf DVI Adapterkabel • Display mit DVI Eingang Bei der erwähnten Hardware sind allerdings noch einige Dinge zu beachten, bzw. kann diese auch im Bedarfsfall durch andere Komponenten ersetzt werden. 3.1.1 SD Karte Hier sollte mindestens eine 8 GB SD Karte eines Markenherstellers mit einer entsprechenden hohen Class eingesetzt werden. Die aktuelle Version von Raspbian belegt alleine etwas weniger als 4 GB Speicher, so dass beim Einsatz einer 4 GB Karte wenig Platz für eigene Projekte und Erweiterungen blieb, weshalb eine 8 GB Karte empfohlen wird. In den Anfängen der Entwicklung der Raspberry Pi Firmware gab es große Probleme bei der Verwendung von SD Karten unbekannterer Hersteller. Diese Probleme sind zum jetzigen Zeitpunkt fast ausgeschlossen, jedoch empfiehlt es sich dennoch weiterhin aus Gründen der Datensicherheit in das Produkt eines Markenherstellers zu investieren. Die Class beschreibt die Geschwindigkeitseinstufung einer SD Karte. Eine 9 3 Grundlagen und Installation möglichst hohe Class, wie z.B. Class 10 empfiehlt sich bei der Verwendung des Raspberry Pi, damit diese nicht zum limitierenden Faktor bei Schreib- und Lesezugriffen wird. Alternativ kann die SD Karte auch durch eine Micro SD Karte mit entsprechendem Adapter ersetzt werden, was beim Raspberry Pi Modell B+ zwingend erforderlich ist. 3.1.2 Netzteil mit Micro USB Anschluss Als Netzteil könnte beim Raspberry Pi (Modell A und B) prinzipiell ein altes Handyladegerät verwendet werden. Jedoch sollte man aufpassen, dass dieses mindestens 1,2 Ampere Strom liefern kann. Der Raspberry Pi könnte dank seiner auf 1,1 Ampere festgelegten Polyfuse bis zu 5 Watt an Leistung aufnehmen, oder weitere Leistung bis zu dieser maximalen Grenzen an angeschlossene Verbraucher weitergeben. Da besonders günstigere Netzteile den Strom bei höherer Belastung nicht konstant halten können, geht daher die Empfehlung an ein entsprechend starkes Netzteil mit 1,2 Ampere oder höher. Zu niedrige Versorgungsleistung kann sich in Schreib- / Lesefehlern bei der SD Karte, Fehlfunktionen des RPi, bis hin zum Einfrieren des gesamten Systems äußern. Beim Raspberry Pi Modell B+ sind dank der gesunkenen Anforderungen an Strombedarf ein Netzteil mit 1,2 Ampere weiterhin verwendbar, bei der Nutzung aller vier USB Ports empfiehlt sich allerdings die Verwendung eines Netzteils mit mindestens 2 Ampere Leistung, da die 1,1 Ampere Polyfuse durch eine 2 Ampere Polyfuse ersetzt wurde. 3.1.3 Netzwerkkabel Das Netzwerkkabel soll den Raspberry Pi mit einem Netzwerk, welches Internetzugang wie auch DHCP Service anbietet, verbinden. Dies ist bei normalen Heim Routern wie z.B. einer Fritz!Box Standard. Bei Firmen- oder Universitätsnetzwerken können weitere Schritte zur Einrichtung der Internetverbindung notwendig sein. 3.1.4 HDMI auf DVI Adapterkabel / Display mit DVI Eingang Um die Videoausgaben des Computers möglichst komfortable anzuzeigen, empfiehlt es sich eine HDMI auf DVI Adapterkabel zu verwenden und dieses mit dem DVI Eingang eines Computer Displays zu verwenden. Alternativ kann der Raspberry Pi auch direkt mit einem HDMI Kabel an einem HDMI Display oder modernen Fernseher angeschlossen werden. Letztere Methode hat den Vorteil, dass die Audiosignale zusammen mit dem Videosingal übertragen werden, was es zu einer idealen Anschlussart für Multimedia Anwendungen macht. Bei der Verwendung des DVI Eingangs muss das Audiosignal zusätzlich vom Raspberry Pi mittels 3,5 mm Klinkekabels abgegriffen und z.B. zu einem Paar Aktivboxen weitergeleitet werden. Sollten weder DVI noch HDMI kompatible Displays verfügbar sein, könnte man im letzten Schritt über die Chinch Buchse einen alten Röhrenfernseher anschließen. 10 3.2 Anschluss des Raspberry Pi 3.1.5 Weitere Komponenten Je nach Einsatzzweck kann es erforderlich sein, weitere Komponenten zu verwenden. Aufgrund der Tatsache, dass der 5V Eingang des Raspberry Pi (Modell A und B) mit einer 1,1 Ampere Polyfuse abgesichert ist [20] (S.1, oben, F1), welches den gesamten Raspberry Pi versorgt wird schnell klar, dass die beiden USB Ports nicht wie sonst 500 mA pro Port liefern können. Daher müssen Geräte mit höherem Strombedarf (USB Festplatten, größere USB Sticks, etc) an einem aktiven USB Hub betrieben werden, um zum einen die Anzahl der verfügbaren USB Anschlüsse zu erhöhen und zum anderen auch Geräte mit erhöhter Leistungsaufnahme sicher am Raspberry Pi betreiben zu können. Beim Modell B+ ist, insbesondere mit der Verwendung eines 2 Ampere Netzteils, die Problematik zumindest bei größeren USB Sticks und WLAN Dongles behoben wurden. Für besonders energiehungrige Endgeräte empfiehlt sich allerdings auch hier ein aktiver USB Hub. Weiterhin werden für die erste Inbetriebnahme ein aktueller Windows Rechner mit SD Karten Lesegerät und Internetzugriff vorausgesetzt um die SD Karte vorzubereiten. 3.2 Anschluss des Raspberry Pi Für den weiteren Verlauf des Dokumentes wird vorausgesetzt, dass die angegebenen Komponenten vorhanden und der Raspberry Pi angeschlossen, allerdings stromlos und ohne SD Karte bereit steht. 3.3 Raspbian Das bereits erwähnte Raspbian ist die Standard Distribution für den Raspberry Pi. Es handelt sich dabei um ein Debian Derivat, welches den Anforderungen und der Architektur des ARMv6 Prozessors des Einplatinen Computers angepasst wurde. Zusätzlich zu dem reinen Betriebssystem werden auch viele der unter Debian verfügbaren Software Pakete über den Paketmanager apt mit den entsprechenden Anpassungen angeboten. Um Raspbian auf der SD Karte zu installieren bieten sich zwei Möglichkeiten an. Zum einen die Verwendung des sogenannten noobs Systems der Raspberry Pi Foundation oder das bitweise Kopieren eines fertigen Images. 3.4 Installation mittels Image Die „traditionelle“ Art ein Betriebssystem per Image zu installieren ist auch nach der Einführung des noobs Systems weiterhin beliebt. Dies ist darin begründet, dass diese Art der Installation relativ schnell funktioniert. Weiterhin lassen sich auf gleichem Weg Backups von vorhandenen Installationen erstellen und wiederherstellen. Zu guter Letzt ist es auch für weniger bekannte Distributionen ohne Integration in noobs die einzige Möglichkeit diese für die Nutzung auf dem Raspberry Pi vorzubereiten. 11 3 Grundlagen und Installation 3.4.1 Image downloaden Um das Raspbian Image zu installieren, müssen wir es erst von der Website der Raspberry Pi Foundation herunterladen. Man findet es unter der Adresse http://www.raspberrypi. org/downloads/. Dort kann man sich entscheiden, ob man das Image von Raspbian per direktem HTTP Download oder per Torrent erhalten möchte. Für die meisten Einsatzzwecke sollte der Download als ZIP Datei die geeignete Wahl sein. In dieser Arbeit wird das aktuelle Image vom Juni 2014 verwendet (Release 20.06.2014, Kernel 3.12, 788 MB). Nach dem erfolgreichen Download muss die Datei mittels einem geeigneten Werkzeug (z.B. 7-zip: http://www.7-zip.org/) entpackt werden. Bei der resultierenden, fast 3 GB großen Datei mit der Endung „.img“ handelt es sich um die besprochene Image Datei, welche bitweise die Kopie des Raspbian Betriebssystems enthält. Diese Datei wird in den nächsten Schritten auf die vorhandene SD Karte kopiert. 3.4.2 Formatieren Um das Image auf die SD Karte kopieren zu können, muss deren Inhalt zuerst gelöscht, die Karte also formatiert werden. Dies ist bei der Verwendung einer neuen und leeren SD Karte nicht notwendig, da die Karte im nächsten Schritt bitweise überschrieben wird. Beim Überschreiben werden normalerweise zwei Partitionen angelegt: Eine FAT32 Partition wie man sie auch bei USB Sticks kennt, sowie eine EXT Partition unterschiedlicher Version. Das EXT Dateisystem entstammt dem Linux Bereich und ist unter Windows nicht lesbar. Will man nun also eine bereits für den Raspberry Pi verwendete SD Karte ein weiteres Mal neu beschreiben, oder ein Backup wiederherstellen, so erscheint die ggf. mehrere GB große SD Karte als nur knapp 56 MB großer, FAT32 formatierter USB Stick im Dateisystem. Durch die Formatierung kann das ursprüngliche Format wiederhergestellt und anschließend mit der vollen Größe auch ein Image wieder zurück gespielt werden. Um unter Windows die SD Karte korrekt zu formatieren, sollte man nicht das Windows eigene Tool verwenden, sondern den SD Formatter der SD Association. Man kann dieses Tool kostenlos unter https://www.sdcard.org/downloads/formatter_4/ per Klick auf „Download SD Formatter for Windows“ herunterladen. Nachdem man die EULA angenommen hat, startet der Download der wenigen MB großen ZIP Datei. Sobald man die enthaltene Setup Datei entpackt und das Tool installiert hat, startet man dieses einfach. Das Tool selbst ist relativ einfach gehalten: Unter „Drive“ wählt man das korrekte Laufwerk aus und per Klick auf „Format“ startet man die Formatierung der SD Karte. Dabei ist jedoch darauf zu achten, dass das Tool alle Wechselmedien unter „Drive“ auflistet. Man muss also darauf achten wirklich seine SD Karte zu formatieren, und nicht versehentlich einen USB Stick mit wichtigen Daten. Bevor man allerdings den Vorgang startet, sollte man unter „Option“ noch eine Anpassung vornehmen. In jedem Fall, besonders bei der Vorbereitung einer SD Karte für die Verwendung von noobs, sollte man hier das „Format Size Adjustment“ auf „On“ stellen und den Dialog per Klick auf „OK“ verlassen, sowie die Formatierung per Klick auf „Format“ starten. 12 3.4 Installation mittels Image Abbildung 3.1: SD Formatter Abbildung 3.2: SD Formatter Optionen 13 3 Grundlagen und Installation Nachdem zwei weitere Sicherheitsabfragen bestätigt wurden, beginnt der Vorgang und endet mit einer Übersicht über die tatsächliche Größe der SD Karte. Der Vorgang ist damit abgeschlossen und das Tool kann beendet werden. 3.4.3 Image kopieren Um das bereits heruntergeladene Image auf die nun vorbereitete SD Karte zu kopieren, benötigen wir ein weiteres Tool, die Freeware Win32 Disk Imager. Dieses Werkzeug kann man unter der URL http://sourceforge.net/projects/win32diskimager/ per Klick auf „Download unamed sequel here“ herunterladen, installieren und anschließend starten. Abbildung 3.3: Win32 Disk Imager Wie bereits beim SD Formatter gibt es auch hier ein Feld zur Auswahl des korrekten Wechsellaufwerkes („Device“). Es ist auch dieses Mal genaustens darauf zu achten die SD Karte und nicht einen anderen Wechseldatenträger, wie z.B. einen USB Stick auszuwählen, da im nächsten Schritt alle Dateien auf diesem überschrieben werden. Nachdem die SD Karte als Laufwerk ausgewählt wurde, wählen wir per Klick auf den Dateiordner das vorher heruntergeladene Raspbian Image aus (hier: 2014-06-20wheezy-raspbian.img). Nach dem Klick auf „Öffnen“ ist das Tool dann auch schon fertig konfiguriert. Per Klick auf „Write“ beginnt nach einer weiteren Sicherheitsabfrage der Schreibvorgang. Nach Abschluss des selbigen kann die SD Karte ausgeworfen, aus dem Lesegerät entfernt und in den Raspberry Pi eingesetzt werden. Dies schließt das Kopieren des Raspbian Image auf die SD Karte ab. Der Raspberry Pi kann nun an die Stromversorgung angeschlossen werden um Raspbian zu booten. 3.4.4 Backup und Wiederherstellung Wie bereits eingangs erwähnt kann das Win32 Disk Imager Tool auch dazu verwendet werden, Backups einer bestehenden Raspbian Installation anzufertigen, bzw diese Wiederherzustellen. 14 3.5 Installation mittels noobs Wollen wir ein Backup erstellen, so setzen wir die SD Karte in das Lesegerät ein und starten den Win32 Disk Imager. Anders als beim bisherigen Vorgang wählen wir diesmal über den Dateiordner kein fertiges Image aus, sondern geben im entsprechenden Dialogfeld einen eigenen, nicht existierenden Dateinamen ein, z.B. „RaspbianBackup.img“. Nach dem Klick auf „Öffnen“ sind wir wieder im Hauptdialog und können durch Klick auf den Button „Read“ das Auslesen der SD Karte in die neu angelegte Datei starten. Die Datei wird später die Größe der verwendeten SD Karte haben und kann ohne weitere Änderungen auch nur auf eine solch große, oder größere SD Karte wiederhergestellt werden. Zur Wiederherstellung gehen wir ähnlich vor wie beim Kopieren des Raspbian Images: Wir führen zuerst eine Formatierung der SD Karte wie unter 3.4.2 angegeben durch, anschließend kopieren wir das Backup Image anstelle des Raspbian Images auf die SD Karte wie unter 3.4.3 beschrieben. 3.5 Installation mittels noobs Um den Einstieg in die Welt des Raspberry Pi zu vereinfachen erfand die Raspberry Pi Foundation die sogenannte noobs oder New Out Of Box Software. Es handelt sich dabei um einen Installationsassistenten welcher, nachdem er auf der SD Karte installiert wurde, den Boot des Raspberry Pi und dort die Auswahl des gewünschten Betriebssystems erlaubt. Erst dann findet die eigentliche Installation statt. Noobs gibt es auch vorinstalliert auf Micro SD Karten samt Adapter im Handel zu kaufen, um den Einstieg mit dem Raspberry Pi zu einer echten „Plug and Play“ Lösung zu machen. Sollte der Installer jedoch beschädigt werden, man noobs selbst auf einer leeren SD Karte installieren wollen oder andere Probleme auftreten, ist es gut die wenigen Schritte bis zur Einrichtung und Nutzung dieses Systems zu kennen, welche nachfolgenden aufgelistet werden. 3.5.1 noobs downloaden Wie auch bei der direkten Installation von Raspbian muss das noobs Paket erst von der Raspberry Pi Website heruntergeladen werden. Dazu navigieren wir zu http:// www.raspberrypi.org/downloads/ und wechseln zum Eintrag „noobs“. Die New Out Of Box Software gibt es in zwei Versionen: Full und Lite. Bei der Full Version sind alle wichtigen Betriebssysteme bereits auf der SD Karte hinterlegt, so dass eine Offline Installation nach dem Download möglich ist. Die Lite Version benötigt, da nur der Installer auf der Karte untergebracht ist, bei der Installation eine Internetverbindung um die Images herunterzuladen. Je nach Einsatzzweck downloaden wir die passende Version per Klick auf den „Download ZIP“ Button. 3.5.2 Formatieren Wie bereits bei 3.4.2 erklärt muss nun auf gleichem Wege die SD Karte formatiert werden. Nachdem dies abgeschlossen ist, kann noobs selbst im nächsten Schritt auf die SD 15 3 Grundlagen und Installation Karte kopiert werden. 3.5.3 noobs kopieren Abbildung 3.4: noobs nach dem Entpacken auf die SD Karte Nachdem wir die SD Karte vorbereitet haben, entpacken wir den Inhalt des heruntergeladenen Paketes direkt ins Hauptverzeichnis der SD Karte unter Beibehaltung der Datei- und Ordnerstruktur. Auch hierbei wird empfohlen einen bewährten Entpacker wie z.B. 7-zip (http://www.7-zip.org/) dem Windows eigenem Tool vorzuziehen. Anschließend kann die SD Karte sicher entfernt und schließlich in den Raspberry Pi eingesetzt werden. Damit ist noobs erfolgreich eingerichtet und wir können den Raspberry Pi an die Stromversorgung anschließen, um Raspbian zu installieren. 3.5.4 Raspbian mit noobs installieren Nach dem Boot des Raspberry Pi erscheint die Oberfläche von noobs, welche uns die Möglichkeit gibt, zum einen die Sprachoptionen und Tastatureinstellungen zu ändern, sowie zum anderen ein Betriebssystem zur Installation auszuwählen und den Prozess zu starten. Da wir, wie auch in der manuellen Methode, Raspbian installieren wollen, aktivieren wir diesen Eintrag mit einem Klick in das entsprechende Kästchen und klicken anschließend auf „Install“. Nach einer Sicherheitsabfrage beginnt die Installation die nun einige Zeit dauern kann. Nach dem Abschluss der Einrichtung informiert noobs den Nutzer mittels Dialogbox. Nach dem Klick auf „OK“ startet der Raspberry Pi neu und bootet Raspbian. 3.5.5 Vorteile von noobs Der Vorteil der Installation nach dieser Methode liegt zum einen darin, dass die Sprachoptionen und Tastatureinstellungen welche in noobs eingegeben wurden nach Raspbian 16 3.5 Installation mittels noobs Abbildung 3.5: Installation von Raspbian unter noobs übernommen werden, zum anderen aber auch darin, dass man jederzeit beim Booten des Raspberry Pi die Shift Taste gedrückt halten kann, um das noobs Menü erneut aufzurufen. Damit hat man die Möglichkeit Einstellungen zu ändern, wie auch ohne den Einsatz eines PCs andere Betriebssysteme zu installieren. Weiterhin ermöglicht noobs die gleichzeitige Installation mehrerer Betriebssysteme auf einer SD Karte und dient als Bootmanager. 17 4 Konfiguration von Raspbian Nachdem der Raspberry Pi im letzten Kapitel zum ersten Mal in Betrieb genommen wurde, muss nun die Grundkonfiguration erfolgen. Dies bedeutet zum Beispiel das Tastaturlayout, die Zeitzone und die Internationalisierungsoptionen einzustellen. Anschließend werden die Schritte zur Installation neuer Software und Update bestehender, sowie dem Upgrade der Firmware beschrieben. Am Ende dieses Kapitels werden alle notwendigen Vorbereitung zur Nutzung der GPIO Schnittstelle in verschiedenen Programmiersprachen getroffen sein. 4.1 Erster Boot Nachdem Raspbian nun auf der SD Karte installiert und der Raspberry Pi nun bootet, muss ersteres nun in einer Grundkonfiguration für die Verwendung beim Nutzer eingerichtet werden. Im Idealfall wird dies direkt am Raspberry Pi durch die Verwendung von Maus, Tastatur und Bildschirm erledigt. Sollte dies nicht möglich sein, bzw. eine Einrichtung headless, also ohne Bildschirm über das Netzwerk erfolgen, so kann man dies unter Verwendung eines SSH Tools wie z.B. PuTTY (http://www.chiark. greenend.org.uk/~sgtatham/putty/download.html) tun. Die Login Daten bei Raspbian sind, wie auch auf der Downloads (http://www.raspberrypi.org/downloads/) Seite vermerkt, Nutzer: pi sowie Passwort: raspberry. Dabei ist zu beachten, dass beim direkten Login über die Tastatur, so diese nicht von noobs auf QWERTZ umgestellt wurde, im QWERTY Format Eingaben entgegen nimmt, also u.a. die Position von Z und Y auf der Tastatur vertauscht ist. 4.1.1 raspi-config Nachdem der Raspberry Pi zum ersten Mal gebootet ist, erscheint das Software Configuration Tool, auch bekannt als raspi-config. Sollte man diese Schritte in einer headless Installation nachvollziehen wollen, so muss man nach Login über PuTTY das Tool manuell durch die Eingabe von sudo raspi-config starten. raspi-config ermöglicht viele Änderungen und Grundeinstellungen. So kann man in diesem Werkzeug z.B. die Verteilung des gemeinsam von CPU und GPU genutzten RAMs ändern, das Nutzerpasswort ändern, den Boot in die grafische Benutzeroberfläche aktivieren oder die Raspberry Pi Kamera aktivieren. Alle Hardwarenahen Änderungen, wie z.B. Übertaktungseinstellungen werden vom Tool in Form der config.txt [8] Datei in der FAT32 Partition der SD Karte abgelegt und sind auch manuell von einem normalen Windows PC änderbar und damit auch eine Wiederherstellung bei z.B. 19 4 Konfiguration von Raspbian Abbildung 4.1: raspi-config fehlerhaft konfigurierten Übertaktungseinstellungen möglich. Im Normalfall empfiehlt sich allerdings die Verwendung dieses Tools um Fehler zu vermeiden. Die Navigation in raspi-config erfolgt über folgende Tastenkombinationen: Pfeiltasten Hoch, Runter Page UP, Page Down Enter ESC Schnell Hoch, Schnell Runter Menü betreten Menü verlassen Leertaste Menüpunkt markieren, bei [ ] Auswahl Wir beginnen die Konfiguration im Menü 8 Advanced Options, in dem wir unter Punkt A3 Memory Split den Anteil der Grafikkarte am Gesamtarbeitsspeicher des RPi festlegen. Im Normalfall reicht die Standardeinstellung von 64 MB. Bei sogennaten Headless Konfigurationen, also dem Betrieb des RPi ohne Bildschirm, Maus und Tastatur als Server, kann dort der Anteil der GPU auch auf 16 MB gesenkt werden. Der Name des RPi im Netzwerk kann unter A2 Hostname festgelegt werden. Es empfiehlt sich dort einen sprechenden Namen einzugeben und nicht alle RPi mit dem Standardnamen „raspberrypi“ zu belassen. Unter 7 Overclock: Kann man die Übertaktung des Raspberry Pi einstellen, um eine Leistungssteigerung zu erhalten. Die einzigen beiden sinnvollen Parameter sind dabei None oder Turbo: Mit None betreibt man den Raspberry Pi innerhalb der Standardparameter, mit Turbo erhält man eine sehr starke Übertaktung und Steigerung u.a. der CPU Geschwindigkeit von 700 MHz auf 1 GHz. Dennoch bleibt bei der Nutzung der Turbo Einstellung die Garantie erhalten, da die CPU automatisch diese Übertaktung zurückregelt, sobald die Temperatur der CPU 85 Grad Celsius erreicht [23]. Diese Einstellung ist allerdings auf Grund von Fertigungstoleranzen nicht auf jedem Raspberry Pi zu erreichen. Sollte es Probleme geben, so kann man durch Halten der Shift Taste beim Boot 20 4.1 Erster Boot des Raspberry Pi in den abgesicherten Modus wechseln um diese Einstellung zu ignorieren. Sollte man die Raspberry Pi Kamera nutzen wollen, so muss vor dem Anschluss dieses Moduls die Unterstützung für diese mit der Einstellung 5) Enable Camera aktiviert werden. Danach kann man die Kamera an den ausgeschalteten Raspberry Pi anschließen und nach einem erneuten Start nutzen. Um den Raspberry Pi sinnvoll in Deutschland zu nutzen, stellen wir nun unter 4 Internationalization Options die Internationalisierungsoptionen auf unseren Standort und unsere Sprache um. Wir beginnen mit I1 Change Locale und wählen im erscheinenden Menü den Punkt [*] de_DE.UTF-8 UTF-8 aus, bestätigen die Wahl und beantworten die Frage nach dem Default locale mit de_DE.UTF-8. Nun werden die Standortparameter erstellt, was einen kurzen Moment dauern kann. Als nächstes ändern wir die Zeitzone unter dem Punkt I2 Change Timezone in dem wir zuerst als Geographic area Europe und dann als Timezone Berlin angeben. Der Raspberry Pi bezieht sich seine Zeitinformationen per NTP über das Netzwerk und stellt die Uhr direkt korrekt ein. Abschließend muss die Einstellung der Tastatur auf das deutsche Schema angepasst werden. Der korrekte Unterpunkt dafür ist I3 Change Keyboard Layout. • Generic 105-key (Intl) PC • Other • German • German • The default for the keyboard layout • No compose key • <No> Anschließend wird die neue Keymap erstellt und mit dem nächsten Login aktiv. Um beim nächsten Bootvorgang nicht wieder in der Kommandzeile zu landen, sondern direkt zum Desktop zu booten, aktivieren wir nun unter 3 Enable Boot to Desktop/Scratch die Option Desktop Log in as user ’pi’ at the graphical desktop. Aus Sicherheitsgründen empfiehlt es sich im vorletzten Schritt das Passwort des Standardnutzers pi unter 2 Change User Password zu ändern. Zu guter Letzt möchten wir, dass der Raspberry Pi nicht nur die knapp 3 GB Speicher, welche durch das Image bereitgestellt wurden nutzt, sondern die gesamte SD Karte belegt. Daher führen wir als letzte Aktion 1 Expand Filesystem aus. Mit der Bestätigung von Finish im Hauptmenü beenden wir raspi-config und beantworten die Frage nach dem gewünschten Reboot mit Yes. Mit dem Neustart wird das Dateisystem angepasst und der Raspberry Pi bootet schließlich zur grafischen Benutzeroberfläche, dem Desktop. 21 4 Konfiguration von Raspbian Abbildung 4.2: Raspbian Desktop 4.2 WLAN Zugriff / eduroam Sollte ein Zugriff auf das eduroam WLAN benötigt werden, muss der Raspberry Pi zuvor mit einem USB WLAN Dongle ausgestattet werden. Eine entsprechende Kompatibilitätsliste geeigneter Modelle kann unter http://elinux.org/RPi_USB_Wi-Fi_Adapters gefunden werden. Anschließend kann unter Nutzung des Wifi Config Tools des RPi unter dem Punkt „Manage Networks“ und „Add“ das WLAN eduroam hinzugefügt werden: Tabelle 4.1: Einstellungen für eduroam Einstellung Wert SSID eduroam Authentication WPA2-Enterprise (EAP) Encryption CCMP EAP method PEAP Identity [email protected] Password Passwort CA certificate /etc/wpa_supplicant/deutsche-telekom-root-ca-2.crt Inner auth EAP-MSCHAPV2 Anschließend kann über den Reiter „Current Status“ und die Schaltfläche „Connect“ eine Verbindung hergestellt werden. 22 4.3 Updates 4.3 Updates Nachdem wir nun die Grundkonfiguration des Raspberry Pi durchgeführt haben, ist es zwingend erforderlich, zum einen die neuste Firmware wie auch Software Updates zu installieren und die grundlegende Arbeit mit dem Paketmanager apt zu erlernen. 4.3.1 rpi-update Das Firmware Paket besteht aus dem Kernel von Raspbian, dem GPU Bootloader sowie den benötigten Modulen für den Kernel. Sobald der Raspberry Pi mit Strom versorgt wird sucht die GPU automatisch auf der FAT32 Partition der SD Karte nach einem passenden Bootloader. Mit diesem kann die Grafikeinheit dann die CPU und die restliche Peripherie initialisieren und schließlich den Kernel booten. Die Firmware auf einem aktuellen Stand zu halten ist wichtig, da man nur auf diese Art von Verbesserungen wie z.B. verbesserter Hardwareunterstützung oder Fehlerbeseitigung profitieren kann. Die aktuelle Kernelversion kann man sich mit dem Kommando uname -a anzeigen lassen. Dazu verwenden wir das Tool LXTerminal welches in der oberen, linken Ecke des Desktops abgelegt ist. Als Beispiel sei hier die Ausgabe unseres neu installierten Raspbian angegeben: Linux raspberrypi 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux Wie man erkennen kann, handelt es sich hierbei um den Kernel Version 3.12.22+ welcher am 18. Juni 2014 gegen 18:29:58 kompiliert wurde. Die Zahl #691 ist die Versionsnummer des Kernels. Die Version der GPU Firmware lässt sich durch das Kommando /opt/vc/bin/vcgencmd version herausfinden: Jun 18 2014 18:46:58 Copyright (c) 2012 Broadcom version 1a6f79b82240693dcdb9347b33ab16f656b5f067 (clean) (release) Um nun ein Update auf die neuste Version durchzuführen, reicht das Kommando sudo rpi-update. Da es sich hierbei um ein Kommando handelt welches tiefgreifend in wichtige Bereiche des Linux Betriebssystems eingreift, zu welchen unser Standardnutzer pi keinen Zugriff hätte, müssen wir das Kommando sudo vorstellen. Durch dieses Kommando wird der nachfolgende Befehl (hier: rpi-update) mit den Rechten des Linux Administrators, root durchgeführt: sudo rpi-update *** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS *** Performing self-update % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 135 100 135 0 0 227 0 --:--:-- --:--:-- --:--:-- 299 100 7037 100 7037 0 0 8049 0 --:--:-- --:--:-- --:--:-- 8049 *** Relaunching after update 23 4 Konfiguration von Raspbian *** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS and Dom *** We're running for the first time *** Backing up files (this will take a few minutes) *** Backing up firmware *** Backing up modules 3.12.22+ *** Downloading specific firmware revision (this will take a few minutes) % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 168 100 168 0 0 350 0 --:--:-- --:--:-- --:--:-- 465 100 21.2M 100 21.2M 0 0 902k 0 0:00:24 0:00:24 --:--:-- 525k *** Updating firmware *** Updating kernel modules *** depmod 3.12.25+ *** Updating VideoCore libraries *** Using HardFP libraries *** Updating SDK *** Running ldconfig *** Storing current firmware revision *** Deleting downloaded files *** Syncing changes to disk *** If no errors appeared, your firmware was successfully updated to 774062f644162e209214bc2d3a7ba79fdf765ba3 *** A reboot is needed to activate the new firmware Um die Installation der neuen Firmware abzuschließen, müssen wir den Raspberry Pi neustarten. Dies geschieht entweder rechts unten im Desktop über die Abmelden Schaltfläche, den Shutdown Icon auf dem Desktop oder mittels Kommandozeile über die Befehle sudo shutdown -h now zum herunterfahren oder sudo shutdown -r now zum neustarten. Nachdem wir nun die Firmware des Raspberry Pi aktualisiert haben, möchten wir uns im nächsten Schritt um seine Software kümmern. 4.3.2 apt-get APT ist der sogenannte Paket Manager unter dem von Debian abstammenden Raspbian Linux. Pakete können die unterschiedlichsten Arten von Software, Libraries und anderen Abhängigkeiten enthalten. Der Paket Manager selbst verwaltet die Installation sowie die benötigten Grundlagen / Abhängigkeiten um die gewünschte Software auf dem Rechner zu betreiben. Weiterhin können über den Paket Manager nicht nur Software installiert und gelöscht, sondern auch aktualisiert werden. Unter der Nutzung von LXTerminal führen wir den Befehl sudo apt-get update aus. Damit lädt sich der Paket Manager die aktuellen Paketlisten herunter um zu wissen, welche Software in welcher Version für den Nutzer zur Verfügung steht. Mit dem Kommando sudo aptget upgrade starten wir schließlich das Software update. Der Paket Manager berechnet die Abhängigkeiten, benötigten neuen Pakete und verlangt schließlich die Bestätigung 24 4.4 Einrichtung Hardware seitens des Nutzers. sudo apt-get upgrade Paketlisten werden gelesen... Fertig Abhängigkeitsbaum wird aufgebaut. Statusinformationen werden eingelesen.... Fertig Die folgenden Pakete werden aktualisiert (Upgrade): cups-bsd cups-client cups-common dbus dbus-x11 gnupg gpgv libcups2 libcupsimage2 libdbus-1-3 libjpeg8 libsmbclient libwbclient0 libxml2 openssh-client openssh-server python-picamera python-rpi.gpio python3-picamera python3-rpi.gpio rpi-update samba-common smbclient ssh tzdata 25 aktualisiert, 0 neu installiert, 0 zu entfernen und 0 nicht aktualisiert. Es müssen 13,2 MB an Archiven heruntergeladen werden. Nach dieser Operation werden 100 kB Plattenplatz zusätzlich benutzt. Möchten Sie fortfahren [J/n]? Nachdem diese Frage mit J und der Eingabe von Enter bestätigt wurde, führt der Raspberry Pi die Updates durch. Danach empfiehlt sich ein Neustart von Raspbian. Die Installation von neuen Paketen funktioniert mit dem Kommando sudo apt-get install <Paketname> respektive die Entfernung mit sudo apt-get remove <Paketname>. Diese Kommandos werden wir gleich u.a. bei der Installation von wiringpi2 verwenden. 4.4 Einrichtung Hardware Wie bereits erwähnt, verfügt der Raspberry Pi über eine GPIO Schnittstelle. Die 26 (Modell A,B) respektive 40 Pins (Modell B+) lassen sich je nach Programmierung entweder als digitaler Ein- oder Ausgang verwenden um die unterschiedlichsten Aufgaben zu erfüllen. Einige dieser Pins verfügen noch über spezielle Alternativfunktionen, wie z.B. einen I2C Bus, einen SPI Bus oder einen Universal asynchronous receiver/transmitter (UART) in Form einer RS-232 seriellen Schnittstelle. Die ersten beiden Funktionen sind standardmäßig deaktiviert um dem Nutzer mehr freie GPIO Pins zu bieten, die letztere wird aktiv als serielle Konsole von Raspbian verwendet. Wenn man diese Schnittstellen und Funktionen also für eigene Projekte verwenden möchte, muss man sie erst aktivieren respektive aus der Nutzung anderer Dienste entfernen. 4.4.1 Vorbereitung des I²C / SPI Bus Um die I2C bzw SPI Funktionen der GPIO Pins zu verwenden, führen wir zunächst ein Update des Paket Managers mit sudo apt-get update durch und installieren anschließend mit sudo apt-get install i2c-tools python-smbus die Pakete für die I2CTools sowie die Python Bibliothek für den SPI Bus. Nachdem dies erfolgt ist, müssen wir die Module für I2C und SPI von der Blacklist entfernen. Die Blacklist verhindert dass diese Module beim Start geladen und damit 25 4 Konfiguration von Raspbian die alternativen Funktionen auf der GPIO zur Verfügung stehen. Um dies zu bewerkstelligen können wir entweder mittels LXTerminal und vi über Kommandozeile die entsprechenden Dateien editieren, oder per LXTerminal mit dem Kommando sudo leafpad den Texteditor Leafpad mit root Rechten starten um anschließend die sonst schreibgeschützten Dateien zu editieren. Im ersten Schritt öffnen wir die Datei /etc/modprobe.d/raspi-blacklist.conf und kommentieren die beiden blacklist Befehle für die Module spi-bcm2708 und i2c-bcm2708 mittels vorangestelltem # Zeichen aus: # blacklist spi and i2c by default (many users don't need them) #blacklist spi-bcm2708 #blacklist i2c-bcm2708 Danach speichern wir die Datei. Als nächstes müssen wir die beiden Module in /etc/modules vermerken, damit diese auch beim Start des RPi geladen werden. Dazu hängen wir einfach nach dem letzten Eintrag in der genannten Datei die folgenden Zeilen an: i2c-bcm2708 spi-bcm2708 i2c-dev Das Ergebnis sieht wie folgt aus: # # # # # /etc/modules: kernel modules to load at boot time. This file contains the names of kernel modules that should be loaded at boot time, one per line. Lines beginning with "#" are ignored. Parameters can be specified after the module name. snd-bcm2835 i2c-bcm2708 spi-bcm2708 i2c-dev Abschließend müssen wir nur noch den Standardnutzer pi zu den entsprechenden Linux Gruppen hinzufügen, damit er die Berechtigung zur Nutzung dieser Dienste erhält. Standardmäßig sind die Berechtigungen für die SPI und GPIO Gruppe schon erteilt ( groups pi zeigt die zugeteilten Gruppen an). Daher müssen wir nur noch mit dem Befehl sudo adduser pi i2c den Nutzer pi die Rechte für die Gruppe I2C geben. Die durchgeführten Änderungen werden erst nach einem Neustart aktiv. 4.4.2 Vorbereitung der seriellen Schnittstelle Da im Standardfall die serielle Schnittstelle des RPi von Raspbian als Terminal genutzt wird, kann diese nicht direkt dazu verwendet werden um z.B. einen Global Positio- 26 4.5 Einrichtung Software ning System (GPS) Empfänger oder eine Microcontroller Unit (MCU) wie den Arduino anzuschließen. Um diese Funktionalität zu entfernen müssten wir aus der Datei /boot/cmdline.txt die Einträge console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 entfernen sowie in der Datei /etc/inittab den Eintrag T0:23:respawn:/sbin/getty -L ttyAMA 0 115200 vt100 durch voranstellen eines # Zeichens auskommentieren [10]. Da diese Änderung jedoch so häufig durchgeführt wurde und ins besondere Fehler in der /boot/cmdline.txt zu einem nicht bootfähigen System führen können, hat der Nutzer lurch auf Github das Programm rpi-serial-console (https://github.com/lurch/ rpi-serial-console) geschrieben, welches diese Änderung vollautomatisch durchführt. Die Installation erfolgt mit den Befehlen sudo wget https://raw.github.com/lurch/rpi-serial-console/master/rpi-serial-console -O /usr/bin/rpi-serial-console Enter sudo chmod +x /usr/bin/rpi-serial-console Enter was dafür sorgt, dass das Programm nach /usr/bin/rpi-serial-console heruntergeladen und anschließend ausführbar gemacht wird. Anschließend können wir mit sudo rpi-serial-console disable die serielle Konsole von Raspbian deaktivieren. Mit dem Parameter enable diese im Übrigen wieder aktiviert und mit status der aktuelle Zustand der UART abgefragt werden. Wie auch bei den Änderungen für I2C und SPI werden die Änderungen erst nach einem Neustart des RPi aktiv. 4.5 Einrichtung Software Nachdem nun die Hardware soweit vorbereitet ist, beginnen wir damit die entsprechenden Schnittstellen zur Software zu installieren. Als wichtigstes wäre da das Framework wiringpi2 (http://wiringpi.com/), welches die Schnittstelle zwischen Hardware und weiteren, spezialisierten Libraries für unterschiedliche Programmiersprachen wie Python oder Java bereitstellt. 4.5.1 Installation von wiringpi2 Um wiringpi2 zu installieren, wechseln wir mit dem Kommando cd ~ ins Heimverzeichnis unseres Nutzers pi. Anschließend laden wir mittels git clone git://git.drogon .net/wiringPi den Quellcode der Software herunter und wechseln mit cd wiringPi/ in das entsprechende Verzeichnis. Mit dem Kommando ./build starten wir schließlich den Build Prozess, sorgen also dafür dass das Programm kompiliert und installiert wird. Dies kann einige Minuten dauern. Nach dem Abschluss des Vorgangs kann man als ersten Test mit dem Kommando gpio -v Informationen über die Software, sowie den verwendeten RPi Type (Model B, Rev.2) ausgeben lassen. gpio version: 2.20 Copyright (c) 2012-2014 Gordon Henderson This is free software with ABSOLUTELY NO WARRANTY. 27 4 Konfiguration von Raspbian For details type: gpio -warranty Raspberry Pi Details: Type: Model B, Revision: 2, Memory: 512MB, Maker: Sony Und schließlich mittels gpio readall alle GPIO Pins auf ihren Status abfragen. +-----+-----+---------+------+---+-Model B2-+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5V | | | | 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 0 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 | | 10 | 12 | MOSI | ALT0 | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 | | 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | ALT0 | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | ALT0 | CE1 | 11 | 7 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | 28 | 17 | GPIO.17 | IN | 0 | 51 || 52 | 0 | IN | GPIO.18 | 18 | 29 | | 30 | 19 | GPIO.19 | IN | 0 | 53 || 54 | 0 | IN | GPIO.20 | 20 | 31 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+-Model B2-+---+------+---------+-----+-----+ 4.5.2 Installation von wiringpi2-python Als Bindeglied zwischen wiringpi2 und der Programmiersprache Python dient die Library wiringpi2-python (https://github.com/Gadgetoid/WiringPi2-Python). Um diese einzurichten, müssen wir vorher noch einige Erweiterungen für Python installieren: sudo apt-get update Enter sudo apt-get install python-setuptools python-dev Enter Anschließend erfolgt die eigentliche Installation: cd ~ Enter git clone https://github.com/Gadgetoid/WiringPi2-Python.git Enter cd WiringPi2-Python/ Enter sudo python setup.py install Enter Um die Funktionalität der Library zu testen möchten wir, wie auch mit gpio -v ermittelt, die Revision unseres RPi Boards anzeigen lassen - diesmal allerdings in Python. 28 4.5 Einrichtung Software Wir beginnen also in dem wir mit dem Befehl sudo python die Umgebung starten. Anschließend importieren wir die wiringpi2 Library mittels import wiringpi2 und lassen uns die Revision des Boards ausgeben wiringpi2.piBoardRev(). Als Ausgabe erhalten wir wieder >> 2. Damit war der Test erfolgreich und wir können Python mit exit() verlassen. 4.5.3 Test des SPI Bus (Optional) Um Funktionalität des SPI Bus zu testen, müssen wir die GPIO Pins 9 (MISO) und 10 (MOSI) kurzschließen. Anschließend muss das Testskript heruntergeladen, kompiliert und ausgeführt werden: cd ~ Enter wget http://www.nico-maas.de/spidev_test.c Enter gcc spidev_test.c -o spidev_test Enter ./spidev_test Enter Sofern die Ausgabe nicht ausschließlich aus Nullen besteht, war der Loopback Test erfolgreich: spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz) FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DE AD BE EF BA AD F0 0D Damit wären alle Vorbereitungen abgeschlossen und wir können mit der Nutzung des Raspberry Pi beginnen. 29 5 GPIO Schnittstelle Nachdem alle Vorbereitungen zur Nutzung der GPIO Schnittstelle in den letzten Kapiteln getroffen wurden, wird das Ziel in diesem Kapitel sein, mehr über diese Schnittstelle und deren Funktionen zu lernen. Es werden die grundlegenden Sicherheitshinweise im Umgang mit der Schnittstelle erörtert, wie auch die Funktion der einzelnen Bus Systeme. Zum Schluss wird das Erweiterungsboard, welches für diese Arbeit entwickelt wurde, erklärt und mittels einer Testsoftware in C auf Funktionalität getestet. 5.1 Aufbau Die GPIO Schnittstelle ist eine der besonderen Eigenschaften, welche den Raspberry Pi von einem normalen PC unterscheidet. Durch diese Anschlüsse kann der RPi mit zahlreichen Sensoren, Aktoren und Schaltern verbunden werden, um eine Vielzahl von Einsatzzwecken zu ermöglichen. Zu diesem Zweck verfügt die GPIO Leiste über mehrere Arten von Pins: • Einfache GPIO Pins • GPIO Pins mit Zusatz- / Alternativfunktionen • 3,3 Volt / 5 Volt / Ground Anschlüsse Die genannten Pins können in nachfolgender Abbildung 5.1 eingesehen werden: Abbildung 5.1: GPIO Schnittstelle Raspberry Pi Modell A / B / B+ [11] Im vorangegangenen Kapitel 4 haben wir bereits die Alternativfunktionen einiger Pins erwähnt und diese auch für die spätere Nutzung aktiviert. Bevor wir uns aller- 31 5 GPIO Schnittstelle dings näher mit den Pins und deren Funktion beschäftigten, müssen wir uns zuerst mit den Einschränkungen des Raspberry Pi und dessen GPIOs vertraut machen. 5.2 Sicherheitshinweise 5.2.1 Logik Level Der Raspberry Pi arbeitet mit einem Logik Level von 3,3 Volt. Dies bedeutet, dass die interne Schaltung des Einplatinen Computers die Spannung 3,3 Volt als „HIGH“ oder „TRUE“ erkennt, während 0 V (Ground) als „LOW“ oder „FALSE“ interpretiert wird. Im Bereich der MCU (z.B. Arduino) und SoC (z.B. Raspberry Pi) sind die Verwendung von Spannungen im Bereich von 1,8 Volt, 3,3 Volt und 5 Volt üblich. Im Unterschied zu z.B. dem Arduino ist der Raspberry Pi allerdings keines Falls 5 Volt tolerant, was bedeutet, dass niemals mehr als 3,3 Volt direkt an einen der GPIO Pins angelegt werden dürfen, da sonst das SoC beschädigt werden könnte. 5.2.2 Sicherungen Der Raspberry Pi verfügt über eine 1,1 Ampere (Modell A und B), respektive 2 Ampere (Modell B+) starke Polyfuse welche direkt an den Micro USB Port der Spannungsversorgung angeschlossen ist. Die GPIO Pins selbst verfügen über keinerlei Schutz gegen Verpolung, Kurzschluss oder Überspannung. Daher sollten Änderungen an den GPIO Pins nur im ausgeschalteten / stromlosen Zustand des RPi gemacht werden. 5.2.3 Belastbarkeit der Pins / 3,3 Volt Schiene Die 3,3 Volt Versorgung des Raspberry Pi wurde ursprünglich so entworfen, das jeder der 17 Pins mit 3 mA belastet werden konnte, was eine Gesamtbelastbarkeit von 51 mA ergibt. Allerdings bezieht sich diese Bewertung nur darauf, wenn alle Pins genutzt werden. Prinzipiell ist jeder Pin in der Lage bis zu 16 mA belastet zu werden - solange die feste Gesamtlast 51 mA nicht überschreitet, weil sonst Schäden an der Hardware auftreten können [16]. Diese Zahlen beziehen sich ausschließlich auf die Raspberry Pi Modelle A und B, das neue Modell B+ erhielt eine neue Spannungsversorgung und stellt weitere GPIO Pins zur Verfügung. In wieweit dadurch die Versorgung der GPIO Pins verbessert wurde, ist noch nicht publiziert wurden. 5.2.4 Belastbarkeit der 5 Volt Schiene Die 5 Volt Versorgung wird beim Raspberry Pi Modell A und B durch eine 1,1 Ampere Polyfuse eingeschränkt, welche selbst ca. 100 mA Stromabfall bewirkt. Daher ist die Belastbarkeit durch die Differenz aus der Beschränkung der Polyfuse und dem Eigenbedarf des Raspberry Pi, sowie weiterer angeschlossener Geräte zu errechnen. Beim Raspberry Pi Modell A (ca. 500 mA) erhält man daher 500 mA, beim Modell B (ca. 700 32 5.3 GPIO mA) 300 mA Reserven für z.B. Erweiterungsplatinen oder USB Geräte. Beim Modell B+ wurde die Polyfuse auf 2 Ampere erhöht und zusätzlich durch die neue Spannungsversorgung der Strombedarf des Raspberry Pi selbst reduziert, weshalb man davon ausgehen kann, dass die zusätzlichen Reserven dort - je nach verwendetem Netzteil - mehr als 1,3 Ampere betragen können. 5.2.5 Zusammenfassung • Nur im ausgeschalteten Zustand an der GPIO Leiste arbeiten • Keine Spannungen über 3,3 Volt an den Raspberry Pi anschließen • Keine Pins kurzschließen • Schaltung immer doppelt auf Verpolung / falsche Belegung überprüfen • Belastbarkeit beachten, größere Lasten z.B. mit Transistor schalten 5.3 GPIO Wie bereits in Abbildung 5.1 dargestellt, verfügt die GPIO Schnittstelle über eine Vielzahl an unterschiedlichen Pins deren Möglichkeiten wir nun genauer erörtern werden. 5.3.1 GPIO Die in grüner Farbe gekennzeichneten Pins stellen die normalen GPIO Pins ohne weitere Zusatzfunktionen da. Diese Pins dienen je nach Nutzereinstellung als digitale Einoder Ausgabe und können entweder über Einsatz des gpio Programms aus dem wiringpi2 Package, oder direkt per echo angesteuert werden. Als erster Schritt muss zuerst der entsprechende GPIO Pin exportiert, also für die Nutzung im Linux Userspace vorbereitet werden. Anschließend muss die Art der Verwendung angegeben werden, also ob der Pin zur Ein- oder Ausgabe dienen soll. Abschließend kann der Status des Pins ausgelesen, beziehungsweise „HIGH“ oder „LOW“ gesetzt werden - je nach Einsatzzweck. # Beispiel für die direkte Verwendung in Bash mittels echo # Pin 24 exportieren sudo echo "24" > /sys/class/gpio/export # Pin 24 als Ausgabe festlegen echo "out" > /sys/class/gpio/gpio24/direction # Pin 24 auf HIGH setzen echo 1 > /sys/class/gpio/gpio24/value # Pin 24 auf LOW setzen echo 0 > /sys/class/gpio/gpio24/value # Export von Pin 24 aufheben 33 5 GPIO Schnittstelle echo "24" > /sys/class/gpio/unexport # Pin 27 exportieren sudo echo "27" > /sys/class/gpio/export # Pin 27 als Eingabe festlegen echo "in" > /sys/class/gpio/gpio27/direction # Pin 27 auslesen cat /sys/class/gpio/gpio27/value # Export von Pin 27 aufheben echo "27" > /sys/class/gpio/unexport Die Verwendung mit dem Tool gpio geht noch etwas einfacher und benötigt keine root Rechte: # Beispiel für die direkte Verwendung in Bash mittels gpio # Pin 24 exportieren und als Ausgabe festlegen gpio export 24 out # Pin 24 auf HIGH setzen gpio -g write 24 1 # Pin 24 auf LOW setzen gpio -g write 24 0 # Export von Pin 24 aufheben gpio unexport 24 # Pin 27 exportieren und als Eingabe festlegen gpio export 27 in # Pin 27 auslesen gpio -g read 27 # Export von Pin 27 aufheben gpio unexport 27 5.3.2 PWM Pulse-width modulation (PWM) ist ein Verfahren mit welchem die Breite eines ausgegebenen Stromimpulses kontrolliert werden kann. In diesem Zusammenhang wird der Begriff „duty cycle“ verwendet, um die Dauer des „HIGH“ Zustandes des Pins innerhalb einer Zeiteinheit zu beschreiben. Entspricht der „duty cycle“ z.B. 60%, so führt der Pin in genau diesem Prozent einer Zeiteinheit Strom. Durch das lückenhafte Versorgen des Gerätes mit Strom sinkt die Spannung je nach „duty cycle“ von 100% auf bis 0% ab. Mit dieser Technik können damit nicht nur die Helligkeit von LEDs kontrolliert werden, sondern im Sonderfall auch die Stellung von Servo Motoren. PWM ist bei dem Raspberry Pi auf dem GPIO 18 verfügbar. Aufgrund der besonderen Technik (prinzipiell dem schnellen, kontrollierten Ein- / Ausschalten des Pins) ist eine sinnvolle Nutzung mittels echo Befehls nicht gegeben. Allerdings kann auch in diesem Fall das Programm gpio genutzt werden: 34 5.3 GPIO # Beispiel für die direkte Verwendung in Bash mittels gpio # Pin 18 exportieren und als Ausgabe festlegen gpio export 18 out # Pin 18 in PWM Modus versetzen gpio -g mode 18 pwm # Pin 18 als PWM auf 100% duty cycle setzen gpio -g pwm 18 1023 # Pin 18 als PWM auf 25% duty cycle setzen gpio -g pwm 18 256 # Pin 18 als PWM auf 10% duty cycle setzen gpio -g pwm 18 102 # Pin 18 als PWM auf 1% duty cycle setzen gpio -g pwm 18 10 # Pin 18 als PWM auf 0% duty cycle setzen gpio -g pwm 18 0 # Export von Pin 18 aufheben gpio unexport 18 5.3.3 I2C Inter-Integrated Circuit (I2C) ist ein Bussystem, welches 1982 von der Firma Philips (heute: NXP Semiconductors) veröffentlicht wurde. Dieses System sollte vorrangig dazu genutzt werden, einzelne Komponenten innerhalb eines geschlossen Systems miteinander zu verbinden, z.B. Mikrocontroller mit verschiedenen Arten von Sensoren, Speichern und Analog/Digital bzw. Digital/Analog Wandlern. Da das System neben der Versorgungsspannung und Masse nur zwei Leitungen (SDA für Daten, SCL für Takt) benötigt wird es auch als Two Wire Interface (TWI) bezeichnet. SDA wie SCL müssen durch einen hochohmigen Widerstand an die Versorgungsspannung angeschlossen werden, da der Bus im Leerlauf Konstant „HIGH“ signalisiert (Pull-Up). In einem normalen I2C Netzwerk erzeugt der Master, meist ein Mikrocontroller, den Takt für den SCL Port und fragt die einzelnen Slaves, meist simple Sensoren oder Signalwandler, unter Verwendung des SDA Ports ab. Es ist allerdings auch möglich Master-Master Netzwerke zu erstellen und Teilnehmer bei aktivem Netzwerk an- und abzuklemmen (Hot-Swap) [25], S. 444 / [19]. Der Raspberry Pi verfügt über zwei I2C Busse. Bei der Revision pre 2.0 wurde nur der Bus 0 auf dem GPIO Header ausgeführt. Mit dem Wechsel zur Revision 2.0 wanderte der Bus 0 auf ein zusätzliches Verbindungsfeld (P5) und auf dem GPIO Header lag nun der Bus 1 an. Beim Modell B+ änderte sich dieser Zustand dahingehend, dass der Header P5 wieder entfiel, der Bus 1 weiterhin auf seiner Stelle auf dem GPIO Header verblieb und der Bus 0 fortan als ID_I2C geführt wurde und für die Nutzung durch den Anwender nicht mehr verfügbar war. Der I2CBus auf dem Raspberry Pi arbeitet in der Standard Geschwindigkeit (100 kHz) und im Fast-Mode (400 kHz). Theoretisch kann ein I2C Bus bis zu 127 Teilneh- 35 5 GPIO Schnittstelle mer adressieren. Mittels des Befehls i2cdetect -y 1 können alle Geräte auf dem Bus 1 angezeigt werden: 00: 10: 20: 30: 40: 50: 60: 70: 0 1 -------- -------- 2 3 --- --- --- --- --- --- --- -- 4 --------- 5 --------- 6 --------- 7 --------- 8 ----48 --- 9 -------- a -------- b ---UU ---- c -------- d -------- e -------- f -------- Unter anderem ist hier die Adresse 0x48 angezeigt, welches die hexadezimale Adresse eines LM75B Temperatursensors ist. Da laut Datenblatt dieses Sensors die Temperatur bei diesem Gerät im ersten Register liegt, können wir nun mit dem Befehl i2cget -y 1 0x48 0x00 auf dem Bus 1 an der Geräteadresse 48 das Register 0 auslesen. Wir erhalten die Antwort in Form einer hexadezimalen Notation, z.B. 0x23, was im dezimal System einer Temperatur von 35 Grad Celsius entspricht. 5.3.4 I2S Nach dem Erfolg von I2C folgte 1986 Philips Erweiterung I2S. Dabei handelt es sich um ein Bussystem, welches ausschließlich zur Verwendung innerhalb von Audiogeräten vorgesehen war. Es wurden hierbei wieder ein Takt Signal (SCK) und ein Daten Signal (SD) verwendet, zusätzlich wurden diese beiden Leitungen allerdings noch um eine sogenannte Word Select (WS) Leitung ergänzt. Je nachdem ob sich Word Select im Zustand „LOW“ oder „HIGH“ befindet, werden die übertragenen Daten dem linken, respektive rechtem Audiokanal zugeordnet. Da die Übertragung vollständig digital geschieht, ist sie verlustfrei und daher für die Verbindung von z.B. Digitalen Signal Prozessoren und Digital/Analog Wandlern geeignet. Beim Raspberry Pi ist der I2S Bus bei der Revision pre 2.0 nicht vorhanden, bei der Revision 2.0 auf dem Header P5 zu finden und bei dem Modell B+ auf dem GPIO Header. [21] 5.3.5 SPI Der Serial Peripheral Interface (SPI) Bus wurde 1979 von Motorola in Form eines Mikrocontrollers auf Basis des Motorola 68000 Mikroprozessors veröffentlicht. Im Gegensatz zum I2C Bus von Philips wurde er nicht getrennt formal beschrieben, sondern ist nur vage in den Unterlagen des Controllers als Teil dessen definiert [15]. Das SPI System verwendet vier Anschlüsse: Takt (SCLK), Master Out - Slave In (MOSI), Master In - 36 5.3 GPIO Salve Out (MISO), sowie Slave Select (SS). Der Takt wird hierbei konstant vom Master über SCLK vorgegeben, und die Daten je nach Senderichtung entweder über MOSI (vom Master zum Slave) oder MISO (vom Slave zum Master) ausgetauscht. Zusätzlich muss für jedes zu adressierende Gerät im Bus eine Slave Select Leitung bereitstehen. Diese wird vom Master auf „LOW“ gezogen, um den Slave in Empfangsbereitschaft zu schalten. Der Vorteil dieses Systems liegt in der vollduplexfähigen Kommunikation, der Nachteil in der Anzahl der benötigten n Slave Select Leitungen pro n Geräte in der Sternverbindung. Sollte man kompatible Slave Geräte gleicher Bauart verwenden, so können diese auch kaskadiert werden, womit nur eine Slave Select Leitung nötig ist. Die Geräte können dann wie ein Schieberegister ausgelesen werden [25], S. 440. Auf dem Raspberry Pi sind drei SPI Controller verfügbar, jedoch nur einer auf die GPIO Leiste ausgeführt. Der Controller kann auf 0.5 MHz, 1 MHz, 2 MHz, 4 MHz, 8 MHz, 16 MHz und 32 MHz Taktrate eingestellt werden [13]. Die maximal verwendbare Taktrate hängt aber auch vom verwendeten Slave ab. SPI kann unter Raspberry Pi am besten über die entsprechende Library mittels Python oder C angesteuert werden. 5.3.6 Serial Die serielle Schnittstelle (auch V.24 oder RS-232-C genannt) wurde 1969 von der Electronic Industries Association (EIA) für die Nutzung im Computer Umfeld definiert, was den ursprünglichen Einsatzzweck von RS-232 im Umfeld der Fernschreiber erweiterte [7]. Serielle, asynchrone Verbindungen wurden vor den Zeiten der Breitbandverbindungen genutzt um Modems mit dem Computer zu verbinden um Zugriff zum Internet oder dem Telefonnetz herzustellen. Mit dem Aufkommen von A-/S-DSL und Kabelbreitbandverbindungen wurde diese Schnittstelle an regulären Rechnern immer unwichtiger, kann aber bis heute vorgefunden werden. Eine besondere Bedeutung nimmt dieses Interface weiterhin bei eingebetteten Systemen, Mikrocontrollern, GPS Empfängern, wissenschaftlichen Geräten sowie Netzwerkequipment und Servern ein. Die Übertragung der seriellen Schnittstelle erfolgt prinzipiell über zwei Adern: RX (Recieve) und TX (Transmit). Die Verbindung muss direkt zwischen Sender und Empfänger hergestellt und die beiden Datenadern überkreuzt angeschlossen werden, also RX des Senders auf TX des Empfängers und umgekehrt. Zusätzlich muss die Masse (GND) beider Systeme miteinander verbunden werden. Als Geschwindigkeiten werden häufig 4800, 9600, 19200 und 115200 Baud (Zeichen pro Sekunde) verwendet. Eine Besonderheit ist im Bereich von eingebetteten Systemen, Mikrocontrollern, GPS Empfängern und anderen Klein- und Kleinstgeräten zu beachten: Im Gegensatz zu den im RS-232C definierten Signalpegeln von -15 Volt bis +15 Volt [12] setzen diese Geräte oft einen sogenannten TTL Pegel (Transistor-Transistor Logic) ein, welcher zwischen 0 Volt und 3,3 Volt, respektive 5 Volt liegen kann. Dies trifft auch auf den Raspberry Pi zu, weshalb dessen serielle Schnittstelle in keinem Fall direkt mit dem PC zu verbinden ist, da sonst eine Beschädigung des SoC des Raspberry Pi möglich ist. Durch die Nutzung eines TTL-Serial Konverters ist diese Verbindung gefahrlos möglich. 37 5 GPIO Schnittstelle Auf dem Raspberry Pi kann die serielle Schnittstelle auf verschiedene Arten genutzt werden. Zum einen um einen GPS Empfänger anzuschließen, einen Mikrocontroller mit Arduino Bootloader zu programmieren oder um Modell A Boards ohne Netzwerkinterface per PPP (Point-to-Point Protocoll) in ein Netzwerk zu integrieren. Ein einfaches und empfehlenswertes Tool um die serielle Schnittstelle zu nutzen, stellt minicom dar. 5.4 Das Erweiterungsboard Um die Nutzung der GPIO des Raspberry Pi zu ersten Testzwecken so einfach wie möglich zu machen, wurde im Rahmen dieser Thesis ein Erweiterungsboard entworfen und zur Verwendung im Rahmen der Lehre der HTW Saar in zehnfacher Stückzahl aufgebaut. 5.4.1 Design Das Design sollte so ausgelegt sein, dass es möglichst klein, kostengünstig und dennoch vielseitig verwendbar sein sollte. Durch die Entwicklung des Boards sollten besonders Fehler die beim Aufbau der Schaltungen mit der GPIO Leiste auftreten könnten verhindert werden, und der Fokus auf die Entwicklung der Software gelegt werden. Da zum Zeitpunkt des Beginns dieser Thesis der Raspberry Pi Modell B+ noch nicht verfügbar war, wurde die Platine auf Basis des Modell A/B Rev. 2.0 entwickelt und ist auf beiden Versionen ohne Einschränkungen verwendbar. Ebenfalls ist die Nutzung mit dem neuen Modell B+ möglich, wobei allerdings keine korrekte mechanische Entlastung wie bei den Modellen A/B Rev. 2.0 durch ein passendes Bohrloch gegeben ist. Das Erweiterungsboard stellt folgende Merkmale zur Verfügung: • Vier einfarbige LEDs • Vier Taster • LM75B (I2C Temperatursensor) • MCP3002 (SPI Zweikanal Analog/Digital Wandler) mit angeschlossenem Light Dependent Resistor (LDR) Dabei sind die LEDs in einem Steuerkreuz angeordnet und den betreffenden Tastern zugeordnet. 5.4.2 Routing Die Belegung und Anschlüsse der einzelnen Komponenten auf dem Erweiterungsboard lässt sich der angefügten Grafik und Tabelle entnehmen. 38 5.4 Das Erweiterungsboard LM75B Nor t h Eas t Wes t Sout h Bauteil Bemerkung GPIO LED North grün, PWM 18 LED East rot 23 LED West gelb 25 LED South blau 24 Switch North Pull-Down 4 Switch East Pull-Down 17 Switch West Pull-Down 22 Switch South Pull-Down 27 LM75B SDA 2 SCL 3 MOSI 10 MISO 9 SCLK 11 CS / SS 8 MCP3002 MCP3002 Abbildung 5.2 & Tabelle 5.1: Erweiterungsboard und Routing der Komponenten Als Besonderheiten sei dabei zu erwähnen, dass die erste LED (LED North / grün) am PWM Anschluss des RPi angeschlossen ist, um die Nutzung dieses Verfahrens zu demonstrieren. Die LEDs selbst werden nicht direkt von den GPIO Pins versorgt, sondern schalten einen Transistor, welche wiederum die Schaltlast übernimmt und die LEDs mit 5 Volt Spannung versorgt. Weiterhin werden die Taster durch einen Pull-Down Widerstand konstant auf „LOW“ gezogen, sind also mit der Masse des Raspberry Pi verbunden. Es ist üblich Taster entweder per Pull-Down auf „LOW“ oder per Pull-Up auf „HIGH“ zu ziehen, um einen stets definierten Zustand zu erreichen. Erst beim Schließen des Kontaktes wird der entsprechende GPIO Port mit 3,3 Volt Spannung verbunden. Zur Temperaturmessung steht ein LM75B zur Verfügung, ein I2C Sensor, welcher direkt auf dem Board verbaut ist. Durch das normale Auslesen des Wertes mittels i2cget erhält man den Temperaturwert in 8 bit Darstellung, also nur Abstufungen von einzelnen Grad. Möchte mit die kompletten 11 bit Auflösung des Sensors ausnutzen, also eine Auflösung von bis zu 0,125 Grad Celsius Unterschied erreichen, so muss das entsprechende Register in doppelter Byte Länge ausgelesen und ausgewertet werden. Dazu kommen wir in einem späteren Kapitel. Der erwähnte Lichtsensor (LDR) verhält sich wie ein Widerstand und erreicht je nach einfallendem Licht Werte zwischen 40,5 k und 1 M Ohm. Da der Raspberry Pi allerdings 39 5 GPIO Schnittstelle über keinen Analog/Digital Wandler verfügt um z.B. eine Spannungsmessung durchzuführen, wird der an einem MCP3002 angeschlossen, einem externen Analog Digital Converter (ADC) welcher über SPI angesprochen wird. Insgesamt bleiben damit ausschließlich die GPIO Pins 14 und 15 (TX/RX der Serial Verbindung) und GPIO 7 (SPI Slave Select 1) ungenutzt. 5.4.3 Testprogramm Um die Funktionalität des Erweiterungsboards zu überprüfen, gibt es im Home Verzeichnis des Raspberry Pi Hauptnutzers pi den Unterordner RPi_HTW/boardTest, welchen das in C geschrieben Testprogramm boardTest beinhaltet. Es verwendet die bereit vorher installierte wiringpi2 Library, um die unterschiedlichen Funktionen des Erweiterungsboards auf Funktionalität zu überprüfen. Dazu gehören die LEDs, die PWM Funktionalität, die Schalter wie auch der I2C Bus mit dem angeschlossenen LM75B Temperatursensor und dem SPI Bus mit dem MCP3002 ADC Wandler. Letzterer gibt auf Kanal 0 den Helligkeitswert des angeschlossenen LDR wieder. Um es zu nutzen muss es zuerst kompiliert werden, was der Aufruf von make erledigt. Anschließend kann das Programm unter Verwendung von sudo sudo ./boardTest gestartet werden. Eine Beispielausgabe sieht wie folgt aus: LED Test beginnt NORTH: LED gruen EAST: LED rot WEST: LED gelb SOUTH: LED blau LED Test beendet PWM Test beginnt PWM Test beendet Switch Test beginnt NORTH: Switch druecken NORTH: Switch ok EAST: Switch druecken EAST: Switch ok WEST: Switch druecken WEST: Switch ok SOUTH: Switch druecken SOUTH: Switch ok Switch Test beendet LM75B Temperatursensor Test beginnt LM75B: 34.12 Grad Celsius LM75B: 34.25 Grad Celsius LM75B: 34.12 Grad Celsius LM75B: 34.12 Grad Celsius LM75B: 33.88 Grad Celsius 40 5.4 Das Erweiterungsboard LM75B: 34.00 Grad Celsius LM75B: 34.00 Grad Celsius LM75B: 34.00 Grad Celsius LM75B: 34.12 Grad Celsius LM75B: 34.00 Grad Celsius LM75B Temperatursensor Test beendet MCP3002 ADC Test beginnt MCP3002 - Channel 0: 232 MCP3002 - Channel 0: 320 MCP3002 - Channel 0: 348 MCP3002 - Channel 0: 72 MCP3002 - Channel 0: 48 MCP3002 - Channel 0: 300 MCP3002 - Channel 0: 332 MCP3002 - Channel 0: 724 MCP3002 - Channel 0: 612 MCP3002 - Channel 0: 616 MCP3002 ADC Test beendet Die boardTest.c ist im Anhang D.1 verzeichnet. Sollte ein eigenes Programm ohne die make File kompiliert werden, so ist es wichtig, den Schalter -lwiringPi anzugeben. Beispielsweise: gcc -o test test.c -lwiringPi. 41 6 Bash Programmierung In diesem Kapitel soll die Nutzung des Erweiterungsboards unter Verwendung der Bash anhand eines Beispielprojektes aufgezeigt werden: Ziel wird es sein, einen Klon des alten elektronischen Spiels „Simon“ zu erstellen, und damit die in der Vorlesung „Betriebssystem Einführung“ gelernten Grundlagen zu vertiefen und festigen. 6.1 Grundlagen 6.1.1 Simon Simon ist ein 1977 erfundenes, elektronisches reaktions- und Merkspiel auf Basis des Texas Instruments TMS1000 Mikrocontrollers [18]. Simon verfügt über vier LEDs (grün, rot, blau, gelb) und entsprechend, den Farben zugewiesene Taster. Das Spiel beginnt in dem eine zufällige Farbe auf dem Spielzeug aufleuchtet und der Spieler eben dem dieser Farbe entsprechenden Schalter drückt. War er erfolgreich, werden in der nächsten Runde die Farbe des ersten Zyklus plus eine weitere Farbe vorgegeben, welcher der Spieler wieder in der richtigen Reihenfolge eingeben muss. Das Spiel endet falls der Spieler eine falsche Kombination eingibt. Abbildung 6.1: Simon 43 6 Bash Programmierung 6.1.2 Ablaufdiagramm Ein prinzipieller grober Ablauf des Spiels ist in Abbildung 6.2 aufgezeigt. Darüber hinaus empfiehlt es sich zusätzlich den Start und das Ende des Programms durch die Verwendung aller LEDs zu kennzeichnen und gegeben falls einen rekursiven Aufruf beim Ende durchzuführen. Abbildung 6.2: Flowchart Simon 6.2 Programmierung Alle genannten Dateien sind im Home Verzeichnis des Hauptnutzers pi im Unterordner RPi_HTW/Simon zu finden. 44 6.2 Programmierung 6.2.1 Erweiterungsboard und Hilfsfunktionen Das Erweiterungsboard bietet für dieses Projekt die vier genannten LEDs, nebst den benötigten Schaltern. Um die Entwicklung zu vereinfachen steht die gpio.sh im Anhang D.2 zur Verfügung, welche die benötigten Funktionen zur Nutzung der an die GPIO Pins angeschlossenen LEDs und Schalter bereitstellt. Für jede LED existiert jeweils eine Funktion, um diese ein-, beziehungsweise auszuschalten. Für die Schalter gibt es jeweils eine Funktion, welche den aktuellen Status zurück gibt (0 für „LOW“ beziehungsweise nicht gedrückt, 1 für „HIGH“ beziehungsweise gedrückt). • ledNorthOn() • ledNorthOff() • ledEastOn() • ledEastOff() • ledWestOn() • ledWestOff() • ledSouthOn() • ledSouthOff() • switchNorth() • switchEast() • switchWest() • switchSouth() Neben diesen Funktionen gibt es noch mehrere Hilfsfunktionen: • ledOn() • ledOff() • ledBlink() • ledBlinkFast() Die beiden ersten Hilfsfunktionen schalten alle LEDs an, beziehungsweise aus. Die letzteren beiden lassen jeweils alle LEDs einmal mit einem Abstand von 0,5, respektive 0,25 Sekunden aufblinken. In den nachfolgenden beiden Unterkapiteln werden wir diese Funktionen nutzen. 45 6 Bash Programmierung 6.2.2 LED Ausgabe Um eine LED per Bash anzusteuern, können wir unter Verwendung der gpio.sh folgendes Skript erstellen: # !/ bin / bash source gpio . sh ledNorthOn sleep 2 ledNorthOff Mit source gpio.sh binden wir die gpio.sh und ihre Hilfsfunktionen ein, welche wir mit ledNorthOn beziehungsweise ledNorthOff nutzen um die grüne LED an- beziehungsweise auszuschalten. sleep 2 rundet das ganze Programm ab und erzeugt eine Pause von zwei Sekunden, damit der sonst zu schnelle Schaltvorgang für das menschliche Auge sichtbar wird. Das Codelisting der demoLed.sh ist als Langversion auch im Anhang D.3 verfügbar. Nachdem die Datei erstellt wurde, muss sie unter Verwendung des Befehls chmod +x dateiname ausführbar gemacht, und anschließend mittels ./dateiname gestartet. 6.2.3 Switch Eingabe Die Eingabe ist wie die LED Ausgabe ebenfalls sehr einfach zu bewerkstelligen: # !/ bin / bash source gpio . sh while : do if [ $ ( switchNorth ) = 1 ] then echo " North gedrueckt " ledNorthOn else ledNorthOff fi done Das Programm läuft in diesem Beispiel in einer endlosen Schleife, welche mittels der Tastenkombination Strg + C unterbrochen werden kann. Durch die while Schleife wird ständig geprüft, ob der Schalter North gedrückt wurde. Ist dies der Fall, wird eine entsprechende Nachricht ausgegeben, und die dazu passende LED angeschaltet. Sollte dem nicht so sein, wird die LED ausgeschaltet. Es gibt auch die Möglichkeit Pins nicht per polling, also dauerndem Abfragen auf einen Wechsel des Zustandes zu überprüfen, sondern per Interrupt. Dies setzt aber eine höhere Programmiersprache voraus und ist daher leider in Bash nicht möglich (siehe dazu: http://wiringpi.com/reference/ priority-interrupts-and-threads/). 46 6.3 Abschluss 6.3 Abschluss Mit den hier gelernten Grundlagen, sowie dem Wissen aus der Vorlesung „Betriebssystem Einführung“ sollte es nun möglich sein, einen einfachen Klon des Spiels Simon mittels des Raspberry Pi und dem Erweiterungsboard zu erschaffen. Das Musterprogramm simon.sh ist im Anhang D.5 zu finden, allerdings nicht auf der SD Karte vorinstalliert, um die Studenten zur Entwicklung einer eigenen Lösung anzuhalten. 47 7 Python Programmierung Nachdem wir im vorangegangenen Kapitel die Nutzung der GPIO mittels Bash gelernt haben, wollen wir diese Fähigkeiten nun mit der Programmiersprache Python vertiefen. Dieses Kapitel soll als leichter Einstieg in die Sprache Python die Grundlagen für die Vorlesung „Systemmanagement und Sicherheit“ liefern, wie auch die praktische Nutzung von Bus Systemen, wie sie in „Rechnerarchitektur“ und „Mikroprozessortechnik“ gelehrt werden verdeutlichen. Am Ende dieses Kapitels werden sowohl die Grundlagen zur Nutzung von Python gelegt, als auch der I2C, wie auch der SPI Bus, in die Nutzung eingeflossen sein. 7.1 Arbeiten auf dem Raspberry Pi 7.1.1 Python 2 / Python 3 Python ist ähnlich wie PHP, eine Skriptsprache die zur Ausführung einen Interpreter benötigt. Von Python gibt es inzwischen zwei verschiedene Versionen: Python 2 (2.7.x) und Python 3 (3.4.x). Python 3 enthält Verbesserungen, welche allerdings die Kompatibilität unter anderem wegen der Entfernung redundanter Befehle zu alten Skripten brechen kann. Da die Version 2 bereits länger existiert, viele Bibliotheken nur in dieser Version funktionieren, und dieser Branch immer noch mit aktuellen Updates versorgt wird, ist Python 2 auch auf dem Raspberry Pi die empfohlene und verwendete Standardversion. Sollten durch den vorzeitigen Abbruch eines Programms LEDs im aktiven Zustand verbleiben, können die GPIO Pins mittels des CLI Kommandos gpio reset zurückgesetzt und damit die LEDs ausgeschaltet werden. 7.1.2 Programmierung mittels IDLE Verwendet man den Raspberry Pi als vollwertigen PC, empfiehlt sich die Nutzung des Python Integrated Development Environment (IDE) IDLE. IDLE liegt auf dem RPi in zwei Versionen vor. Einmal als IDLE (zur Nutzung mittels Python 2) als auch als IDLE3 (welches Python 3 einsetzt). Wie bereits erwähnt werden wir Python 2, und damit das normale IDLE nutzen. Da die Nutzung der GPIO Pins root Rechte erfordert, sollte man IDLE nicht per Klick auf das Desktop Icon, sondern mittels LXTerminal unter Verwendung des Befehls sudo idle & starten, um die Anwendung im Kontext des root Nutzers zu starten. Die Nutzung selbst ist sehr einfach: Über das Menü File, New Window kann man ein neues Editor Fenster erstellen, in welchem man seinen Python Code schreiben, laden und speichern kann. Ausgeführt wird dieser Code über das Menü Run per Klick auf Run Module. 49 7 Python Programmierung 7.1.3 Programmierung mittels CLI Sollte man den RPi Headless verwenden, also ohne Bildschirm und Eingabegeräte, empfiehlt sich die Nutzung eines Texteditors wie vi in Kombination mit python direkt auf Ebene des Command Line Interface (CLI) / der Shell. Dazu sollte man seinen Programmcode mit einem Editor seiner Wahl schreiben, speichern und schließlich direkt unter Verwendung von sudo python dateiname ausführen. 7.2 Grundlagen der Python Programmierung 7.2.1 Ausführung Es gibt drei prinzipielle Möglichkeiten ein Python Programm auszuführen: 1.) Die direkte Eingabe der Befehle in eine interaktive Shell wie IDLE oder python auf dem CLI. 2.) Der direkte Aufruf einer geschriebenen Skriptdatei mittels python dateiname .py im CLI. 3.) Die Verwendung der Shebang Zeile (#!/usr/bin/python) als erste Zeile in einer Skriptdatei, gefolgt vom setzen des X / Ausführungbarkeits-Bits (./chmod +x dateiname.py) und dem anschließenden Aufruf im CLI (./dateiname.py). Um Python kennen zu lernen empfiehlt sich besonders am Anfang die Arbeit in einer interaktiven Shell, für die spätere Programmentwicklung die Methoden Zwei und Drei. 7.2.2 Variablen Variablen werden bei Python durch Zuweisung eines Wertes angelegt: # !/ usr / bin / python meinInteger =2+3 meinFloat =5.0 meinString = " Hallo Welt " print ( meinInteger ) print ( meinInteger / 2) print ( meinFloat / 2) print ( meinString + " ! " + " Binaer % s Hex % s " % ( bin ( meinInteger ) , hex ( meinInteger ) ) ) Dies erzeugt die Ausgabe: 5 2 2.5 Hallo Welt ! Binaer 0 b101 Hex 0 x5 7.2.3 Operatoren Python verwendet die üblichen arithmetischen Operatoren. Besondere Beachtung fällt dabei auf den verwendeten Datentyp: Sollte ein Integer Wert geteilt werden, so ist das 50 7.2 Grundlagen der Python Programmierung Tabelle 7.1: Arithmetische Operatoren Operation Ergebnis Bezeichnung 5+5 10 Summe 5-1 4 Differenz 5*1 5 Produkt 5/2 2 Quotient (Integer) 5.0 / 2 2.5 Quotient (Float) 5%2 1 Modulo 2 ** 3 8 Power Ergebnis ebenfalls ein Integer. Wenn im Rahmen dieser Rechenoperation eine rationale Zahl entsteht, so wird diese abgerundet und als ganze Zahl dargestellt. Die Vergleichsoperatoren sind ebenfalls bekannt sofern man Vorkenntnisse in Java besitzt: Tabelle 7.2: Vergleichsoperatoren Operation Bezeichnung x == y Gleichheit x != y Ungleichheit x>y Größer x<y Kleiner x >= y Größer-gleich x<= y Kleiner-gleich Da in diesem Dokument mit hardwarenahen Anwendungen gearbeitet wird, ist es auch von Bedeutung die binären, bitweisen Operatoren zu kennen. Dies ist besonders wichtig da Geräte in Bussystemen wie I2C oder SPI ihre Ergebnisse in einzelnen Registern speichern, welche meist wenige Byte umfassen. Dabei besitzt häufig jedes Bit eines Bytes eine eigene Relevanz, zum Beispiel die Konfiguration eines Pins als Einoder Ausgang, je nachdem ob dessen Bit gesetzt ist oder nicht. Durch die binären, bitweisen Operationen können diese Werte entsprechend schnell gesetzt beziehungsweise ausgelesen werden. Um einen Wert in binärer Schreibweise eingeben zu können, muss ihm der Präfix 0B vorgestellt werden. So würde zum Beispiel die Zahl 0B11110000 von Python als 240 verstanden werden. Alternativ können die binären, bitweisen Operationen auch mit den Werten in beliebiger anderer, zum Beispiel dezimaler Schreibweise angewandt werden. Die vier wichtigsten Operationen, welche auch schon in den Vorlesungen „Digital- 51 7 Python Programmierung technik 1“ und „Mikroprozessortechnik“ gelehrt wurden, sollen an dieser Stelle noch einmal kurz wiederholt werden: 1.) Binäres Und: Es werden jeweils die Werte gleicher Position beider binärer Notationen per „Und“ miteinander verknüpft. Sollten diese beide „Wahr“ entsprechen, ist auch das Ergebnis „Wahr“ - sonst „Falsch“. Tabelle 7.3: Binäres Und x y x&y 0 0 0 0 1 0 1 0 0 1 1 1 2.) Binäres Oder: Das binäre „Oder“ entspricht der gleichen Wirkungsweise wie „Und“, allerdings wird die Ausgabe „Wahr“ solange entweder eine oder beide Werte „Wahr“ sind. Tabelle 7.4: Binäres Oder x y x|y 0 0 0 0 1 1 1 0 1 1 1 1 3.) Binäres XOR: XOR, welches auch zur Verschlüsselung genutzt wird, erwartet als Voraussetzung für eine „Wahre“ Ausgabe zwei unterschiedliche Eingaben. Tabelle 7.5: Binäres XOR 52 x y xˆy 0 0 0 0 1 1 1 0 1 1 1 0 7.2 Grundlagen der Python Programmierung 4.) Binäres 1er Komplement: Das 1er Komplement wird zur Berechnung im Bereich der Mikrocontroller verwendet und negiert alle Eingaben. Tabelle 7.6: Binäres 1er Komplement x ˜x 0 1 1 0 Tabelle 7.7: Binäre, bitweise Operatoren Operation Ergebnis Bezeichnung x&y 0000 0001 / 1 Binäres Und x|y 1111 1111 / 255 Binäres Oder xˆy 1111 1110 / 254 Binäres XOR ˜x 1111 0000 / -16 Binäres 1er Komplement 7.2.4 Vergleiche und Schleifen Eine wichtige Besonderheit bei Python ist das Fehlen von Klammern zum Kapseln von Schleifen oder Befehlsfolgen. Stattdessen verwendet Python Einrückungen wie die Tabulator Taste, um den Programmcode zu formatieren und strukturieren. Dies erzeugt sauberen und lesbaren Code, welcher ohne diese Einrückungen nicht lauffähig ist. Im nächsten Beispiel wird eine while Schleife und eine verschachtelte if Anweisung gezeigt. Da die letzte Zeile sich auf der gleichen Ebene wie die Vergleiche befinden, ist sie kein Teil davon und wird nach der Abarbeitung der Vergleiche aufgerufen. # !/ usr / bin / python meinInteger =40 while meinInteger < 45: if meinInteger == 42: print ( " Integer ist 42! " ) elif meinInteger < 42: print ( " Integer ist kleiner als 42 " ) else : print ( " Integer ist groesser als 42 " ) meinInteger += 1 Dies erzeugt die Ausgabe: Integer ist kleiner als 42 Integer ist kleiner als 42 53 7 Python Programmierung Integer ist 42! Integer ist groesser als 42 Integer ist groesser als 42 Die for Schleife kann auf mehrere Art genutzt werden: # !/ usr / bin / python # Zaehlschleife , Werte zwischen 0 und 5 ( von 0 -4) ausgeben for i in range (0 ,5) : print ( i ) # Äquivalent zur for each # jedes Element einer Liste verwenden sprachen = [ " Python " , " Java " , " C " , " Haskell " ] for i in sprachen : print ( " % s ist eine Programmiersprache " % i ) # jeden Buchstaben eines Strings ausgeben meinString = " Hallo Welt " for i in meinString : print ( i ) Dies erzeugt die Ausgabe: 0 1 2 3 4 Python ist eine Programmiersprache Java ist eine Programmiersprache C ist eine Programmiersprache Haskell ist eine Programmiersprache H a l l o W e l t 7.2.5 Funktionen Funktionen werden in Python mittels def definiert. Als Beispiel wollen wir an dieser Stelle zwei Algorithmen aus der Vorlesung „Programmierung 1“ [9] verwenden, in diesem Fall die Berechnung des größten gemeinsamen Teilers. 54 7.2 Grundlagen der Python Programmierung # !/ usr / bin / python import timeit # Importiere die Python Bibliothek timeit zur Laufzeitmessung von Funktionen def ggTintuitiv (m , n ) : # Definiere die erste Funktion ggTintuitiv , welche die Teiler einzeln probiert m = abs ( m ) n = abs ( n ) teiler = 1; groessterTeiler = 1 while (( teiler <= m ) and ( teiler <= n ) ) : if ( ( m % teiler == 0 ) and ( n % teiler == 0) ) : groessterTeiler = teiler teiler += 1 return groessterTeiler def ggTeuklid (m , n ) : # Definiere die zweite Funktion ggTeuklid , welche den Algorithmus nach Euklid verwendet m = abs ( m ) n = abs ( n ) r = m % n while ( r > 0) : m = n n = r r = m % n return n t_intuitiv = timeit . Timer ( " ggTintuitiv (12345678 , 23456789) " , " from __main__ import ggTintuitiv " ) # Erstelle ein neues Objekt von der Klasse Timer . # Der erste Parameter ist die zur Messung auszuführende Funktion , # der zweite Parameter die einmalig auszuführende Setup Anweisung , bei der wir die zu messende # Funktion nocheinmal in den Kontext einbinden zeit_intuitiv = t_intuitiv . timeit (1) # Führe die Messung einmal durch und schreibe die vergangene Zeit in die Variable t_euklid = timeit . Timer ( " ggTeuklid (12345678 , 23456789) " , " from __main__ import ggTeuklid " ) zeit_euklid = t_euklid . timeit (1) print ( " Inuitiv : " + str ( ' {:.2 f } '. format ( zeit_intuitiv ) ) + " Sekunden " ) print ( " Euklid : " + str ( ' {:.10 f } '. format ( zeit_euklid ) ) + " Sekunden ") # Gebe jeweils die abgelaufene Zeit für beide Berechnungen aus # '{:.2 f } '. format ( Variable ) beschränkt die Anzahl der Nachkommastellen print ( " Euklid ist : " + str ( ' {:.2 f } '. format ( zeit_intuitiv / zeit_euklid ) ) + " x schneller " ) 55 7 Python Programmierung # Berechne wie vielfach Euklid schneller ist , wandle den Float in einen String um und gebe den Wert aus Im direkten Vergleich zu den Folien (Seite 16/18) von Herrn Folz kann man erkennen, dass die nötigen Anpassungen in den Algorithmen minimal waren. Die Beispielausgabe zeigt dass die Berechnung die geringen Ressourcen des Raspberry Pi stark beanspruchen und wie massiv der Unterschied zwischen beiden Implementationen in der Laufzeit aussieht: Inuitiv : 28.54 Sekunden Euklid : 0.0000569820 Sekunden Euklid ist : 500789.60 x schneller Besonders interessant wird es, wenn man diese Werte jeweils der entsprechenden Implementation in Java und C++ auf einem Intel Core i7-620M mit 2,66 GHz (JDK 1.6 und GNU C++) gegenüberstellt: Tabelle 7.8: Laufzeiten beider Algorithmen in Sekunden RPi Python i7 Java i7 C++ ggTintuitiv 28,54 0,163 0,043 ggTeuklid 0.0000569820 0,00000011 0,00000016 Wie man erkennen kann bleibt die effiziente Implementierung nach Euklid auch auf dem Raspberry Pi mit seinen geringen Ressourcen gut verwendbar, während die intuitive Version spürbare Verzögerungen erzeugt. Es zeigt sich, dass im Bereich der Embedded Systeme auch heute noch eine ressourcensparende Programmierung notwendig ist und unabhängig von der verwendeten Programmiersprache zum guten Stil gehören sollte. 7.2.6 Bibliotheken Im vorangegangen Abschnitt haben wir bereits mit timeit eine Bibliothek verwendet, ohne auf die Verwendung dieser genauer einzugehen. Bibliotheken können, wie auch in anderen Sprachen dazu genutzt werden, den Funktionsumfang zu erweitern. In Python werden Bibliotheken normal durch die Verwendung von import, gefolgt vom Bibliotheksname eingebunden. Beispielsweise import time, womit die gesamte Bibliothek time eingebunden wird. Möchte man nur einzelne Module aus der Bibliothek einbinden, so kann man dies mit dem Schema from time import sleep tun. Damit wird nur das Modul sleep aus der Bibliothek time eingebunden. Um einer doppelten Nutzung des gleichen Namespaces vorzubeugen, kann man Module und Bibliotheken auch beim Import mittels as umbenennen: So kann nach dem Import mit import time as zeit das Modul sleep unter Verwendung von zeit.sleep() aufgerufen werden. 56 7.3 Verwendung der GPIO mittels Python 7.3 Verwendung der GPIO mittels Python Nachdem wir bereits die GPIO in Bash mittels der abstrahierenden gpio.sh verwendet haben, werden wir diesmal die Pins mittels der wiringpi2-python Bibliothek direkt ansprechen. Die wichtigsten Funktionen sind in der WiringPi API Dokumentation (https://projects.drogon.net/raspberry-pi/wiringpi/functions/) bzw. WiringPi Referenz (http://wiringpi.com/reference/) nachlesbar. 7.3.1 Digitale Ausgabe: LEDs Beginnen wir mit der digitalen Ausgabe unter Verwendung des Erweiterungsboards. Zur Hilfestellung sei an dieser Stelle die entsprechenden LEDs und ihre GPIO Nummern vermerkt: Tabelle 7.9: LEDs auf dem Erweiterungsboard Bauteil Bemerkung GPIO LED North grün, PWM 18 LED East rot 23 LED West gelb 25 LED South blau 24 # !/ usr / bin / python import wiringpi2 as wpi # Importiere die Python Bibliothek wiringpi2 unter # dem Namen wpi zur Nutzung der GPIO from time import sleep # Importiere das Modul sleep aus der # Python Bibliothek time wpi . wiringPiSetupGpio () # Initialisiert die Bibliothek unter Nutzung des # BCM GPIO Namenschema wpi . pinMode (18 ,1) # Definiert den Port der gruenen LED als Ausgabe wpi . digitalWrite (18 ,1) # Setzt den Port der gruenen LED auf HIGH sleep (0.5) # Wartet eine halbe Sekunde wpi . digitalWrite (18 ,0) # Setzt den Port der gruenen LED auf LOW Dieses Listing entspricht dem Hello World des Physical Computing: Es schaltet die grüne LED an, aus und beendet das Programm. 57 7 Python Programmierung 7.3.2 Übungsaufgabe zur digitalen Ausgabe Um das Verständnis für die grundlegende Nutzung von Python und der GPIO zu Vertiefen empfiehlt sich folgende Übungsaufgabe: Man erstelle einen Programmcode um alle LEDs, beginnend mit der Grünen, im Uhrzeigersinn einzuschalten. Anschließend sollen, wieder beginnend mit der Grünen, alle LEDs wieder ausgeschaltet werden. Nachdem Durchlauf dieser Prozedur soll dieser Vorgang bis zur Eingabe von Strg + C wiederholt werden. Die Lösung der Aufgabe findet sich im Anhang unter D.6. 7.3.3 Digitale Eingabe: Schalter Nachdem wir nun die digitale Ausgabe beherrschen, wenden wir uns der digitalen Eingabe zu. Wir beginnen mit der Auflistung der Schalter auf dem Erweiterungsboard: Tabelle 7.10: Schalter auf dem Erweiterungsboard Bauteil Bemerkung GPIO Switch North Pull-Down 4 Switch East Pull-Down 17 Switch West Pull-Down 22 Switch South Pull-Down 27 # !/ usr / bin / python import wiringpi2 as wpi wpi . wiringPiSetupGpio () wpi . pinMode (4 ,0) # Definiert den Port des North Switches als Eingabe while True : print ( " North Switch : % d " % ( wpi . digitalRead (4) ) ) # Wert des North Switches auslesen und ausgeben In diesem Fall nutzen wir pinMode mit dem Pin des ersten Schalters und setzen seinen Modus auf 0, was der Eingabe entspricht. Anschließend können wir in einer endlos Schleife den Wert dieses Pins abfragen und auf der Python Konsole ausgeben. 7.3.4 Übungsaufgabe zur digitalen Eingabe Als Übung zur digitalen Eingabe verwenden wir ein kleines Reaktionsspiel unter Nutzung der vier LEDs und einem Schalter. Wie bei der vorherigen Übung sollen bei diesem Programm alle LEDs zum Leuchten gebracht werden. Es gilt weiterhin die Richtung im Uhrzeigersinn, allerdings soll diesmal die blaue LED den Anfang machen. 58 7.3 Verwendung der GPIO mittels Python Weiterhin sollen die LEDs nicht dauerhaft an- oder ausgeschaltet werden, sondern in jedem Zyklus einmal kurz aufblinken. Zwischen jeder LED soll eine Pause von einer halben Sekunde liegen. Ziel des Spieles soll es sein, den äußerten Schaltern (South / S) zu drücken, kurz bevor die grüne LED leuchtet. Sollte dies erfolgreich sein, so soll die LED zweimal kurz aufblinken, die Pause zwischen dem aufleuchten der einzelnen LEDs um den Wert 0.05 reduziert, die aktuelle Rundenanzahl ausgegeben werden und das Spiel wieder bei der blauen LED starten. Sollte man zu früh oder zu spät drücken, so soll die falsche LED aufleuchten und eine entsprechende Nachricht auf dem Bildschirm angezeigt werden und das Programm sich selbst beenden. Gleiches gilt, falls man gar nicht den Schalter in der Runde betätigt. Die Lösung der Aufgabe findet sich im Anhang unter D.7. 7.3.5 Abschlussprojekt GPIO: Binärzähler Als Abschlussprojekt soll an dieser Stelle ein Vier-Bit-Binärzähler programmiert werden. Dabei sollen zwei Schalter und alle vier LEDs verwendet werden. Der äußerte Schalter (South / S) soll dabei bei jeder Betätigung im Python Programm eine Zählvariable um 1 erhöhen, während der darüber liegende Schalter (West / W) den Zähler auf 0 zurücksetzen soll. Das Programm soll bis zu 15 zählen und danach wieder zu 0 umbrechen und von vorne zu zählen beginnen. Die LEDs sollen bei diesem Projekt die Ausgabe der Zahl in binärer Notation ermöglichen. Dabei ist jede LED als eine Stelle einer vierstelligen, binären Notation zu verstehen: 2³ 2⁰ 2¹ 2² Abbildung 7.1: Festlegung des binären Wertes jeder LED Zusätzlich zu der Ausgabe der Zahl über die LEDs, soll das Programm weiterhin den Wert über die Konsole in den Formen Dezimal, Binär und Hexadezimal ausgeben. Die Lösung der Aufgabe findet sich im Anhang unter D.8. 59 7 Python Programmierung 7.4 Verwendung des I2C Bus mittels Python Im nachfolgenden Beispiel wird schrittweise erörtert, wie der I2C Bus mit wiringpi2, hier in Python verwendet wird. Als Beispiel dazu dient der verbaute LM75B Temperatursensor. Die nachfolgenden technischen Daten lassen sich im Datenblatt des Sensors unter [14], respektive in der Datei RPi_HTW/Datenblaetter/LM75B.pdf auf dem Raspberry Pi finden. 7.4.1 Adressierung Wie bereits unter Abschnitt 5.3.3 erklärt, hat jeder Teilnehmer im I2C Bus eine eindeutige, hexadezimal notierte Adresse. Da allerdings verschiedene Anwendungszwecke mehrere Geräte einer Art erfordern könnten (zum Beispiel mehrere LM75B in einem Bus, um die Temperatur an verschiedenen Punkten eines Raumes zu überwachen), haben viele Hersteller die Möglichkeit mitgegeben, die Adresse ihres I2C Gerätes durch Adressanschlüsse zu verändern. Diese Adresspins können wir in dem Pinout des Datenblattes unter 6.1, Figure 2 (Pin configuration for SO8) einsehen: Abbildung 7.2: LM75B Pinout Da hier mit A0, A1 und A2 gleich drei Pins zur Verfügung stehen, können also je nach unterschiedlichen Verbindungen mit „HIGH“ (3,3V) und „LOW“ (Ground) bis zu 23 , also acht unterschiedliche Adressen erzeugt werden. Dies bedeutet, dass bis zu acht Geräte im gleichen Bus ohne Adresskonflikt angeschlossen werden können. Wie sich diese Konfiguration der Pins auf die Adresse auswirkt, ist unter 7.3, Table 4 ersichtlich: Abbildung 7.3: LM75B Adresstabelle Die ersten vier Bit sind immer die Folge „1001“. Anschließend wird die Wertigkeit der Bits (Eins oder Null) dadurch bestimmt, ob die Adresspins entweder „HIGH“ (1) 60 7.4 Verwendung des I2C Bus mittels Python oder „LOW“ (0) sind. In dem Fall des vorliegenden Erweiterungsboards wurden alle Adresspins mit Ground verbunden, entsprechen also Null. Dadurch entsteht die fertige Geräteadresse von 1001000 oder 0x48. Das fehlende, letzte Bit wird im I2C Bus verwendet um festzulegen, ob es sich um lesende oder schreibende Anfrage im Bus handelt. Dies wird allerdings durch die verwendete Bibliothek durchgeführt. In unserem Beispiel öffnen wir die entsprechende I2C Verbindung wie folgt: lm75b_file = wpi . wiringPiI2CSetup (0 x48 ) # Verbindung zu LM75B oeffnen if lm75b_file < 0: print ( " Kann den I2C Bus nicht oeffnen ! " ) else : 7.4.2 Register des Sensors In I2C System wird sowohl die Konfiguration, als auch der Datenaustausch über 8 oder 16 Bit tiefe Register erledigt. Der LM75B hat, wie unter 7.4, Table 5 zu sehen ist vier davon: Abbildung 7.4: LM75B Register Das 16 Bit tiefe Temperaturregister (0x00), das 8 Bit tiefe Konfigurationsregister (0x01) sowie zwei 16 Bit tiefe Register für Temperaturschwellwerte bei denen der Sensor unterschiedliche Aktionen unternehmen kann: Hysteresis (0x02) und Overtemperature shutdown (0x03). Damit ist klar, dass wir für die Auswertung der Temperatur das Register 0x00 mit 16 Bit auslesen müssen. lm75_temp = wpi . wiringPiI2CReadReg16 ( lm75b_file , 0) # Register 0 von LM75B in 16 Bit Tiefe auslesen 61 7 Python Programmierung 7.4.3 Interpretation des Temperaturwertes Wie der ausgelesene Wert zu interpretieren ist, findet sich im Bereich 7.4.3, Table 9: Abbildung 7.5: LM75B Temperatur Register Die dort gekennzeichneten Bits D10-D0 enthalten den nötigen, 11 Bit langen Temperaturwert. Die restlichen Bits des LSByte (Stellen 4-0) sind durch das „X“ als „Don’t Care“ gekennzeichnet und sollten ignoriert werden. Am einfachsten erhält man den Temperaturwert, in dem man den ausgelesenen Wert wie im Datenblatt beschrieben in den MSB und den LSB Bereich aufteilt. Der LSB Bereich muss anschließend um fünf Stellen nach rechts geshiftet werden und mit einer sieben verundet werden, um die übrigen Stellen in dem Byte gleich Null zu setzen. Anschließend muss das HSB um drei Stellen nach links geshiftet und mit dem vorbereiten LSB Bereich logisch durch ein Order verbunden werden. Damit werden die beiden Bestandteile sauber zusammengesetzt. Zum Schluss muss nur noch der erhaltene Wert mit 0.125 multipliziert, oder durch acht geteilt werden, um die Temperatur in Grad Celsius zu erhalten. lm75b_hi = ( lm75_temp & 0 xFF ) lm75b_lo = ( lm75_temp >> 8) # In 2x 8 Bit Werte ( High und Low Bit ) umwandeln n = lm75b_hi << 3 | (( lm75b_lo >> 5) & 0 x07 ) # gemaess Datasheet des Sensors aus den ausgelesenen # 2 Bytes die korreten 11 Bits fuer den Temperaturwert # extrahieren und shiften lm75b_temp = n / 8.0 # 11 Bit Wert in Temperatur umwandeln Das gesamte Listing ist im Anhang D.9 einsehbar. 7.4.4 Übungsaufgabe zur Verwendung des I2C Bus Um die gelernten Fähigkeiten zu festigen, soll in dieser Übung eine Temperatursteuerung unter Verwendung des LM75B entwickelt werden. Der Sensor soll zum Start die Umgebungstemperatur messen und diese als Standardtemperatur verwenden. Sollte die Temperatur ein Grad unter diese Temperatur fallen, soll mit der blauen LED angezeigt werden, dass der Raum abgekühlt ist. Sollte die Temperatur hingegen ein Grad über diese Temperatur steigen, soll dies mit der roten LED repräsentiert werden. Die Idealtemperatur soll mit der grünen LED dargestellt werden. Zusätzlich zu den Übergängen dieser Zustände, soll - sofern der Zustand stabil ist - der Name des Zustandes und die aktuelle Temperatur ausgegeben werden. Die Lösung der Aufgabe findet sich im Anhang unter D.10. 62 7.5 Verwendung des SPI Bus mittels Python 7.5 Verwendung des SPI Bus mittels Python Nachdem nun die Kommunikation über den I2C Bus erfolgreich funktioniert, wenden wir uns dem letzten Bauteil auf dem Erweiterungsboard zu, dem MCP3002 2 Kanal 10 Bit Analog/Digital Wandler mit SPI Bus. Damit erweitern wir den RPi um zwei analoge Eingänge. In unserem Beispiel wird der erste Kanal, Kanal 0 dazu genutzt den Wert eines angeschlossenen Lichtsensors / LDR auszulesen. Da es sich um einen 10 Bit Wandler handelt, kann dieser die angelegte analoge Spannung von 0 bis 3,3 V in einem digitalen Wertebereich von 0 bis 1024 (210 ) darstellen. Das bedeutet, dass jede analoge Spannungssteigerung von 3,3 mV sich in einer Erhöhung des digitalen Wertes um 1 auswirkt. Die folgenden technischen Daten lassen sich im Datenblatt des Wandlers unter [17], respektive in der Datei RPi_HTW/Datenblaetter/MCP3002.pdf auf dem Raspberry Pi finden. 7.5.1 Adressierung Wie bereits in Abschnitt 5.3.5 beschrieben haben die SPI Bus Teilnehmer keine eigene Adresse, sondern werden über eine eigene Leitung zum Master (Slave Select) in den Kommunikationsmodus geschaltet. In dem Fall des Erweiterungsboards wurde der MCP3002 auf den Slave Select 0 gelegt, den ersten der beiden Slave Selects. Diese sind in keinem Fall mit den internen beiden ADC Kanälen des MCP3002 zu verwechseln, welche nicht zur Kommunikation dienen, sondern zur Messung von analogen Spannungen - der eigentlichen Aufgabe des MCP3002. Da wir weiterhin die Übertragungsgeschwindigkeit beim Öffnen des SPI Bus angeben müssen, suchen wir im Datenblatt nach den entsprechenden Angaben. Auf Seite drei findet man unter Timing Parameters, Clock Frequency die entsprechenden Angaben: Abbildung 7.6: MCP3002 SPI Bus Geschwindigkeit Da der MCP3002 auf dem Erweiterungsboard mit 3,3 V Spannung versorgt wird, liegt die maximale Geschwindigkeit für den SPI Bus bei 1,2 MHz. Da der Controller des RPi allerdings ganze vielfache bevorzugt, werden wir eine Geschwindigkeit von 1 MHz verwenden - sowie den Slave Select 0. # !/ usr / bin / python import wiringpi2 as wpi from binascii import hexlify from binascii import unhexlify mcp3002_channel =0 if wpi . wiringPiSPISetup (0 ,1000000) < 0: print ( " Kann den SPI Bus nicht oeffnen ! " ) 63 7 Python Programmierung else : 7.5.2 Kommunikation Die Kommunikation beim SPI Bus verläuft bidirektional, in dem eine gewisse Anzahl an Bytes in Form eines Bytebuffers über den Bus versendet, und gleichzeitig wieder von der Gegenstelle mit Daten gefüllt wird. Das heißt, dass nach erfolgter Kommunikation der Sendebuffer mit den Zieldaten überschrieben wurde. Der Ablauf dieser Kommunikation kann im Datenblatt der Abbildung 6-2 entnommen werden: Abbildung 7.7: MCP3002 SPI Kommunikation DIN beziehungsweise „MCU Transmitted Data“ beschreibt dabei die Kommunikation vom RPi zum MCP3002, DOUT beziehungsweise „MCU Received Data“ die umgekehrte Richtung. Wie wir sehen beginnt die Kommunikation im ersten Byte bei DIN mit einem „Don’t Care“, gefolgt von einem feststehenden Startbit. Anschließend folgen drei Bits welche bestimmte Optionen festlegen: „SGL/DIFF“, „ODD/SIGN“ und „MSBF“. Beendet wird das Byte mit weiteren drei „Don’t Care“ Bits. Das zweite Byte besteht völlig aus „Don’t Care“ Bestandteilen, die wir beliebig mit Eins und Null füllen könnten. Für die bessere Lesbarkeit werden wir allerdings alle „Don’t Care“ Bits mit Null füllen. Unser bisheriger Kommunikationsbuffer sieht also so aus: Tabelle 7.11: Vorläufiger Kommunikationsbuffer Bit 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 Mode 0 1 ? ? ? 0 0 0 | 0 0 0 0 0 0 0 0 Die Bedeutung und korrekten Einstellungen für die noch fehlenden Werte von „SGL/DIFF“ und „ODD/SIGN“ kann man in der Tabelle 5-1 nachlesen: 64 7.5 Verwendung des SPI Bus mittels Python Abbildung 7.8: MCP3002 Konfigurationsbits Es handelt sich dabei um Konfigurationsbit mit welchem man die Funktionsart des MCP3002 einstellen kann. „SGL/DIFF“ bestimmt ob der Analog/Digital Wandler entweder die Spannung an einem seiner beiden Kanäle lesen (Einstellung 1) oder ob er den Unterschied zwischen beiden Kanälen feststellen soll (Einstellung 0). Da wir die Spannung am Kanal 0, an dem auch der LDR angeschlossen ist messen wollen, müssen wir das „SGL/DIFF“ Bit auf 1 setzen. In diesem Modus wird das „ODD/SIGN“ Bit dazu genutzt, den Kanal auszuwählen. Ist das Bit auf 0 gesetzt, wird Kanal 0 gemessen, wird es auf 1 gesetzt, wird der Kanal 1 gemessen. Somit sind unsere Einstellungen für „SGL/DIFF“ 1 und für „ODD/SIGN“ 0. Das letzte Bit, „MSBF", sorgt dafür, dass die Kommunikation im MSB Format abläuft, wenn es gesetzt ist. Ansonsten arbeitet der Wandler mit LSB. Wir lassen diese Einstellung auf 0. Damit steht unser Buffer für die Kommunikation fest: Tabelle 7.12: Kommunikationsbuffer Bit 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 Mode 0 1 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 Wir müssen diese Werte nur entsprechend in Python in das entsprechende Format bringen und auf Slave Select 0 übertragen: buffer =((6+ mcp3002_channel ) < <12) buffer = ' {0: x } '. format ( int ( buffer ) ) # Wandle den dezimalen Integer in einen # hexadezimalen String um , ohne das Praefix # 0 x davorzustellen buffer = unhexlify ( buffer ) # Wandle den Hex String in einen Byte String um if ( wpi . wiringPiSPIDataRW (0 , buffer ) == -1) : # Anforderung auf den SPI Bus auf Slave # Select 0 schreiben und 65 7 Python Programmierung # gleichzeitig ( bi - direktional ) mit der # Antwort den Buffer ueberschreiben print ( " Schreibfehler auf SPI Bus !\ n " ) else : Nachdem die Kommunikation beendet ist, befindet sich im Buffer bereits die Antwort in Form eines Byte Strings, welche dann nur noch in einen Integer Wert umgewandelt werden muss: buffer = hexlify ( buffer ) # Wandle den Byte String nach Hex um buffer = int ( buffer , 16) # Wandle den Hex String in einen # dezimalen Integer Wert um Dieser Wert kann nun noch formatiert und ausgegeben werden. Das gesamte Listing ist im Anhang D.11 einsehbar. Zusätzliches zu der hier beschriebenen, manuellen Kommunikation bietet wiringpi2 bereits eine Bibliothek, welche die Kommunikation mit dem MCP3002 vereinfacht. Das entsprechende Listing befindet sich im Anhang D.12 7.5.3 Übungsaufgabe zur Verwendung des SPI Bus Nachdem nun die Nutzung des SPI Bus erlernt wurde, soll in der nachfolgenden Übungsaufgabe der Einsatz des LDR als Näherungssensor realisiert werden: Um die Messwerte leichter zu visualisieren, soll dazu die Bibliothek curses verwendet werden. Mit dieser Bibliothek kann in der Konsole ein virtuelles Fenster erzeugt werden, in dessen Koordinatensystem man zum Beispiel eine horizontale Linie zeichnen kann. Wichtig ist dabei zu erwähnen, dass diese Bibliothek nicht in IDLE läuft und daher der Aufruf direkt aus LXTerminal wie in Abschnitt 7.2.1 als 2) und 3) beschrieben erfolgen muss. Wegen dem Aufruf von curses wird das Programm in diesem Fall durch das Drücken einer beliebigen Taste beendet und sollte nicht per Strg + C abgebrochen werden. # !/ usr / bin / python import curses from time import sleep screen = curses . initscr () # curses in der Konsole initialisieren dims = screen . getmaxyx () # y , x Groesse des Bildschirms in Array ablegen # dims [0] entspricht y Wert # dims [1] entspricht x Wert screen . nodelay (1) # nodelay Modus aktivieren um screen . getch () # im non - Blocking Modus zu betreiben while ( screen . getch () == -1) : # fuehre die Schleife aus solange keine 66 7.5 Verwendung des SPI Bus mittels Python # Taste gedrueckt wurde screen . erase () # Bildschirm loeschen screen . hline (20 , 0 , ' - ' , 40) # horinzontale Linie aus - Zeichen malen # hline (y Koordinate , x Beginn , ch Zeichen , n Laenge ) screen . refresh () # Bildschirm neu laden sleep (0.1) curses . endwin () # Beenden Die Aufgabe wird nun sein, dieses Skript dahingehend zu ergänzen, dass die horizontale Linie jeweils den aktuellen Messwert des an den MCP3002 angeschlossenen LDR anzeigt. Wichtig wird dabei sein, jeweils zum Start des Skriptes den aktuellen Messwert als Maximalwert zu erfassen, sowie den Wert jeweils korrekt zu skalieren, damit der Lichtsensor als Eingabegerät für z.B. ein Spiel verwendbar werden könnte. Die Lösung befindet sich im Anhang D.13. 67 8 Mathematica In dem letzten Kapitel dieser Arbeit soll die Einführung in die Nutzung der Software Mathematica und deren Verwendung mit den GPIO Pins im Vordergrund stehen. Dabei soll gegen Ende des Kapitels sowohl die grundlegende Nutzung der Software selbst, wie auch die Verwendung in Kombination mit dem Erweiterungsboard verständlich geworden sein. Diese Software könnte besonders in den Vorlesungen „Mathematik 13“, sowie „Informatikgrundlagen“ und „Graphentheorie“ Verwendung finden. 8.1 Grundlagen Die Software Wolfram Mathematica ist ein mathematisch-naturwissenschaftliches Programm zur Lösung unterschiedlichster Probleme. Dies beinhaltet die Lösung von Gleichungen, Zeichnung von Plots, Darstellung und Visualisierung von Problemen sowie Datenanalyse. Damit kann Mathematica im Bereich der Mathematik, Computerwissenschaften, Physik, Biologie, Medizin, Ingenieurswesen, Finanz- und Sozialwissenschaften eingesetzt werden. Die Besonderheiten dieser Software umfassen neben zahlreichen Sonderfunktionen wie Cloud- und Grindcomputing, wissensbasiertem Programmieren, Integration neuer Technologien wie Internet of Things und webbasierten Sensoren auch eine leistungsfähige API, sowie die Möglichkeit eigene Programme mittels des MathLink Protokolls als Datenquelle und -senke in Wolfram zu integrieren. Aufgrund des großen Funktionsumfangs und der Leistungsfähigkeit dieser Software ist diese im Normalfall für Studenten nur eingeschränkt oder gar nicht zugänglich. Durch die kostenlose Integration der aktuellen Version von Wolfram Mathematica in Raspbian, dem Betriebssystem des Raspberry Pi, wird dieses Werkzeug also für einen größeren Nutzerkreis verfügbar. Weiterhin können durch die Nutzung des Raspberry Pi als Schnittstelle auch I2C, SPI und GPIO Sensoren und Aktoren mittels MathLink Protokolls von anderen Raspberry Pis oder vollwertigen Mathematica Arbeitsplätzen verwendet werden. 8.2 Benutzung Mathematica ist auf dem RPi in zwei Varianten installiert: wolfram, die CLI basierte Form von Mathematica, welche ausschließlich zur Verwendung im reinen Textmodus und in Verbindung mit Skripten gedacht ist, sowie mathematica, welche alle Features in der grafischen Benutzeroberfläche bietet - inklusive der Ausgabe von Grafiken und Plots. Für unsere Einsatzzwecke werden wir mathematica einsetzen. 69 8 Mathematica 8.2.1 Beispiele Free-form input Zu berechnende Ausdrücke werden in Mathematica einfach in das sogenannte Sketchbook, dem Hauptfenster der Software eingegeben und durch Bestätigung mittels ⇑ + Enter ausgewertet. Diese Form von Eingabe nennt sich „Free-form input“ und wird von Mathematica offline auf dem RPi gelöst. So können Berechnungen wie 1+1, 3/4*(5-2)^2 oder ganze Gleichungen (Solve[x^3+x^2-8x-12==0,x]) und auch bestimmte Integrale (Integrate[Sin[x],{x,0,Pi}]) einfach und direkt gelöst werden. Die möglichen Befehle und Verwendungsmöglichkeiten können in der ausführlichen Sprachreferenz von Wolfram unter http://reference.wolfram.com/language/ nachgelesen werden. 8.2.2 Beispiele Wolfram Alpha query Wesentlich leistungsfähiger ist allerdings die Nutzung der „Wolfram Alpha query“, welches die Eingaben online an die Wolfram Alpha Compute Engine weiterleitet. Wie in Abbildung 8.1 gezeigt, erfolgt die Umstellung dieser Eingabe per Klick auf das „+“ Zeichen im Sketchbook. Abbildung 8.1: Umstellung der Eingabeart in Wolfram Wichtig ist, dass die Nutzung dieses Softwareteils nur bei aktiver Internetanbindung möglich ist. Die Stärke von Wolfram Alpha liegt in der Auswertung natürlicher Sprache in mathematische Zahlen. Kombiniert mit der Menge der in der Compute Engine 70 8.2 Benutzung hinterlegten Daten, sind dadurch interessante Auswertungen mit sehr geringem Aufwand möglich. So zum Beispiel die wissenschaftlich nicht relevante Berechnung der Anzahl aller Einwohner von Frankreich mal der Höhe des Eiffelturms: Abbildung 8.2: Berechnung mittels Wolfram Alpha Weitere Beispiele und mögliche Einsatzzwecke sind in der Dokumentation von Wolfram Alpha unter http://www.wolframalpha.com/examples/ zu finden. 71 8 Mathematica 8.3 Verwendung mittels Erweiterungsboard Wie bereits erwähnt können die Sensoren und Aktoren des Erweiterungsboards auch mittels Mathematica genutzt werden, um z.B. Temperatur- oder Helligkeitsdaten zu sammeln und grafisch auszuwerten. Es wäre auch möglich die Schalter des Boards zur Zählung von z.B. Besuchern einer Veranstaltung oder der Auslastung einer Straße einzusetzen, wie es häufig für statistische Erfassungen getan wird. Damit diese Peripherie in Mathematica verfügbar wird, muss zuerst die entsprechende Library eingebunden werden. Da es für Mathematica noch keine Erweiterung zur Nutzung der I2C und SPI Bus Systeme gibt, wurde im Rahmen dieser Arbeit unter Nutzung von C, wiringpi2 und dem MathLink Protokoll eine eigene geschrieben. Der Quellcode für diese wpi genannte Library kann auf dem Raspberry Pi im Unterverzeichnis RPi_HTW/Mathematica/ des Hauptnutzers pi, beziehungsweise im Anhang unter D.14 und D.15 gefunden werden. Erzeugt wird das fertige Programm unter Aufruf von mcc wpi.c wpi.tm -o wpi -luuid -lwiringPi. Wichtig zu erwähnen ist, dass - unabhängig ob nun Mathematica oder Wolfram genutzt werden soll - beide Programme mit root Rechten über die CLI gestartet werden müssen. Sonst kann der Zugriff auf die GPIO nicht erfolgen. Wir starten also Mathematica durch den Befehl sudo mathematica im LXTerminal. Nachdem die Software geladen ist, können wir durch den Befehl SetDirectory["/home/pi/RPi_HTW/Mathematica"] das Heimverzeichnis von Mathematica temporär ändern und mit dem weiteren Befehl link = Install["wpi"] die Library wpi laden. Solange die Sitzung von Mathematica beziehungsweise Wolfram aktiv ist, sind ab nun folgende weitere Befehle verfügbar: setPinMode[pin, mode] setDigitalWrite[pin, value] setPwmWrite[pin, value] getDigitalRead[pin] getLM75B[] getMCP3002[channel] Zu jedem Befehl kann die entsprechende Hilfe durch das Vorstellen eines Fragezeichens (z.B. ?getLM75B) und die anschließende Auswertung per ⇑ + Enter ausgegeben werden. Die ersten vier angegebenen Befehle sind die bekannten Kommandos der wiringpi2 Bibliothek, die anderen beiden basieren auf dem bereits in Abschnitt 7.4 und Abschnitt 7.5 entwickelten Python Code zur Nutzung des LM75B Temperatur Sensors und des MCP3002 ADC. Dementsprechend einfach ist die Verwendung der GPIOs in Mathematica, um zum Beispiel die grüne LED zu aktiveren: setPinMode[18, 1] (* Definiert den Port der gruenen LED als Ausgabe *) setDigitalWrite[18, 1] (* Setzt den Port der gruenen LED auf HIGH *) 72 8.3 Verwendung mittels Erweiterungsboard Auch die Überprüfung des ersten Schalters und die entsprechende Ausgabe des Zustandes auf die erste LED ist sehr einfach: setPinMode[18, 1] (* Definiert den Port der gruenen LED als Ausgabe *) setPinMode[4, 0] (* Definiert den Port des North Switches als Eingabe *) If[getDigitalRead[4]==1, setDigitalWrite[18,1], setDigitalWrite[18,0]] (* Sollte der North Switch zur Zeit der Auswertung gedrueckt wurden sein, schalte die gruene LED ein, sonst aus *) Als nächstes sollen die Möglichkeiten von Mathematica in der grafischen Auswertung aufgezeigt werden, hier in Verbindung mit dem Temperatur Sensor: t={} (* Definiert die leere Liste t, fuer die Temperaturwerte *) RunScheduledTask[(AppendTo[t,getLM75B[]]),1]; (* Definiert einen Task der jede Sekunde ablaeuft und den aktuellen Wert des Temperatur Sensors in die Liste schreibt *) Dynamic[ListLinePlot[t,Joined->True,PlotRange->Automatic]] (* Erzeugt einen dynamischen Plot in Form einer Linie welcher sich mit jedem neuen Wert der Liste neu zeichnet und sich selbst skaliert *) Der entstehende Plot wird mit der Erweiterung der Liste dynamisch aktualisiert bis entweder eine gegebene, zeitliche Grenze erreicht wurde oder z.B. unter „Evaluation“ die Option „Dynamic Updating Enabled“ abgeschaltet wurde. Abbildung 8.3: Plot des Temperatur Sensors über 400 Sekunden Als letzten Punkt wollen wir die Messwerte des Lichtsensors in Form eines analogen Messwerkes darstellen. Dazu verwenden wir wieder die Methode RunScheduledTask 73 8 Mathematica um die Messwerte zu erfassen. Das Auswertung wird diesmal jedoch nicht über einen ListLinePlot, sondern über AngularGauge erfolgen: RunScheduledTask[val = getMCP3002[0], 1] (* Definiert einen Task der jede Sekunde ablaeuft und den aktuellen Wert des Lichtsensors in eine Variable schreibt *) AngularGauge[Dynamic[val], {0, 1023}] (* Erzeugt einen dynamischen Plot in Form eines analogen Messwerkes welches sich mit jedem neuen Wert in der Variable neu aktualisiert. Der Wertebereich wird mit 0 - 1023 vorgegeben *) Abbildung 8.4: Darstellung des Lichtsensor Wertes als analoges Messwerk Die Verbindung zur Library kann jederzeit durch den Befehl Uninstall[link] beendet werden, sollte z.B. ein Fehler auftreten. Weiterhin können alle Zellen und Auswertungen einzeln markiert, gelöscht oder angehalten werden. Es empfiehlt sich möglichst wenige dynamische Objekte gleichzeitig zu erstellen, um den RPi nicht völlig auszulasten. 74 9 Fazit 9.1 Zusammenfassung Im Rahmen dieser Bachelor Thesis wurde der Raspberry Pi dazu genutzt unterschiedliche Themen des Studienganges „Praktische Informatik“ aufzugreifen und deren Lehre anhand von praktischen Beispielen und konkreten Projekten zu unterstützen. Dies umfasst folgende Punkte: Tabelle 9.1: Stakeholder dieser Thesis Veranstaltung / Labor Aufgabe Mikroprozessortechnik Evaluation von Beagle Bone Black und Raspberry Pi Elektrotechnik Labor Erstellung eines Grundlagen Handbuches zum RPi Systemtechnik Labor Erstellung Standard Image zur Verwendung im STL Betriebssystem Einführung Praktisches Bash Projekt zur Vorbereitung der Klausur Systemmanagement & Sicherheit Einführung in die Sprache Python Programmierung 1 Darstellung Nachteile ineffizienter Programmierung Digitaltechnik 1 Binäre Logik / Binärer Zähler Rechnerarchitektur Grundlagen I2C / SPI Bussysteme & Verwendung Theoretische Informatik Primitiver Automat mit I2C / SPI Sensoren Mathematik 1-3 Vorstellung von Wolfram Alpha / Mathematica Darüber hinaus wurden zum Erreichen dieser Ziele, als Bestandteil dieser Thesis, das in diesem Dokument besprochene Erweiterungsboard entwickelt und in zehnfacher Stückzahl hergestellt, um anschließend mit den gleichzeitig vorbereiten Raspberry Pis aktiv in der Lehre der HTW Saar eingesetzt zu werden. Zum Abschluss lässt sich sagen, dass die gesteckten Ziele dieser Arbeit im Rahmen der Möglichkeiten erreicht werden konnten und sich der Raspberry Pi trotz seines geringen Preises als gute Plattform für den Bereich der Forschung und Lehre erwiesen hat. 75 9 Fazit 9.2 Ausblick Aufgrund der gegebenen, zeitlichen Begrenzung dieser Thesis, war es leider nicht mehr möglich die Assembler Programmierung des verbauten ARMv6 SoC zu erläutern, oder eine Einführung in die objektorientierte Programmierung unter Python zu geben, was den gegebenen Rahmen gesprengt hätte. Neben diesen Projekten ließen sich auch weitere Möglichkeiten finden den Raspberry Pi in Zukunft aktiv in die Lehre einfließen zu lassen: Tabelle 9.2: Ausblick auf mögliche Projekte Veranstaltung / Labor Aufgabe Mikroprozessortechnik Assembler Programmierung und Betriebssysteme [3] Betriebssysteme Verwendung RPi mit RTOS ChibiOS [1] Parallele Programmierung Nutzung RPi GPU zur parallelen Berechnung [22] Verteilte Systeme 1 Einführung in MPICH [5] Netzwerktechnik Praktische Konfiguration von IPv4/IPv6 Servern Weitere mögliche Anwendung wäre der Einsatz in der Vorlesung „Einführung in die Robotik“, als Plattform für ein „Gamification“ Projekt, bei interdisziplinäre Arbeiten im Bereich der Elektrotechnik bzw. Medizin- und Biotechnologie oder als Ausstellungsobjekt für den Tag der offenen Tür. 76 Literatur [1] Steve Bate. ChibiOS/RT on the Raspberry Pi. Okt. 2012. URL: http://www.stevebate. net/chibios-rpi/GettingStarted.html. [2] Charles C. Mann. Eben Upton, 34. 2012. com/tr35/profile.aspx?TRID=1307. [3] Alex Chadwick. Baking Pi - Operating Systems Development. Juli 2013. URL: http: //www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/. [4] Arthur C. Clarke. Profiles of the Future: An Inquiry Into the Limits of the Possible. An Indigo paperback. Indigo, 2000. ISBN: 9780575402775. URL: http://books. google.de/books?id=fVp0PwAACAAJ. [5] Simon J. Cox. „Iridis-pi: a low-cost, compact demonstration cluster“. English. In: Cluster Computing 17.2 (2014), S. 349–358. ISSN: 1386-7857. DOI: 10.1007/s10586013-0282-7. URL: http://dx.doi.org/10.1007/s10586-013-0282-7. [6] Tony Dicola. Embedded Linux Board Comparison. Adafruit. Mai 2014. URL: https: //learn.adafruit.com/embedded-linux-board-comparison/overview. [7] EIA Engineering Dept. Interface between data terminal equipment and data communication equipment employing serial binary data interchange. EIA standard. Electronic Industries Association, Engineering Dept., 1969. URL: http://books.google.de/ books?id=Tp08AAAAIAAJ. [8] Elatllat. RPiconfig. Juni 2014. URL: http://elinux.org/RPiconfig. [9] Prof. Dr. Helmut G. Folz. Programmierung 1: Kontrollstrukturen. HTW. Mai 2013. URL : http://www.htwsaar.de/ingwi/fakultaet/personen/profile/helmutfolz/prog1/folien2013/folien2013-00-08.zip/view. [10] Geertivp. RPi Serial Connection. Feb. 2014. URL: http://elinux.org/RPi_Serial_ Connection. [11] Matt Hawkins. Raspberry Pi B+ GPIO Header Details And Pinout. Juni 2014. URL: http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-headerdetails-and-pinout/. [12] Heinrich Hübscher, Carsten Rathmann, Klaus Richter, Hans J Petersen und Dirk Scharf. IT-Handbuch IT-Systemelektroniker/-in Fachinformatiker/-in: 7. Auflage, 2011. 7. Auflage. Westermann Schulbuch, Jan. 2011. ISBN: 9783142250427. URL: http: //amazon.de/o/ASIN/3142250425/. [13] Gordon Henderson. Understanding SPI on the Raspberry Pi. Aug. 2012. URL: https: //projects.drogon.net/understanding-spi-on-the-raspberry-pi/. URL : http://www2.technologyreview. 77 Literatur [14] LM75B. 6. Aufl. NXP. Aug. 2014. URL: http://www.nxp.com/documents/data_ sheet/LM75B.pdf. [15] F. Leens. „An introduction to I2C and SPI protocols“. In: Instrumentation Measurement Magazine, IEEE 12.1 (Feb. 2009), S. 8–13. ISSN: 1094-6969. DOI: 10.1109/MIM. 2009.4762946. [16] Gert van Loo. GPIO Pads Control2. Aug. 2012. URL: http://de.scribd.com/doc/ 101830961/GPIO-Pads-Control2. [17] MCP3002. E. Microchip. Nov. 2011. URL: http://ww1.microchip.com/downloads/ en/DeviceDoc/21294E.pdf. [18] H.J. Morrison und R.H. Baer. „Microcomputer controlled game“. Pat. US4207087 A. US Patent 4,207,087. Juni 1980. URL: http : / / www . google . com / patents / US4207087. [19] NXP. I2C-bus specification. 6. Aufl. NXP Semiconductor. Apr. 2014. //www.nxp.com/documents/user_manual/UM10204.pdf. [20] PBL. Raspberry Pi Schematics R2.1. Nov. 2013. URL: http : / / www . raspberrypi . org/documentation/hardware/raspberrypi/schematics/Raspberry-Pi-Rev2.1-Model-AB-Schematics.pdf. [21] Philips. I2S-bus specification. Philips Semiconductors. Feb. 1986. sparkfun.com/datasheets/BreakoutBoards/I2SBUS.pdf. [22] Eben Upton. GPGPU Hacking on the Pi. Juni 2014. URL: http://www.raspberrypi. org/gpgpu-hacking-on-the-pi/. [23] Eben Upton. Introducing Turbo Mode: Up to 50% more Performance for free. Sep. 2012. URL : http : / / www . raspberrypi . org / introducing - turbo - mode - up - to - 50 more-performance-for-free/. [24] Liz Upton. Raspberry Pi at Buckingham Palace, 3 Million Sold. Juni 2014. URL: http: //www.raspberrypi.org/raspberry-pi-at-buckingham-palace-3-millionsold/. [25] Roland Woitowitz. Digitaltechnik. 6. Aufl. Springer, Aug. 2011. 78 URL : URL : http : https : / / Abbildungsverzeichnis 3.1 3.2 3.3 3.4 3.5 SD Formatter . . . . . . . . . . . . . . . . . . SD Formatter Optionen . . . . . . . . . . . . . Win32 Disk Imager . . . . . . . . . . . . . . . noobs nach dem Entpacken auf die SD Karte Installation von Raspbian unter noobs . . . . . . . . . 13 13 14 16 17 4.1 4.2 raspi-config . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Raspbian Desktop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 22 5.1 5.2 GPIO Schnittstelle Raspberry Pi Modell A / B / B+ [11] . . . . . . . . . . Erweiterungsboard und Routing der Komponenten . . . . . . . . . . . . 31 39 6.1 6.2 Simon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Flowchart Simon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 44 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 Festlegung des binären Wertes jeder LED LM75B Pinout . . . . . . . . . . . . . . . . LM75B Adresstabelle . . . . . . . . . . . . LM75B Register . . . . . . . . . . . . . . . LM75B Temperatur Register . . . . . . . . MCP3002 SPI Bus Geschwindigkeit . . . . MCP3002 SPI Kommunikation . . . . . . MCP3002 Konfigurationsbits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 60 60 61 62 63 64 65 8.1 8.2 8.3 8.4 Umstellung der Eingabeart in Wolfram . . . . . . . . . . . Berechnung mittels Wolfram Alpha . . . . . . . . . . . . . . Plot des Temperatur Sensors über 400 Sekunden . . . . . . Darstellung des Lichtsensor Wertes als analoges Messwerk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 71 73 74 C.1 Erweiterungsboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 TABELLENVERZEICHNIS Tabellenverzeichnis 80 2.1 2.2 Übersicht [6] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I/O und Peripherie [6] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 4.1 Einstellungen für eduroam . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.1 Erweiterungsboard und Routing der Komponenten . . . . . . . . . . . . 39 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 Arithmetische Operatoren . . . . . . . . . . . Vergleichsoperatoren . . . . . . . . . . . . . . Binäres Und . . . . . . . . . . . . . . . . . . . Binäres Oder . . . . . . . . . . . . . . . . . . . Binäres XOR . . . . . . . . . . . . . . . . . . . Binäres 1er Komplement . . . . . . . . . . . . Binäre, bitweise Operatoren . . . . . . . . . . Laufzeiten beider Algorithmen in Sekunden LEDs auf dem Erweiterungsboard . . . . . . Schalter auf dem Erweiterungsboard . . . . . Vorläufiger Kommunikationsbuffer . . . . . . Kommunikationsbuffer . . . . . . . . . . . . . . . . . . . . . . . . . 51 51 52 52 52 53 53 56 57 58 64 65 9.1 9.2 Stakeholder dieser Thesis . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausblick auf mögliche Projekte . . . . . . . . . . . . . . . . . . . . . . . . 75 76 A.1 Raspbian Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Per apt-get installierte Pakete . . . . . . . . . . . . . . . . . . . . . . . . . A.3 Manuell installierte Pakete . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 85 85 B.1 Raspberry Pi der HTW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 C.1 Erweiterungsboard und Routing der Komponeten . . . . . . . . . . . . . 90 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listings Code/boardTest.c . . . . . Code/gpio.sh . . . . . . . Code/demoLed.sh . . . . Code/demoSwitch.sh . . . Code/simon.sh . . . . . . Code/uebungAusgabe.py Code/uebungEingabe.py Code/binaryCounter.py . Code/lm75b.py . . . . . . Code/uebungI2C.py . . . Code/mcp3002.py . . . . Code/mcp3002lib.py . . . Code/uebungSPI.py . . . Code/wpi.c . . . . . . . . Code/wpi.tm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 95 97 98 99 102 103 104 105 106 108 109 109 110 112 81 Abkürzungsverzeichnis ADC Analog Digital Converter API Application Programming Interface CAN Controller Area Network CSI Camera Serial Interface CLI Command Line Interface DSI Display Serial Interface GPIO General-purpose input/output GPS Global Positioning System I2C Inter-Integrated Circuit I2S Inter-Integrated Sound IDE Integrated Development Environment LDR Light Dependent Resistor MCU Microcontroller Unit PRU Programmable Realtime Unit PWM Pulse-width modulation RPi Raspberry Pi SoC System on a chip SPI Serial Peripheral Interface TWI Two Wire Interface UART Universal asynchronous receiver/transmitter 82 Anhang 83 A Vorgefertigtes Raspbian Image A.1 Übersicht Tabelle A.1: Raspbian Übersicht Raspbian Version June 2014 (20.06.2014) Kernel 3.12.28+ #712 PREEMPT Tue Sep 16 User / Passwort pi / rpi root kein Passwort gesetzt / gesperrt IP per DHCP A.2 Zusätzlich installierte Pakete Tabelle A.2: Per apt-get installierte Pakete Name python-setuptools python-dev cpufrequtils scrot epiphany-browser uuid-dev gfortran screen minecraft-pi python-minecraftpi Tabelle A.3: Manuell installierte Pakete Name URL wiringpi2 git://git.drogon.net/wiringPi wiringpi2-python https://github.com/Gadgetoid/WiringPi2-Python rpi-serial-console https://github.com/lurch/rpi-serial-console MPICH 3.1.2 http://www.mpich.org/static/tarballs/3.1.2/mpich-3.1.2.tar.gz MCPIPY Examples https://github.com/brooksc/mcpipy 85 87 Name rpi01 rpi02 rpi03 rpi04 rpi05 rpi06 rpi07 rpi08 rpi09 rpi10 Nr 1 2 3 4 5 6 7 8 9 10 RS RS RS RS RS RS RS RS RS RS Hersteller B.1 Übersicht Samsung Samsung Samsung Samsung Samsung Samsung Samsung Samsung Samsung Samsung Speicher B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 B Rev. 2.0 Modell B8:27:EB:48:9A:63 B8:27:EB:BD:BA:96 B8:27:EB:10:C8:9D B8:27:EB:89:B0:4B B8:27:EB:2D:26:DC B8:27:EB:1E:D8:E7 B8:27:EB:51:29:89 B8:27:EB:61:B4:4C B8:27:EB:CB:3D:35 B8:27:EB:81:B9:6C MAC RS RS RS RS RS RS RS RS RS RS Netzteil Tabelle B.1: Raspberry Pi der HTW B Raspberry Pi Hardware HTW Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 Intenso Class 10 SD Card x x x x x x x x x x SD Karte ok x x x x x x x x x - 1 GHz Boot? C Erweiterungsboard LM75B Nor t h Eas t Wes t Sout h MCP3002 Abbildung C.1: Erweiterungsboard 89 C Erweiterungsboard Tabelle C.1: Erweiterungsboard und Routing der Komponeten Bauteil Bemerkung GPIO LED North grün, PWM 18 LED East rot 23 LED West gelb 25 LED South blau 24 Switch North Pull-Down 4 Switch East Pull-Down 17 Switch West Pull-Down 22 Switch South Pull-Down 27 LM75B SDA 2 SCL 3 MOSI 10 MISO 9 SCLK 11 CS / SS 8 MCP3002 90 D Code Listings Alle Code Listings stehen unter http://www.nico-maas.de/RPi_HTW.tar.gz zum Download bereit. Die auf dem RPi vorinstallierten Listings enthalten nicht die Lösungen zu den gestellten Übungen um diese nicht vorweg zu nehmen. D.1 boardTest.c /* * boardTest . c : * Programm zum halbautomatischen Test * des Erweiterungsboards und Beispiel * zur Nutzung der GPIOs mit wiringPi2 und C * Testet * - LEDs * - PWM * - Schalter * - I2C LM75B * - SPI MCP3002 */ // Include wiringPi # include < stdio .h > # include < wiringPi .h > // Include and Define I2C # include < wiringPiI2C .h > # include < stdlib .h > # define lm75b_addr 0 x48 int lm75b_file ; int n ; int lm75_temp ; signed char lm75b_hi ; signed char lm75b_lo ; float lm75b_temp ; // Include and Define SPI # include < stdint .h > # include < wiringPiSPI .h > # define ADCCHANNEL 0 // LED Pins # define LEDNORTH 18 # define LEDEAST 23 # define LEDWEST 25 # define LEDSOUTH 24 // Switch Pins # define SWITCHNORTH 4 91 D Code Listings # define SWITCHEAST 17 # define SWITCHWEST 22 # define SWITCHSOUTH 27 // PWM Variable int bright ; int i ; int main ( void ) { wiringPiSetupGpio () ; // wiringPi mit GPIO Bennungschema intialisieren /* * LED Test */ pinMode ( LEDNORTH , OUTPUT ) ; pinMode ( LEDEAST , OUTPUT ) ; pinMode ( LEDWEST , OUTPUT ) ; pinMode ( LEDSOUTH , OUTPUT ) ; // LED Pins als Ausgabe definieren printf ( " LED Test beginnt \ n " ) ; delay (750) ; printf ( " NORTH : LED gruen \ n " ) ; digitalWrite ( LEDNORTH , HIGH ) ; // LED Pin North aktivieren delay (750) ; printf ( " EAST : LED rot \ n " ) ; digitalWrite ( LEDEAST , HIGH ) ; delay (750) ; printf ( " WEST : LED gelb \ n " ) ; digitalWrite ( LEDWEST , HIGH ) ; delay (750) ; printf ( " SOUTH : LED blau \ n " ) ; digitalWrite ( LEDSOUTH , HIGH ) ; delay (2000) ; digitalWrite ( LEDNORTH , LOW ) ; digitalWrite ( LEDEAST , LOW ) ; digitalWrite ( LEDWEST , LOW ) ; digitalWrite ( LEDSOUTH , LOW ) ; // LED Pins deaktivieren printf ( " LED Test beendet \ n " ) ; /* * PWM Test */ pinMode ( LEDNORTH , PWM_OUTPUT ) ; // LED Pin North als PWM Ausgang definieren 92 D.1 boardTest.c printf ( " PWM Test beginnt \ n " ) ; for ( i =0; i < 4; i ++) { for ( bright = 0 ; bright < 1024 ; ++ bright ) { pwmWrite ( LEDNORTH , bright ) ; // LED Pin mit PWM Wert ansteuern . delay (1) ; } for ( bright = 1023 ; bright >= 0 ; -- bright ) { pwmWrite ( LEDNORTH , bright ) ; delay (1) ; } } printf ( " PWM Test beendet \ n " ) ; /* * Switch Test */ pinMode ( SWITCHNORTH , INPUT ) ; pinMode ( SWITCHEAST , INPUT ) ; pinMode ( SWITCHWEST , INPUT ) ; pinMode ( SWITCHSOUTH , INPUT ) ; // Switch Pins als Eingabe definieren printf ( " Switch Test beginnt \ n " ) ; printf ( " NORTH : Switch druecken \ n " ) ; while ( digitalRead ( SWITCHNORTH ) == LOW ) // So lange der Switch North nicht gedrÃ×ckt ist , warten delay (1) ; printf ( " NORTH : Switch ok \ n " ) ; printf ( " EAST : Switch druecken \n " ) ; while ( digitalRead ( SWITCHEAST ) == LOW ) delay (1) ; printf ( " EAST : Switch ok \ n " ) ; printf ( " WEST : Switch druecken \n " ) ; while ( digitalRead ( SWITCHWEST ) == LOW ) delay (1) ; printf ( " WEST : Switch ok \ n " ) ; printf ( " SOUTH : Switch druecken \ n " ) ; while ( digitalRead ( SWITCHSOUTH ) == LOW ) delay (1) ; printf ( " SOUTH : Switch ok \ n " ) ; printf ( " Switch Test beendet \ n " ) ; 93 D Code Listings /* * LM75B Sensortest * Original von http :// www . keesmoerman . nl / raspberry . html * Fehlerkorrektur fÃ×r falschen Bus von Nico Maas */ printf ( " LM75B Temperatursensor Test beginnt \ n " ) ; if (( lm75b_file = wiringPiI2CSetup ( lm75b_addr ) ) == -1) { printf ( " Kann den I2C Bus nicht oeffnen !\ n " ) ; return -1; } // Verbindung zu LM75B oeffnen for ( i =0; i < 10; i ++) { lm75_temp = wiringPiI2CReadReg16 ( lm75b_file , 0) ; // Register 0 von LM75B in 16 Bit Tiefe auslesen lm75b_hi = ( lm75_temp & 0 xFF ) ; lm75b_lo = ( lm75_temp >> 8) ; // In 2 x 8 Bit Werte ( High und Low Bit ) umwandeln n = lm75b_hi << 3 | (( lm75b_lo >> 5) & 0 x07 ) ; /* gemaess Datasheet des Sensors aus den ausgelesenen 2 Bytes die korreten 11 Bits fÃ×r den Temperaturwert extrahieren und shiften */ lm75b_temp = ( float ) n / 8; // 11 Bit Wert in Temperatur umwandeln printf ( " LM75B : %4.2 f Grad Celsius \ n " , lm75b_temp ) ; // Temperatur mit 2 Nachkommastellen ausgeben delay (750) ; } printf ( " LM75B Temperatursensor Test beendet \ n " ) ; /* * MCP3002 ADC Test * Angepasst von http :// raspberrypihobbyist . blogspot . de /2012/12/ analog - interface . html */ printf ( " MCP3002 ADC Test beginnt \ n" ) ; // SPI Daten von MCP3002 Chip lesen , 2 moegliche Kanaele (0 und 1) int readadc ( adcnum ) { uint8_t buff [2]; if (( adcnum > 1) || ( adcnum < 0) ) { return -1; } // Nur MCP Kanal 0 und 1 zulassen buff [0] = (6+ adcnum ) < <4; buff [1] = 0; // korrekte Anfrage fuer MCP3002 gemaess Datenblatt erzeugen wiringPiSPIDataRW (0 , buff , 2) ; // Anfrage absenden und Antwort in den Puffer schreiben 94 D.2 gpio.sh } return (( buff [0]&3) << 8) + buff [1]; // Wert aus Puffer shiften if ( wiringPiSPISetup (0 , 1000000) < 0) { return -1 ; } /* WiringPi SPI API initalisieren auf Slave Select / SPI Kanal 0 mit Geschwindigkeit 1 MHz */ for ( i =0; i < 10; i ++) { // Wert von MCP3002 , Kanal 0 ( LDR ) ausgeben printf ( " MCP3002 - Channel 0: % d \ n " , readadc ( ADCCHANNEL ) ) ; delay (750) ; } printf ( " MCP3002 ADC Test beendet \ n" ) ; } return 0 ; D.2 gpio.sh # !/ bin / bash # LED # GPIO als Ausgang deklarieren und Hilfsfunktionen fuer Steuerung definieren # LED gruen , norden gpio export 18 out ledNorthOn () { gpio -g write 18 1 } ledNorthOff () { gpio -g write 18 0 } # LED rot , east gpio export 23 out ledEastOn () { gpio -g write 23 1 } ledEastOff () { gpio -g write 23 0 95 D Code Listings } # LED gelb , west gpio export 25 out ledWestOn () { gpio -g write 25 1 } ledWestOff () { gpio -g write 25 0 } # LED blau , south gpio export 24 out ledSouthOn () { gpio -g write 24 1 } ledSouthOff () { gpio -g write 24 0 } # LED , alle ledOn () { gpio -g write gpio -g write gpio -g write gpio -g write } ledOff () { gpio -g gpio -g gpio -g gpio -g } write write write write 18 23 25 24 1 1 1 1 18 23 25 24 0 0 0 0 ledBlinkFast () { for i in {0..1} do ledOn sleep 0.25 ledOff sleep 0.25 done } 96 D.3 demoLed.sh ledBlink () { for i in {0..1} do ledOn sleep 0.5 ledOff sleep 0.5 done } # Switch # GPIO als Eingang deklarieren und Hilfsfunktionen fuer Steuerung definieren # Switch north gpio export 4 in switchNorth () { echo ` gpio -g read 4 ` } # Switch east gpio export 17 in switchEast () { echo ` gpio -g read 17 ` } # Switch west gpio export 22 in switchWest () { echo ` gpio -g read 22 ` } # Switch south gpio export 27 in switchSouth () { echo ` gpio -g read 27 ` } D.3 demoLed.sh # !/ bin / bash source gpio . sh # GPIO Hilfsdatei einfuegen echo ' 97 D Code Listings Raspberry Pi Shield Demo Alle LEDs werden auf dem Shield aktiviert und anschliessend deaktiviert . Das Programm beendet sich automatisch . '; ledNorthOn sleep 0.25 ledEastOn sleep 0.25 ledWestOn sleep 0.25 ledSouthOn # LEDs anschalten sleep 2 # 2 Sekunden warten ledNorthOff ledEastOff ledWestOff ledSouthOff # LEDs ausschalten D.4 demoSwitch.sh # !/ bin / bash source gpio . sh # GPIO Hilfsdatei einfuegen echo ' Raspberry Pi Shield Demo Druecke einen Schalter auf dem Shield um die entsprechende LED zu aktivieren . STRG + C um das Programm zu beenden . '; while : do if [ $ ( switchNorth ) = 1 ] # falls Schalter North gedrueckt ist then echo " North gedrueckt " ledNorthOn # North gedrueckt ausgeben und die entsprechende LED anschalten else ledNorthOff # sonst die LED ausschalten fi if 98 [ $ ( switchEast ) = 1 ] D.5 simon.sh then else fi echo " East gedrueckt " ledEastOn ledEastOff if [ $ ( switchWest ) = 1 ] then echo " West gedrueckt " ledWestOn else ledWestOff fi if [ $ ( switchSouth ) = 1 ] then echo " South gedrueckt " ledSouthOn else ledSouthOff fi done D.5 simon.sh # !/ bin / bash source gpio . sh # GPIO Hilfsdatei einfuegen # Konstanten # Verzoegerung zwischen LED leuchten DELAY_TIME_LED =0.25 # Verzoegerung bei Switch Eingabe DELAY_TIME_SWITCH =0.2 # Variablen # correct =0 Eingaben in Ordnung , Spiel geht weiter # correct = -1 Eingabe falsch , Abbruch correct =0 MakeRandom () { # Zufallszahl zwischen 0 und 3 echo $ (( RANDOM %4) ) } LightLed () { # gibt alle Werte aus dem Array wieder , zeigt # also an welche Werte eingegeben werden # muessen um die Runde zu schaffen . # Alle Werte im Array abrufen 99 D Code Listings } for value in " $ { simonArray [ @ ]} " do # gemaess dem Array Wert die pasende LED # an - und ausschalten case " $value " in 0) ledNorthOn sleep $ { DELAY_TIME_LED } ledNorthOff sleep $ { DELAY_TIME_LED } ;; 1) ledEastOn sleep $ { DELAY_TIME_LED } ledEastOff sleep $ { DELAY_TIME_LED } ;; 2) ledWestOn sleep $ { DELAY_TIME_LED } ledWestOff sleep $ { DELAY_TIME_LED } ;; 3) ledSouthOn sleep $ { DELAY_TIME_LED } ledSouthOff sleep $ { DELAY_TIME_LED } ;; esac done ReadButton () { # Liest den Zustand der 4 Schalter ein # sollte einer gedrueckt sein wird die # Abfrage abgebrochen und der Wert # zurueck gegeben . Ist keiner gedrueckt , # wird -1 zurueck gegeben . if [ $ ( switchNorth ) = 1 ] then echo 0 elif [ $ ( switchEast ) = 1 ] then echo 1 elif [ $ ( switchWest ) = 1 ] then echo 2 elif [ $ ( switchSouth ) = 1 ] then echo 3 else echo -1 100 D.5 simon.sh } fi CheckButton () { # Ueberprueft ob die eingegebene # Kombination der physikalischen # Schalter der vorgegebenen # entspricht . Falls ja , geht # das Spiel weiter , wenn nicht , # wird correct = -1 gesetzt . # Alle Werte im Array abrufen for value in " $ { simonArray [ @ ]} " do # Wert der Schalter auslesen btn = $ ( ReadButton ) # Solange kein Schalter gedrueckt # ist , weiter auslesen while [ $btn == -1 ] do btn = $ ( ReadButton ) done # Falls ein Schalter gedrueckt wurde , # und der Wert der Stelle im Array # entspricht , weiter machen if [ $btn == $value ] then echo " Ok ! " # sleep hilft an dieser Stelle einem # zu lange gedrueckten Schalter vorzubeugen . # Alternativ koennte man in ReadButton # einen Flankenwechsel als Schalterdruck # identifizieren sleep $ { DELAY_TIME_SWITCH } # Sonst : correct = -1 setzen und # aus der Schleife ausbrechen else echo " Falsch ! " correct = -1 break fi done } # 2 x schnelles blinken aller LEDs # als " Willkommen " ledBlinkFast sleep 0.5 # Solange die eingegebenen Kombinationen richtig waren , # geht das Spiel immer weiter . while [ $correct == 0 ] do # An der Stelle " groesse des Arrays " einen neuen Zufallswert 101 D Code Listings # zwischen 0 und 3 in das Array einfuegen . Damit sparen # wir uns die Zahlvariable / Iterationsvariable simonArray [ ${ # simonArray [ @ ]}]= $ ( MakeRandom ) # Alle Zufallswerte des Arrays auf den LEDs abspielen LightLed # Die Eingabe der Zufallswerte ueber die Schalter # erwarten und auf Fehler auswerten . Bei Fehler # wird correct = -1 gesetzt und das Spiel endet . # Sonst geht es endlos weiter . CheckButton done # 2 x langsames blinken aller LEDs # bei Fehler / Ende des Spiels sleep 0.5 ledBlink echo $ { # simonArray [@ ]} echo $ { simonArray [ @ ]} # Neustart des Spiels bei Fehler ./ simon . sh D.6 uebungAusgabe.py # !/ usr / bin / python import wiringpi2 as wpi from time import sleep wpi . wiringPiSetupGpio () LEDs =[18 ,23 ,24 ,25] # LED Pins als Array fuer # gruen , rot , blau , gelb led_mode =1 # Variable welche den Wert # haelt ob die LED ein oder # ausgeschaltet werden soll for led_pin in LEDs : wpi . pinMode ( led_pin ,1) wpi . digitalWrite ( led_pin ,0) # Setup : Alle Pins mit LEDs # als Ausgabe setzen und # abschalten while True : for led_pin in LEDs : wpi . digitalWrite ( led_pin , led_mode ) sleep (0.25) led_mode = not ( led_mode ) # Loop : Jeweils pro Durchlauf 102 D.7 uebungEingabe.py # alle LEDs in den jeweils gueltigen # Mode setzen und danach den Mode # negieren ( An / Aus ) D.7 uebungEingabe.py # !/ usr / bin / python import wiringpi2 as wpi from time import sleep wpi . wiringPiSetupGpio () LEDs =[24 ,25 ,18 ,23] # LED Pins als Array fuer # blau , gelb , gruen , rot for led_pin in LEDs : wpi . pinMode ( led_pin ,1) wpi . digitalWrite ( led_pin ,0) # Setup : Alle Pins mit LEDs # als Ausgabe setzen und ausschalten wpi . pinMode (27 ,0) # Setup : Schalter South # als Eingabe setzen def blinkLED ( ledPin , wieoftBlinken , verzoegerung ) : for i in range (1 ,(( wieoftBlinken *2) +1) ) : wpi . digitalWrite ( LEDs [ ledPin ] ,( i %2) ) sleep ( verzoegerung ) # Modul blinkLED nimmt die aktuelle LED entgegen # und laesst diese mit gegebener Verzoegerung # eine gewisse Anzahl blinken aktuelleLED =0 # Gibt aktuelle LED as Position im Array an aktuelleVerzoegerung =0.50 # Gibt die aktuelle Verzoegerung zwischen # den LED wechseln an aktuelleRunde =1 # Gibt die aktuelle Runde an while True : if ( wpi . digitalRead (27) ) : # falls der Schalter gedrueckt wurde blinkLED ( aktuelleLED , 2 , 0.5) # lass die mit dem Schalter gewaehelte # LED zwei mal blinken if ( aktuelleLED ==2) : if ( aktuelleVerzoegerung > 0.05) : aktuelleVerzoegerung = aktuelleVerzoegerung -0.05 # reduziere die Verzoegerung fuer die # nacheste Runde , falls moeglich aktuelleLED =0 103 D Code Listings # setze LED wieder auf Anfang vom Array zurueck print ( " Runde % d bestanden " % aktuelleRunde ) # Erfolg aktuelleRunde = aktuelleRunde +1 # naechste Runde else : print ( " Leider verloren in Runde % d ! " % aktuelleRunde ) # Niederlage , weil falsch / zu spaet gedrueckt break # Verlasse Schleife und beende Programm blinkLED ( aktuelleLED , 1 , aktuelleVerzoegerung ) # die jeweils aktuelle LED einmal blinken lassen aktuelleLED = aktuelleLED +1 # und zur naechsten iterieren if ( aktuelleLED > 3) : print ( " Leider verloren in Runde % d ! " % aktuelleRunde ) # Niederlage , weil gar nicht gedrueckt break # Verlasse Schleife und beende Programm D.8 binaryCounter.py # !/ usr / bin / python import wiringpi2 as wpi wpi . wiringPiSetupGpio () LEDs =[18 ,23 ,24 ,25] # LED Pins als Array fuer # gruen , rot , blau , gelb for led_pin in LEDs : wpi . pinMode ( led_pin ,1) wpi . digitalWrite ( led_pin ,0) # Setup : Alle Pins mit LEDs # als Ausgabe setzen und ausschalten wpi . pinMode (27 ,0) wpi . pinMode (22 ,0) # Setup : Schalter South , # Schalter West als Eingabe setzen southState = wpi . digitalRead (27) westState = wpi . digitalRead (22) # Setup : Initialer Status # von South und West einlesen zahl =0 # Zaehlvariable ledMode =[0 ,0 ,0 ,0] # Zwischenspeicher fuer die # Ergebnisse der Umrechnung def showLED () : ledMode [0] = zahl & 0 b0001 104 D.9 lm75b.py ledMode [1] = zahl & 0 b0010 ledMode [2] = zahl & 0 b0100 ledMode [3] = zahl & 0 b1000 # jeweils aus der binaeren Verundung der # Zahl und der Wertigkeit der LED # den Status fuer die LED errechnen # und speichern for i in range (0 ,4) : wpi . digitalWrite ( LEDs [ i ] , ledMode [ i ]) # alle LEDs auf den aktuellen Status setzen print ( " Dezimal %d , Binaer %s , Hexadezimal % s " % ( zahl , bin ( zahl ) , hex ( zahl ) ) ) # die aktuelle Zahl als Dezimal , # Binaer und Hexadezminal Notation # ausgeben showLED () while True : southValue = wpi . digitalRead (27) # aktueller Status des # Schalters einlesen if ( southValue != southState ) : # besteht ein Unterschied # zum gespeicherten Status if ( southValue ) : # Ist der +1 Schalter gedrueckt ? zahl = zahl +1 # Zahl erhoehen if zahl >15: zahl =0 # Zahl ruecksetzen falls zu hoch showLED () # Anzeigen southState = southValue # neuen Wert des Schalters speichern westValue = wpi . digitalRead (22) if ( westValue != westState ) : if ( westValue ) : # Ist der Reset Schalter gedrueckt ? zahl =0 # Zahl ruecksetzen showLED () # Anzeigen westState = westValue D.9 lm75b.py # !/ usr / bin / python import wiringpi2 as wpi lm75b_addr =0 x48 105 D Code Listings lm75b_file = wpi . wiringPiI2CSetup ( lm75b_addr ) # Verbindung zu LM75B oeffnen if lm75b_file < 0: print ( " Kann den I2C Bus nicht oeffnen ! " ) else : lm75_temp = wpi . wiringPiI2CReadReg16 ( lm75b_file , 0) # Register 0 von LM75B in 16 Bit Tiefe auslesen lm75b_hi = ( lm75_temp & 0 xFF ) lm75b_lo = ( lm75_temp >> 8) # In 2x 8 Bit Werte ( High und Low Bit ) umwandeln n = lm75b_hi << 3 | (( lm75b_lo >> 5) & 0 x07 ) # gemaess Datasheet des Sensors aus den ausgelesenen # 2 Bytes die korreten 11 Bits fuer den Temperaturwert # extrahieren und shiften lm75b_temp = n / 8.0 # 11 Bit Wert in Temperatur umwandeln print ( " LM75B : %4.2 f Grad Celsius " % ( lm75b_temp ) ) # Temperatur mit 2 Nachkommastellen ausgeben D.10 uebungI2C.py # !/ usr / bin / python import wiringpi2 as wpi from time import sleep lm75b_addr =0 x48 # I2C Adresse des LM75B LEDs =[24 ,18 ,23] # LED Pins als Array fuer # blau , gruen , rot modifierState =[ -1 ,0 ,+1] # Temperatur Unterschiede fuer Ubergang nameState =[ " Kalt " ," Normal " ," Warm " ] # Namen der States currentState =0 # State der Pseudo State Machine maxStates =3 # Anzahl der States def readTemp () : lm75_temp = wpi . wiringPiI2CReadReg16 ( lm75b_file , 0) # Register 0 von LM75B in 16 Bit Tiefe auslesen lm75b_hi = ( lm75_temp & 0 xFF ) lm75b_lo = ( lm75_temp >> 8) # In 2x 8 Bit Werte ( High und Low Bit ) umwandeln n = lm75b_hi << 3 | (( lm75b_lo >> 5) & 0 x07 ) # gemaess Datasheet des Sensors aus den ausgelesenen # 2 Bytes die korreten 11 Bits fuer den Temperaturwert # extrahieren und shiften lm75b_temp = n / 8.0 106 D.10 uebungI2C.py # 11 Bit Wert in Temperatur umwandeln return lm75b_temp def transition ( up ) : global currentState , maxMod , minMod # globale Variablen in Funktion laden wpi . digitalWrite ( LEDs [ currentState ] ,0) # Led des jetzigen State abschalten if ( up ==1) : # Falls State erhoeht wird currentState = currentState +1 # State erhoehen print ( " Transition von % s -> % s " % ( nameState [ currentState -1] , nameState [ currentState ]) ) # Ausgabe vorheriger State nach jetziger State else : currentState = currentState -1 # State verringern print ( " Transition von % s -> % s " % ( nameState [ currentState +1] , nameState [ currentState ]) ) # Ausgabe vorheriger State nach jetziger State wpi . digitalWrite ( LEDs [ currentState ] ,1) # Led des nun aktuellen State einschalten if ( modifierState [ currentState ]==0) : # Falls State 1 / Normal aktiv maxMod =1 # setze maximalen Wert auf +1 minMod = -1 # setze minimalen Wert auf -1 else : # sonst setze Max / Min gemaess Array maxMod = modifierState [ currentState ] minMod = modifierState [ currentState ] lm75b_file = wpi . wiringPiI2CSetup ( lm75b_addr ) # Verbindung zu LM75B oeffnen if lm75b_file < 0: print ( " Kann den I2C Bus nicht oeffnen ! " ) else : # Setup wpi . wiringPiSetupGpio () # Initialisiert die Bibliothek unter Nutzung des # BCM GPIO Namenschema for led_pin in LEDs : wpi . pinMode ( led_pin ,1) wpi . digitalWrite ( led_pin ,0) # Alle Pins mit LEDs als Ausgabe setzen und abschalten idealTemp = readTemp () # Ideal Temperatur messen transition (1) # Initalisieren auf Normal Modus while True : 107 D Code Listings if (( readTemp () > ( idealTemp + maxMod ) ) and ( currentState < ( maxStates -1) ) ) : # falls aktuelle Temperatur groesser als Ideal Temperatur + Modifier # und aktueller State kleiner als die maximale Anzahl an States transition (1) # State erhoehen elif (( readTemp () < ( idealTemp + minMod )) and ( currentState > 0) ) : # falls aktuelle Temperatur kleiner als Ideal Temperatur + Modifier # und aktueller State groesser als 0 transition (0) # State verringern else : # falls innerhalb der Temperatur des States print ( " % s : %4.2 f " % ( nameState [ currentState ] , readTemp () ) ) # aktueller State und aktuelle Temperaturmessung ausgeben sleep (0.25) D.11 mcp3002.py # !/ usr / bin / python import wiringpi2 as wpi from binascii import hexlify from binascii import unhexlify mcp3002_channel =0 if wpi . wiringPiSPISetup (0 ,1000000) < 0: print ( " Kann den SPI Bus nicht oeffnen ! " ) else : buffer =((6+ mcp3002_channel ) < <12) buffer = ' {0: x } '. format ( int ( buffer ) ) # Wandle den dezimalen Integer in einen # hexadezimalen String um , ohne das Praefix # 0 x davorzustellen buffer = unhexlify ( buffer ) # Wandle den Hex String in einen Byte String um if ( wpi . wiringPiSPIDataRW (0 , buffer ) == -1) : # Anforderung auf den SPI Bus auf Slave # Select 0 schreiben und # gleichzeitig ( bi - direktional ) mit der # Antwort den Buffer ueberschreiben print ( " Schreibfehler auf SPI Bus !\ n " ) else : buffer = hexlify ( buffer ) # Wandle den Byte String nach Hex um buffer = int ( buffer , 16) # Wandle den Hex String in einen # dezimalen Integer Wert um prozent = ( buffer /1024.0) *100 108 D.12 mcp3002lib.py # Wandle dezimalen Integer in Prozentwert # der eingegangen Beleuchtungsstaerke um print ( " MCP3002 - Kanal % d : %4.2 f Prozent " % ( mcp3002_channel , prozent ) ) D.12 mcp3002lib.py # !/ usr / bin / python import wiringpi2 as wpi mcp3002_channel =0 if ( wpi . wiringPiSPISetup (0 , 1000000) < 0) : # Verbindung zu MCP3002 oeffnen print ( " Kann den SPI Bus nicht oeffnen ! " ) else : wpi . mcp3002Setup (64 , mcp3002_channel ) # MCP3002 Template laden , Kanal 0 auf virtuellen Port 64 legen buffer = wpi . analogRead (64) # Virtuellen Port 64 auslesen prozent = ( buffer /1024.0) *100 # Wandle dezimalen Integer in Prozentwert # der eingegangen Beleuchtungsstaerke um print ( " MCP3002 - Kanal % d : %4.2 f Prozent " % ( mcp3002_channel , prozent )) D.13 uebungSPI.py # !/ usr / bin / python import curses from time import sleep import wiringpi2 as wpi mcp3002_channel =0 if ( wpi . wiringPiSPISetup (0 , 1000000) < 0) : # Verbindung zu MCP3002 oeffnen print ( " Kann den SPI Bus nicht oeffnen ! " ) else : wpi . mcp3002Setup (64 , mcp3002_channel ) # MCP3002 Template laden , Kanal 0 auf virtuellen Port 64 legen ldr_max = float ( wpi . analogRead (64) ) # Virtuellen Port 64 auslesen , als maximal Wert screen = curses . initscr () # curses in der Konsole initialisieren dims = screen . getmaxyx () # y , x Groesse des Bildschirms in Array ablegen # dims [0] entspricht y Wert 109 D Code Listings # dims [1] entspricht x Wert screen . nodelay (1) # nodelay Modus aktivieren um screen . getch () # im non - Blocking Modus zu betreiben while ( screen . getch () == -1) : # fuehre die Schleife aus solange keine # Taste gedrueckt wurde ldr = wpi . analogRead (64) # aktuellen Wert einlesen wert = int (( ldr / ldr_max ) * dims [0]) # LDR Wert auf Dimensionen des Bildschirms skalieren if wert >= dims [0]: # Sollte der Wert die y Dimension ueberschreiten wert = ( dims [0] -1) # dann einfach fuer diese Messung # y - Dimension - 1 als Wert nehmen wert = dims [0] - wert # Gegenwert berechnen , da bei curses die linke , obere # Bildschirm Ecke die x , y Koordinaten 0 ,0 hat screen . erase () # Bildschirm loeschen screen . hline ( wert , 0, ' - ' , dims [1]) # horinzontale Linie aus - Zeichen malen , # welche so breit wie die maximale x Dimension ( dims [1]) # ist und beim x Wert 0 beginnt # hline (y Koordinate , x Beginn , ch Zeichen , n Laenge ) screen . refresh () # Bildschirm neu laden sleep (0.1) curses . endwin () # Beenden D.14 wpi.c // wiringPi 2 MathLink # include " mathlink . h " # include < stdio .h > # include < wiringPi .h > // Include and Define I2C # include < wiringPiI2C .h > # include < stdlib .h > # define lm75b_addr 0 x48 int lm75b_file ; int n ; int lm75_temp ; signed char lm75b_hi ; signed char lm75b_lo ; float lm75b_temp ; // Include and Define SPI 110 D.14 wpi.c # include < stdint .h > # include < wiringPiSPI .h > extern extern extern extern extern extern void setPinMode ( int pin , int mode ) ; void setDigitalWrite ( int pin , int value ) ; void setPwmWrite ( int pin , int value ) ; int getDigitalRead ( int pin ) ; float getLM75B () ; int getMCP3002 ( int channel ); void setPinMode ( int pin , int mode ) { pinMode ( pin , mode ) ; MLPutSymbol ( stdlink , " Null " ) ; } void setDigitalWrite ( int pin , int value ) { digitalWrite ( pin , value ) ; MLPutSymbol ( stdlink , " Null " ) ; } void setPwmWrite ( int pin , int value ) { pwmWrite ( pin , value ) ; MLPutSymbol ( stdlink , " Null " ) ; } int getDigitalRead ( int pin ) { return digitalRead ( pin ) ; } float getLM75B () { if (( lm75b_file = wiringPiI2CSetup ( lm75b_addr ) ) == -1) { printf ( " Kann den I2C Bus nicht oeffnen !\ n " ) ; return -1; } // Verbindung zu LM75B oeffnen lm75_temp = wiringPiI2CReadReg16 ( lm75b_file , 0) ; // Register 0 von LM75B in 16 Bit Tiefe auslesen lm75b_hi = ( lm75_temp & 0 xFF ) ; lm75b_lo = ( lm75_temp >> 8) ; // In 2 x 8 Bit Werte ( High und Low Bit ) umwandeln n = lm75b_hi << 3 | (( lm75b_lo >> 5) & 0 x07 ) ; /* gemaess Datasheet des Sensors aus den ausgelesenen 2 Bytes die korreten 11 Bits fÃ×r den Temperaturwert extrahieren und shiften */ lm75b_temp = ( float ) n / 8; // 11 Bit Wert in Temperatur umwandeln return lm75b_temp ; 111 D Code Listings } int getMCP3002 ( int channel ) { uint8_t buff [2]; if (( channel > 1) || ( channel < 0) ) { // Nur MCP Kanal 0 und 1 zulassen return -1; } } if ( wiringPiSPISetup (0 , 1000000) < 0) { return -1 ; } /* WiringPi SPI API initalisieren auf Slave Select / SPI Kanal 0 mit Geschwindigkeit 1 MHz */ buff [0] = (6+ channel ) < <4; buff [1] = 0; // korrekte Anfrage fuer MCP3002 gemaess Datenblatt erzeugen wiringPiSPIDataRW (0 , buff , 2) ; // Anfrage absenden und Antwort in den Puffer schreiben return (( buff [0]&3) << 8) + buff [1]; // Wert aus Puffer shiften int main ( int argc , char * argv []) { wiringPiSetupGpio () ; return MLMain ( argc , argv ) ; } D.15 wpi.tm float getLM75B () ; : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : getLM75B getLM75B [] { } { } Float : Evaluate : getLM75B :: usage = " getLM75B [] gives the Temperature in degree Celsius . " int getMCP3002 P (( int ) ) ; 112 D.15 wpi.tm : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : getMCP3002 getMCP3002 [ channel_Integer ] { channel } { Integer } Integer : Evaluate : getMCP3002 :: usage = " getMCP3002 [ channel ] gives 10 bit reading (0 -1023) of the choosen ADC channel 0 -1. " void setPinMode P (( int , int ) ) ; : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : setPinMode setPinMode [ pin_Integer , mode_Integer ] { pin , mode } { Integer , Integer } Manual : Evaluate : setPinMode :: usage = " setPinMode [ pin , mode ] set the given pin to 0 ( Input ) , 1 ( Output ) or 2 ( PWM Output ) . " void setDigitalWrite P (( int , int ) ) ; : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : setDigitalWrite setDigitalWrite [ pin_Integer , value_Integer ] { pin , value } { Integer , Integer } Manual : Evaluate : setDigitalWrite :: usage = " setDigitalWrite [ pin , value ] writes a digital value (0 -1) to the pin . " void setPwmWrite P (( int , int ) ) ; : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : setPwmWrite setPwmWrite [ pin_Integer , value_Integer ] { pin , value } { Integer , Integer } Manual 113 D Code Listings : Evaluate : setPwmWrite :: usage = " setPwmWrite [ pin , value ] writes a pwm value (0 -1023) to the pin . " int getDigitalRead P (( int ) ) ; : Begin : : Function : : Pattern : : Arguments : : ArgumentTypes : : ReturnType : : End : getDigitalRead getDigitalRead [ pin_Integer ] { pin } { Integer } Integer : Evaluate : getDigitalRead :: usage = " getDigitalRead [ pin ] gives the digital reading (0 or 1) of the pin . " 114 Kolophon Dieses Dokument wurde mit der LATEX-Vorlage für Abschlussarbeiten an der htw saar im Bereich Informatik/Mechatronik-Sensortechnik erstellt (Version 1.0). Die Vorlage wurde von Yves Hary und André Miede entwickelt (mit freundlicher Unterstützung von Thomas Kretschmer und Helmut G. Folz).