Tipp

Ein-/Ausschalter für Raspberry Pi selber bauen

Gesucht war ein Add-on für den Raspi, mit dem man den kleinen Rechner auf nur einer Taste ein- und ausschalten und noch ein paar andere Funktionen nutzen kann. Kommerzielle Angebote erfüllten nicht alle Anforderungen, lieferten aber die Idee zum Selbstbau.

Eigentlich ist Peter K. Boxler Mac-Nutzer, Elektro-Ingenieur und Software-Engineer in Rente – und er ist auch Raspberry-Projektentwickler. Als solcher hat er einige Projekte erfolgreich auf die Beine gestellt. Einige davon finden Sie auch bereits auf unserer Schwesterpublikation pcwelt.de, die Links dazu stehen am Ende des Beitrags.

Seine neueste Entwicklung ist der Intelligente Power Switch für den Raspberry Pi.

Während der Entwicklung verschiedener Gadgets mit dem Raspberry Pi tauchten immer wieder Themen und Problemstellungen auf, für die ich gern eine elegante Lösung gehabt hätte. So entstand der Plan, ein Add-on zu entwickeln, das folgendes leisten sollte:

Wichtigste Anforderung: Der Raspberry Pi (Power Off) wird - wie jeder andere Computer - in zwei Stufen ausgeschaltet:

Das Einschalten ist dagegen simpel: Stromzufuhr einschalten, der Pi bootet und beginnt mit der Arbeit.

Überlegungen im Vorfeld

Im Handel werden verschiedene Add-ons angeboten, die das Ein-Ausschalt-Problem lösen. Sie bestehen meist aus einer kleinen gedruckten Schaltung mit Anschlüssen für Drucktasten, 5 V und anderen nötigen Verbindungen. Ich habe mir einige dieser Add-ons angeschaut:

Ich habe bereits Kenntnisse in der Programmierung vom Atmel Mikrocontrollern und will einen ATtiny44 Mikrocontroller verwenden. Einzelheiten dazu liefert das Datenblatt zum Mikrocontroller.

Alle oben beschriebenen Add-ons bestehen aus zwei Komponenten, die in bestimmter Weise zusammenarbeiten:

Meine eigene Lösung wird derselben Idee folgen - der Intelligente Power Switch wird also ebenfalls aus einer externen Elektronik-Komponente sowie einem Python-Script bestehen.

Die angedachte Lösung

Mein Add-on werde ich mit einer gedruckten Schaltung in der Größe 38 x 47 mm realisieren. Herz der Schaltung ist ein Mikrocontroller ATtiny44, für den ein C-Programm entwickelt wurde, das die gewünschten Funktionen implementiert (Firmware). Die kleine Platine kann in ein Breadboard gesteckt werden. Diese Platine wird iSwitchPi genannt. Die Lösung sieht so aus:

Übersicht der Lösung
Übersicht der Lösung
Foto:

Das Elektronik-Board (iSwitchPi) sorgt für das Timing des Ein-/Ausschaltens des Pi. Im Pi läuft ein Shutdown-Script, das via GPIO- Pin mit dem iSwitchPi kommuniziert. Der iSwitchPi liefert zudem das Rechteck-Signal an den Pi.

Ich prüfe noch einmal meine Anforderungen. Das zu entwickelnde Bauteil soll neben der Ein-Ausschaltfunktion noch andere Funktionen haben.

Es soll nur eine Drucktaste für Ein-/Ausschalten/Reboot des Pi geben. Ist der Pi ausgeschaltet, genügt ein kurzer Druck auf die Taste, um den Pi mit Strom zu versorgen. Läuft der Pi, kann ich mit einem kurzen Druck auf dieselbe Taste den Shutdown des Pi einleiten, und nach einer definierten Verzögerungszeit wird auch die Stromzuführung zum Pi unterbrochen.

Läuft der Pi, so kann mit einem langen Tastendruck ein Reboot des Pi ausgelöst werden - die Stromzufuhr bleibt in diesem Fall erhalten.

Läuft der Pi, und es wird ein Shutdown via Terminal-Fenster ausgelöst (oder es erfolgt ein programmgesteuerter Shutdown des Pi), so soll dies die Schaltung feststellen und die Stromzufuhr nach der definierten Verzögerungszeit unterbrechen.

