8×8 LED-Matrix mit Raspberry und Lazarus

Titelbild

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.

Beispiel-App für die 8x8 LED Matrix erstellt mit Lazarus
Visualisierung mit Lazarus

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.

Package installieren
Package installieren und Lazarus neu kompilieren

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.

TMS LCL Raspi HW
Neue Komponenten von TMS

 

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.

i2cdetect
Adresse der 8×8 Matrix im I2C

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.

Objektinspektor
Objektinspektor von TTMSLCLAda8x8MatrixLed

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.

Beispiel App
Beispiel App zum Designen von kleinen Animationen

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!

Animationsbeispiel für 8x8 LED Matrix
Animationsbeispiel: Matrix und Bildschirm

Download

symbol_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


Read this article in English.

Dieser Beitrag hat 5 Kommentare

Kommentar verfassen