Möchten Sie eine 8×8 Punkt-Matrix mit einem Raspberry Pi und Lazarus ansteuern? Sie wissen aber nicht wie? Dann finden Sie in diesem Artikel einen Lösungsvorschlag.
Unter Lazarus gibt es für den Raspberry Pi lange nicht so viele Bibliotheken wie unter Python. Deshalb ist Python zu Recht die erste Wahl für Projekte mit dem Pi. In speziellen Fällen ist aber eine Lösung mit Lazarus besser!
Das ist meiner Meinung nach immer der Fall, wenn zusätzlich auch eine Visualisierung auf einem Bildschirm erfolgen soll. Ich möchte Ihnen in diesem Artikel genau diese Variante zeigen.
Voraussetzung für den Einsatz von Lazarus ist, dass die entsprechende Komponente auch über eine fertige Bibliothek unterstützt wird. Andernfalls muss man schon Experte sein, um diese selber zu programmieren.
Eine solche Bibliothek ist der TMS LCL HW Pack for Raspberry Pi von TMS Software. Mit ihr lässt sich eine Reihe von verschiedenen Anzeigen von Adafruit einfach ansteuern:
- 4 digit 7 segment display
- Graphik Display von Adafruit: monochrome 128×32 OLED graphic display
- Adafruit barometrix pressure/temperature sensor
- Adafruit 8×8 I2C LED matrix
Ich möchte die 8×8 LED Matrix einsetzen. Die einzige Bedingung ist, dass die Matrix über den I2C Bus angeschlossen ist.
TMS Bibliothek installieren
Bevor es losgehen kann, muss das Package für Lazarus geladen und installiert werden.
Die Seite mit weiteren Informationen zu den enthaltenen Komponenten finden Sie unter:
https://www.tmssoftware.com/site/tmslclhwpack.asp
Den Download des Lazarus Packages finden Sie unter github:
https://github.com/tmssoftware/TMS-LCL-HW-Pack-for-Raspberry-Pi
Laden Sie die ZIP-Datei herunter und entpacken Sie alle Dateien in Ihren LIB-Ordner (oder einen anderen Ordner Ihrer Wahl).
Im Lazarus Menü wählen Sie PACKAGE und dann PACKAGE-DATEI (*.LPK) ÖFFNEN. Dann wählen Sie aus Ihrem Ordner die LPK-Datei aus.
Klicken Sie auf den Button NUTZUNG und dann auf INSTALLIEREN. Damit wird das Package installiert und Lazarus neu kompiliert. Auf dem Raspberry dauert das ein wenig länger, als auf einem PC. Die Geschwindigkeit ist aber noch okay.
Nach dem Neustarten von Lazarus stehen die neuen Komponenten sofort bereit.
Matrix an den Raspberry anschließen
Der Anschluss der Matrix ist durch den I2C schnell erledigt.
- VCC >> 3V3 (Pin 1)
- GND >> GND (Pin 6)
- SDA >> SDA (Pin 3, GPIO2)
- SDL >> SDL (Pin 5, GPIO3)
Ob alles korrekt arbeitet, können Sie mit dem Befehl i2cdetect überprüfen. Öffnen Sie ein Terminal-Fenster und geben den Befehl ein. Als Ergebnis erhalten Sie die Adresse der 8×8 Matrix.
Coding in Lazarus
Die Adresse des I2C Bus wird mit i2cdetect als Hexadezimalzahl angezeigt. In Lazarus brauchen wir aber eine Dezimalzahl.
Wenn Sie die Umrechnung selber durchführen, kann sie gleich im Objektinspektor eingetragen werden.
Leichter ist es aber eine Hilfsfunktion Hex2Dec direkt im Quelltext zu benutzen. Das Display wird mit wenigen Befehlen vorbereitet.
m8x8.I2CAddress:=Hex2Dec(‘$70‘); m8x8.Open; m8x8.Rotation:=mr90; m8x8.DisplayOn; m8x8.Clear;
Beispiel App: Mini-Animation
Um Ihnen zu zeigen, wie die Programmierung in Lazarus erfolgt, erstellen wir eine Beispiel App. Sie soll es uns ermöglichen, eine kleine Animation zu designen und ablaufen zu lassen. Dazu kommen ein paar Funktionen zum Verschieben und Invertieren der 8×8 Matrix.
LEDs ein-/ausschalten
Die Komponente von TMS stellt nur wenige Funktionen zum Ein- und Ausschalten von LEDs zur Verfügung.
Die beiden wichtigsten Prozeduren sind DrawPixel(x,y) zum Einschalten und ClearPixel(x,y) zum Ausschalten von LEDs. Mit diesen beiden werden wir auch in der Beispiel App arbeiten.
Es gibt aber noch weitere, diese möchte ich Ihnen kurz vorstellen:
- procedure DrawChar(x, y: byte; c: char);
Zeichnet einen Buchstaben oder eine Zahl an die angegebene Position. - procedure DrawArrow(x,y: byte; ADirection: TArrowDirection);
Zeichnet einen Pfeil an die angegebene Position. Mögliche Werte für ADirection sind aUp, aDown, aLeft und aRight. - procedure DrawVertLine(x,y1,y2: integer);
Zeichnet eine vertikale Linie. - procedure DrawHorzLine(x1,x2,y: integer);
Zeichnet eine horizontale Linie.
Visuelle LEDs
Wie schon erwähnt ist die Stärke von Lazarus die Visualisierung. Deshalb soll die 8×8 Matrix auch im Fenster auf dem Bildschirm angezeigt werden.
Als passende Komponente für die Anzeige wähle ich ein TShape-Objekt. Zur einfachen Verwendung benutzen wir es gleich im passenden zwei-dimensionalen Array:
Led : array[0..7,0..7] of TShape;
In der Create-Prozedur des Hauptformulars werden die Shapes alle erzeugt und richtig eingestellt. Anschließend werden sie alle in ein Panel (Panel1) eingefügt.
for x:=0 to 7 do for y:=0 to 7 do begin Led[x,y]:=TShape.Create(self); with Led[x,y] do begin Width:=15; Height:=15; Brush.Color:=clWhite; Shape:=stCircle; Left:=x*20+2; Top:=y*20+2; Tag:=x*10+y; OnMouseDown:=@LedOnClick; end; Panel1.InsertControl(Led[x,y]); end;
In der Eigenschaft Tag wird die x und y Koordinate in der Matrix abgelegt. Das benutzen wir, um bei einem Anklicken der LED mit der Maus wieder die x und y Koordinate auszurechnen und damit die LED in der echten Matrix ein- oder auszuschalten.
Das erfolgt in der Prozedur LedOnClick.
procedure TMainForm.LedOnClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var w,x1,y1 : integer; begin w:=TShape(Sender).Tag; x1:=w div 10; y1:=w-x1*10; Label1.Caption:='X:'+IntToStr(x1)+' Y:'+IntToStr(y1); SetPixel(x1,y1,not GetPixel(x1,y1)); m8x8.Display; end;
Pixel ein- und ausschalten
Soll neben der echten LED-Matrix auch eine visuelle auf dem Bildschirm mitgesteuert werden, bietet es sich an, das über eine gemeinsame Funktion zu realisieren.
Statt den vorhandenen Varianten DrawPixel und ClearPixel führe ich in der Beispiel App zwei neue Elemente ein.
Die Funktion GetPixel(x,y), die als Ergebnis den Status (LED ein oder aus) als Boolean zurückliefert.
function TMainForm.GetPixel(x,y : integer) : boolean; begin result:=false; if x>7 then exit; if x<0 then exit; if y>7 then exit; if y<0 then exit; if TShape(Led[x,y]).Brush.Color=clRed then result:=true else result:=false; end;
Und der Prozedur SetPixel(x,y,Status), die den Status der LED als Boolean setzt.
procedure TMainForm.SetPixel(x,y : integer; LedOn : boolean); begin if x>7 then exit; if x<0 then exit; if y>7 then exit; if y<0 then exit; if LedOn=true then begin TShape(Led[x,y]).Brush.Color:=clRed; m8x8.DrawPixel(x,y) end else begin TShape(Led[x,y]).Brush.Color:=clWhite; m8x8.ClearPixel(x,y); end; end;
LEDs oder Pixel manipulieren
Mit dieser Funktion und dieser Prozedur ist es nun simpel, einfache Manipulationen in der echten und visuellen Matrix durchzuführen.
Die Matrix kann z. B. mit zwei for-Schleifen durchlaufen werden und gelöscht werden.
for x:=0 to 7 do for y:=0 to 7 do SetPixel(x,y,false); 8x8.Display;
Wichtig ist, dass die echte Matrix erst nach dem Befehl Display aktualisiert wird. Dieser muss also am Ende nach jeder Manipulation stehen.
Genauso einfach ist es dann die Matrix zu invertieren. Dafür steht dieser Befehl in den Schleifen:
SetPixel(x,y,not GetPixel(x,y));
Soll das Bild in der Matrix nach links verschoben werden und rechts eine neue Spalte eingefügt werden, sieht die Schleife folgendermaßen aus:
for x:=0 to 6 do for y:=0 to 7 do SetPixel(x,y,GetPixel(x+1,y)); for y:=0 to 7 do SetPixel(7,y,false); m8x8.Display;
Für die anderen drei Richtungen finden Sie die Befehle in den Schleifen in der Beispiel App.
Jetzt wird animiert!
Animieren heißt für uns in diesem Fall, dass wir vorher ein Matrix-Bild speichern müssen. Dafür wandeln wir die Zustände der LEDs (ein=1 und aus=0) in einen 64 Zeichen langen String um und speichern ihn in einer TListbox-Komponente ab.
Die Umsetzung im Code funktioniert genauso über zwei Schleifen. Ist eine LED an, wird einem String s eine 1 angefügt. Ist die LED aus, wird der String s mit einer 0 erweitert. Fertig!
if GetPixel(x,y)=true then s:=s+'1' else s:=s+'0';
Um das Matrix-Bild wieder anzuzeigen, fehlt noch zu umgekehrte Prozedur. Der 64-Zeichen-String wird Stück für Stück wieder in eine x und y Koordinate zerlegt und bei einer 1 die LED eingeschaltet.
procedure TMainForm.StrToMatrix8x8(value : string); var x,y : integer; begin for x:=0 to 7 do for y:=0 to 7 do if copy(value,x*8+y+1,1)='1' then SetPixel(x,y,true) else SetPixel(x,y,false); m8x8.Display; end;
Das eigentliche Animieren erfolgt über einen Timer. Bei jedem Timer-Ereignis wird eine globale Variable erhöht und das nächste „Bild“ aus der Listbox mit dieser Prozedur StrToMatrix8x8 angezeigt.
Das wars auch schon! Im Programm sind noch ein paar weitere Funktionen zum Ändern der Reihenfolge und Öffnen und Speichern enthalten.
Viel Spaß beim Ausprobieren!
Download
Quellcode der Beispiel-App Mini-Animation
entpacken mit tar xfvz de.tar.gz
Links
Webseite von TMS-Software: https://www.tmssoftware.com/site/tmslclhwpack.asp
TMS Package auf github: https://github.com/tmssoftware/TMS-LCL-HW-Pack-for-Raspberry-Pi
Pingback: Audio Pegel-Anzeige mit 8×8 LED Matrix – Mein Techblog
Pingback: Audio-Spektrum mit 128×32 Display – Mein Techblog
Pingback: Audio-Spektrum mit 128×32 Display – Tech+Code
Pingback: 8×8 LED-Matrix with Raspberry and Lazarus – Tech+Code
Pingback: Audio Pegel-Anzeige mit 8×8 LED Matrix – Tech+Code