Die Stromversorgung des Pi soll aber auch ohne Rückmeldung des Pi weiterlaufen - beispielsweise dann, wenn das Python-Shutdown-Script noch nicht aktiviert oder wenn es fehlerhaft ist.

Eine Beschreibung ist nicht immer ganz einfach, ich versuche es, anhand eines sogenannten Endlichen Automaten (Finite State Machine) zu verdeutlichen.

Ein solcher Automat hat definierte Eingänge, Zustände, Übergänge zwischen Zuständen und ebenfalls definierte Ausgänge. Übergänge zwischen Zuständen werden durch Änderungen in den Input-Signalen verursacht. Dies wiederum hat Änderungen in den Output-Signalen zur Folge.

Input- und Output-Signale
Input- und Output-Signale
Foto:

Jetzt aber erst mal zur Elektronik-Komponente, danach geht es dann mit dem Python-Shutdown-Script weiter.

Komponente A - die Elektronik

Zustands-Diagramm: Der iSwitchPi implementiert in Software und Hardware die Ein-/Ausschaltfunktion der Pi-Stromversorgung. Nach ein paar Versuchs-Skizzen wurde folgendes Zustands-Diagramm (State Diagram) für die Endliche Maschine gefunden. Das Zustands-Diagramm und die Zustands-Tabellen definieren das zu erstellende C-Programm für den ATtiny44.

Der Pi wird mittels eines Scripts (siehe weiter unten) regelmäßig Pulse senden, die signalisieren: Ich bin noch am Leben, stell mir bitte nicht den Strom ab.

Zustands-Diagramm
Zustands-Diagramm
Foto:

Input und Output: Dies sind alle Eingangssignale des Automaten (each input can be one or zero).

Eingangssignale
Eingangssignale
Foto:

Ausgänge des Automaten

Ausgangssignale
Ausgangssignale
Foto:

Zustands-Tabelle: Sie beschreibt die Funktion des Endlichen Automaten komplett. Diese Funktion wird durch das C-Programm implementiert. Ein bestimmter Zustand plus Kombination von Eingangssignalen führt zu einem neuen Zustand. Implizit: Ohne Änderung der Eingangssignale bleibt der Automat im aktuellen Zustand.

Zustands-Tabelle
Zustands-Tabelle
Foto:

Eingangs-Aktivitäten der Zustände: Jeder Zustand des Automaten hat im allgemeinen sogenannte entry actions, also Aktivitäten, die beim Eintritt in den Zustand genau einmal ausgeführt werden. Dies sind meist Änderungen in den Output-Signalen.

Eingangs-Aktivitäten der Zustände
Eingangs-Aktivitäten der Zustände
Foto:

Elektrisches Schema: Das elektrische Schema des iSwitchPi sieht so aus: Die Eingangsspannung von 5 Volt wird für den Mikrocontroller im Baustein NCP702 auf 3,3 Volt reduziert. Damit ist auch die Kommunikationsleitung für den Pi mit diesem Pegel angesprochen (GPIO-Pins für den Pi dürfen maximal diese Spannung haben).

Der Mikrocontroller schaltet den High-Side Switch MCP2505 ein und aus - dieser Switch kann maximal 2 Ampere schalten - dies ist die 5-Volt-Spannnungsversorgung für den Pi.

Im Pi läuft ein Python-Script (iswitchpi.py), das am gewählten GPIO-Pin durch regelmäßige Pulse meldet ‚ok ich laufe‘. Das Script kann jedoch auch Pulse vom iSwitchPi empfangen (Interrupt-Handler), und die Anzahl der eintreffenden Pulse bestimmen die Art des Commands, der ans OS abgesetzt wird: shutdown halt oder reboot

Das Herz des iSwitchPi ist ein ATtiny44 Mikrocontroller. Allein für die Steuerung des Pulsgenerators und dessen Output werden fünf Pins benötigt - deshalb genügt ein ATtiny85 mit seinen insgesamt fünf Pins nicht.

Die Schaltung wurde im Programm Eagle PCB gezeichnet - das Programm erstellt ebenfalls das Layout der gedruckten Schaltung (mit einiger Handarbeit). Es ergab sich ein Board von 38 x 47 mm.

Elektrisches Schema iSwitch Pi
Elektrisches Schema iSwitch Pi
Foto:

