Mit einem Lauflichter lassen sich auf einfache Weise tolle Effekte erzeugen. Das geht mit dem Raspberry Pi nicht nur klassisch über die Programmiersprache Python. Auch mit Lazarus und Freepascal ist das einfach möglich.
In der Basisversion kennt Lazarus noch keine Funktionen oder Klassen für die GPIO-Pins des Raspberry. Es gibt aber einige Möglichkeiten, wie man die Pins ansprechen kann.
Eine Übersicht gibt das Wiki unter http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi/de. Für dieses Projekt verwende ich das Paket PascalIO. Laden Sie es herunter und speichern es in Ihrer Larazus-Bibliothek.
PascalIO einbinden
Für einen ersten Test legen Sie sich ein neues Lazarus-Projekt an. Binden Sie das Paket PascalIO ein. Das geht am einfachsten, indem das Paket über den Menüpunkt Package aus Ihrem Ordner geladen wird. Mit dem Klick auf Zum Projekt hinzufügen ist es für Ihr Projekt verfügbar.
Ausgänge schalten
Die Verwendung von PascalIO für die GPIO-Programmierung ist sehr einfach. Im ersten Schritt müssen die entsprechenden Units aus dem Paket eingebunden werden. Sollen nur GPIO geschaltet werden, ist das die Unit fpgpio.
In diesem Beispiel wird an den GPIO18 eine LED über einen Vorwiderstand 330 Ω angeschlossen und vom Programm ein- und ausgeschaltet.
In der FormCreate Methode erfolgen, ähnlich zu Python, die Einstellungen des Pins:
- Festlegung der GPIO-Pin Nummer: Led:=TGpioLinuxPin(18);
- Art des Pins festlegen – Eingang oder Ausgang: Led.Direction:=gdOut;
Um den Pin ein- oder auszuschalten, wird die Eigenschaft Value benutzt. Sie ist vom Typ Boolean.
- Ausgang auf HIGH: Led.Value:=true;
- Ausgang auf LOW: Led.Value:=false;
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, fpgpio; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Shape1: TShape; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private Led : TGpioLinuxPin; public end; var Form1: TForm1; implementation {$R *.lfm} procedure TForm1.FormCreate(Sender: TObject); begin Led:=TGpioLinuxPin.Create(18); //GPIO18 verwenden Led.Direction:=gdOut; //als Ausgang verwenden end; procedure TForm1.Button1Click(Sender: TObject); begin Led.Value:=true; //Ausgang auf HIGH setzen Shape.Brush.Color:=clLime; end; procedure TForm1.Button2Click(Sender: TObject); begin Led.Value:=true; //Ausgang auf LOW setzen Shape.Brush.Color:=clWhite; end; procedure TForm1.FormDestroy(Sender: TObject); begin Led.Free; end; end.
Für einen Test müssen Sie das erzeugte Programm mit sudo aufrufen. Den Link dazu finden Sie am Ende des Artikels.
sudo ./test_led
Ein Lauflicht
In meinem Fall sollen 7 einzelne LED’s und eine Multi LED (3-Farb-LED) möglichst variabel angesteuert werden.
Meine Umsetzung in Lazarus basiert auf einer eigenen Klasse TLedSequence. In dieser werden alle GPIO-Pins in einer Liste zusammengefasst.
TLedSequence = class private FLedCount : integer; //Pins die angesteuert werden sollen FCount : integer; //Anzahl der Sequenzen FSequence : TStringList; //Reihenfolge der Ansteuerung FPins : TList; //Liste der GPIO-Pins public step : integer; stepstr : string; constructor Create; destructor Destroy; procedure AddPin(PinId: integer); procedure ReadSetup(Strings : TStrings); procedure NextStep; procedure AllOff; published property Count : integer read FCount write FCount; property LedCount : integer read FLedCount write FLedCount; property Sequence : TStringList read FSequence write FSequence; property Pins : TList read FPins write FPins; end;
Mit der Methode AddPin werden die GPIO-Kontakte entsprechend der Beschreibung im obigen Beispiel als Ausgang eingestellt und einer TList hinzugefügt.
procedure TLedSequence.AddPin(PinId: integer); {$IFDEF UNIX} var Pin : TGpioLinuxPin; {$ENDIF} begin {$IFDEF UNIX} Pin:=TGpioLinuxPin.Create(PinId); Pin.Direction:=gdOut; Pins.Add(Pin); FLedCount:=FLedCount+1; {$ENDIF} end;
Um die 7 LED’s so einzustellen, ist nur noch folgender Code mit Angabe des GPIO-Pins notwendig:
//Pin-Definitionen für die 7 einzelnen LED's SingleLeds:=TLedSequence.Create; SingleLeds.AddPin(14); SingleLeds.AddPin(15); SingleLeds.AddPin(18); SingleLeds.AddPin(23); SingleLeds.AddPin(24); SingleLeds.AddPin(25); SingleLeds.AddPin(8);
Die Zahlen stehen für die entsprechenden GPIO-Bezeichnungen: GPIO14, GPIO15, GPIO18 usw.
Damit sind die Vorbereitungen auch schon abgeschlossen. Jetzt geht es um die Umsetzung einer variablen Reihenfolge-Programmierung der LED’s. Die Speicherung passiert in einer TStringList. Jede Sequenz – das entspricht einer Zeile in der TStringList – ist eine Folge von 0 oder 1 (ein oder aus) für jede der 7 LED’s. In jeder weiteren Zeile, kann eine weitere Sequenz folgen.
Beispiel:
- 1000000: Nur LED1 ist eingeschaltet, alle anderen sind aus
- 1010101: LED1, LED3, LED5 und LED7 sind eingeschaltet
Der Code dafür steht in der Methode NextStep. Sie wird regelmäßig über einen Timer aufgerufen.
procedure TLedSequence.NextStep; var i,j : integer; s : string; {$IFDEF UNIX} var Pin : TGpioLinuxPin; {$ENDIF} begin step:=step+1; if step>FCount-1 then step:=0; stepstr:=FSequence[step]; {$IFDEF UNIX} for i:=0 to FLedCount-1 do begin Pin:=TGpioLinuxPin(FPins[i]); try s:=copy(FSequence[step],i+1,1); except s:='0'; end; if s='1' then Pin.Value:=true else Pin.Value:=false; end; {$ENDIF} end;
Am besten lässt sich das über ein Beispielprojekt testen. Dafür verbinden Sie die 7 LED’s und einem Vorwiderstand auf einem Breadboard mit jeweils einem GPIO-Pin. Ich möchte zusätzlich noch andere Farben haben, deshalb wird auch noch eine Multi-LED über 3 GPIO-Pins genauso angeschlossen.
Um die 3 LED’s der Multi-LED kümmert sich eine weitere Instanz von TLedSequence.
Mit dem Beispielprogramm Lauflicht Tester lassen sich verschiedene Sequenzen einfach testen. Tragen Sie Ihre Animation ein und drücken auf Start.
Auch das Beispiel-Programm müssen Sie für einen Test mit sudo aufrufen:
sudo ./test_ll
Den Link dazu finden Sie auch am Ende des Artikels.
Im Beispiel zeigt sich auch einer der Vorteile von Lazarus als Progammierumgebung für die GPIO’s des Raspberry Pi: Die einfache Visualisierung!
Mit ein paar TShape-Elementen lässt sich eine aussagefähige Visualisierung aufbauen. Und anders als in Python nicht über nur Quelltext, sondern visuell per Maus direkt im Formular.
Ich verwende das Lauflicht gleich in meinem nächsten Projekt. Der Testaufbau von oben kommt als optische Erweiterung in meinen Medienplayer. Wie dieser bisher – vor der Erweiterung – aussieht, können Sie unter TACTbox – Mein Mediaplayer nachlesen.
Jetzt aber viel Spaß beim Testen und Weiterentwickeln.
Downloads
Lauflicht mit Einzel- und 3-fach-LED
Links
- Möglichkeiten GPIO-Pins unter Lazarus zu programmieren
- Paket PascalIO
- Lazarus auf dem Raspberry Pi installieren
Die Lösung jedes Programm mit sudo aufzurufen, ist auf Dauer nicht zufriedenstellend. Eine Möglichkeit ist, die entsprechenden Ordner für den Benutzer pi zu berechtigen.
Erstellen Sie eine Datei mit diesem Inhalt unter z. B. /home/pi/skripte/gpio_init.sh
#!/bin/sh
sudo chmod -R 666 /sys/class/gpio/gpio0/value
sudo chmod -R 666 /sys/class/gpio/gpio0/direction
Dann machen Sie das Skript ausführbar mit:
chmod a+x gpio_init.sh
Das muss aber bei jedem Start neu getan werden. Um das noch zu automatisieren, fügen Sie den Aufruf in der Datei /etc/rc.local ein. Dann klappen die Programmierung und der Test unter Lazarus wesentlich einfacher.
Pingback: TACTbox+ – Mein Techblog
Pingback: Running lights and LED control with Lazarus – Tech+Code
Pingback: TACTbox+ – Tech+Code