Pulsgenerator: Er erzeugt kurze Rechteck-Pulse (Duty Cycle ca. 10 Prozent) mit verschiedenen Frequenzen. Durch einen DIP-Schalter kann die produzierte Frequenz eingestellt werden:

Die Frequenz kann mit den drei rechten Schaltern des DIP-Schalters gewählt werden. Mit drei Schaltern sind acht Positionen wählbar; alle drei Schalter off bedeutet: Frequenz mittels Trimm-Potentiometer einstellbar.

Kommunikation zwischen Pi und iSwitchPi:Das im Folgenden beschriebene Python-Script im Pi sendet prinzipiell jede Sekunde einen Puls auf der Kommunikationsleitung auf dem definierten GPIO-Pin. Diese Pulse signalisieren: Ich lebe noch.

Das Programm im ATtiny44 ist prinzipiell immer auf Empfang, um diese Pulse zu bekommen. Kommen keine Pulse mehr, wird angenommen, dass der Pi nicht mehr läuft oder sich in einem Reboot-Prozess befindet. Die Power-Off-Sequenz wird dann eingeleitet.

Wird die Drucktaste kurz oder lang gedrückt (Shutdown oder Reboot), wird dies dem Script im Pi mitgeteilt durch Senden von Pulsen: ein Puls bedeutet Shutdown, zwei Pulse bedeuten Reboot. Diese Pulse werden jedoch erst gesendet, nachdem ein Puls vom Pi eingetroffen ist - nur dann ist sicher, dass der Pi wieder auf Empfang ist.

Folgendes Schema soll dies verdeutlichen.

Schema der Kommunikation
Schema der Kommunikation
Foto:

Programm im ATtiny44: Das Programm für den Mikrocontroller wird aus zwei C-Programmen kompiliert:

Die Verwendung der I/O-Pins des ATtiny ist im Sourcecode dokumentiert. Das C-Programm implementiert die Endliche Maschine mit sechs Zuständen gemäss der Zustands-Tabelle. Die Drucktaste für die Auslösung der verschiedenen Funktionen ist entprellt (debounce) mit C-Code von Peter Dannegger. Der Code ist auf Mikrocontroller.net publiziert und diskutiert. Er funktioniert prima, ist aber nicht ganz einfach zu durchschauen. Ich habe zusätzlich eine Funktion key_clear() eingefügt. Damit können die Tastendrücke besser mit den Zuständen synchronisiert werden.

Zur Programmierung von AVR Mikrocontrollern gibt es ebenfalls in Mikrocontroller.net gute Tutorials.

Hier ist der Sourcecode iSwitchPi inkl. Eagle-Dateien verfügbar.

Gedruckte Schaltung: Für den Mikrocontroller ATtiny44 ist ein 14-poliger IC-Sockel vorgesehen. Für dessen Neuprogrammierung ist deshalb auf dem Board keine ICSP-Schnittstelle vorhanden: Der Chip wird abgezogen und in den Zero-Force-Sockel des Programmers gesteckt. Die Platine wird teilweise mit SMD-Komponenten der Größe 1206 bestückt - das erfordert einige Erfahrung für das Löten.

Gedruckte Schaltung iSwitchPi (Version 2)
Gedruckte Schaltung iSwitchPi (Version 2)
Foto: Peter Boxler

Prototyp iSwitchPi, bereit zum Testen, leeres Board
Prototyp iSwitchPi, bereit zum Testen, leeres Board
Foto: Peter Boxler

Komponente B - das Python-Shutdown-Script

Wie bereits erwähnt, arbeitet die Elektronik-Komponente mit einem Python-Script iswitchpi.py zusammen, das nach dem Boot im Pi gestartet wird (Eintrag in /etc/rc.local). Die externe Komponente und das Script kommunizieren mittels Signalen auf einem einzigen GPIO-Pin.

Das Script besteht im wesentlichen aus einem einfachen Loop, in dem jede Sekunde ein 50-ms-Puls am definierten GPIO-Pin ausgegeben wird.

Nach dem Start wird dieser Pin jedoch auf Input gesetzt, und es wird ein Interrupt-Handler auf rising abgesetzt. Vor dem Senden des Pulses wird dieser Interrupt-Handler entfernt und der Pin auf Output gesetzt. Nach dem Senden des Pulses wird der Pin wieder auf Input gesetzt und der Interrupt-Handler erneut aufgesetzt.

Der Interrupt-Handler zählt die Anzahl der Interrupts (Pulse), die seit dem letzten Senden eingetroffen sind. Ein einzelner Interrupt führt zu Shutdown Halt, zwei Interrupts führen zu Reboot des Pi (siehe Kommunikations-Diagramm weiter oben).

Das Script wird durch folgenden Eintrag in der Datei /etc/rc.local gestartet (Ersetzen des Directories myservices durch eigenes Directory):

Der Commandline Parameter -d spezifiziert Debug Output:

Verwendete GPIO-Pins:Nicht alle GPIO-Pins des Pi sind identisch. In Internetforen findet man viele Diskussionen zur Frage des Initialzustands (High/Low und Impedanz) der GPIO-Pins nach dem Power-On des Pi. Für sehr viele (aber nicht alle) Anwendungen ist es wichtig, genau darüber Bescheid zu wissen, damit verbundene Komponenten nicht im falschen Moment schalten/aktiviert werden.

Die Raspberry Foundation bietet seit 2014 eine Lösung für das Problem. Mehr Informationen dazu liefern auch dieser Blog oder die Google-Suche mit ‚raspberry gpio initial state‘.

Fazit ist, dass man für Pins, die als Input-Pins verwendet werden, in jedem Fall einen Widerstand zur Strombegrenzung vorschalten sollte.

Output-Pins sollten immer mit einem 15-k-Widerstand nach Masse geschaltet werden, damit sie sicher low sind, auch wenn sie während dem Boot Pi-intern floating sind.

Der GPIO-Pin für die Kommunikation kann frei gewählt werden, er ist im Python-Script definiert.

Den GPIO-Pin PULSE braucht man nur, falls die Rechteck-Signalquelle im Pi benötigt wird (für einen Timer-Interrupt).

Der Testaufbau

Testaufbau iSwitchPi auf Breadboard (ohne Pi)
Testaufbau iSwitchPi auf Breadboard (ohne Pi)
Foto: Peter Boxler

Programmierung des ATtiny44: Die Entwicklung des Codes für iSwitchPi wurde auf einem Mac durchgeführt. Installiert wurde das Cross Pack for AVR Development, das folgende Komponenten enthält:

Für das Schreiben des Codes in den Speicher des Mikrocontrollers (flashen oder uploaden) wurde ein einfaches Board mit einem 28-poligen Zero-Force-Sockel gebaut, siehe Bild. Dieses Board wird über ein 10-poliges Kabel an den Programmer Olimex AVR-ISP-MK2 angeschlossen. Dieser wiederum ist via USB-Kabel mit dem Mac verbunden.

Für das Flashen wird der Uploader AVRDUDE benutzt - er wird im Makefile durch ‚make flash‘ nach der Compilation aufgerufen.

Foto: Peter Boxler

Anmerkung zur Cross Pack-Version:

Auf Mac OS X 10.9 (und höher) muss die AVRDUDE Version 5.11.1 verwendet werden, da Version 6.01 bei Verwendung eines Olimex-ISPMK2-Programmers einen Bug hat.

http://www.avrfreaks.net/forum/olimex-isp-mk2-error-mac-osx-109

http://www.avrfreaks.net/comment/1011406#comment-1011406

Ich habe deshalb Cross Pack AVR-20121203 installiert.

Fazit

Das Problem mit Hilfe Endlicher Automaten (Finite State Machines) anzugehen, war zwar aufwändig, hat aber die Lösungsfindung viel klarer gemacht. Das C-Programm für den iSwitchPi zu schreiben war dadurch relativ einfach; durch die Zustands-Diagramme und die Zustands-Tabellen war der Code klar vorgegeben. Beim Testen sind keine ernsthaften logischen Probleme des Programmablaufs aufgetreten.

Was den bekannten Satz erneut bestätigt: Erst denken, dann codieren.

Und hier geht's zu Peter Boxlers anderen Raspberry-Pi-Projekten:

Funksteckdosen schalten mit dem Raspberry Pi

Light Painting mit dem Raspberry Pi

Raspberry-Projekt: Xmas-TV mit Musik bauen

(PC-Welt/ad)