LED Matrix Display ansteuern • Wolles Elektronikkiste (2024)

Über den Beitrag

In diesem Beitrag möchte ich euch Methoden vorstellen, wie ihr ein LED Matrix Display (engl.: Dot Matrix Display) ansteuern könnt. Das ist natürlich nicht der erste Beitrag zu diesem Thema im Netz, aber vielleicht gibt es doch noch das eine oder andere Neue für euch zu entdecken. Im Einzelnen behandele ich die folgenden Themen:

  • Was ist ein LED Matrix Display und wie funktioniert es?
  • Direkte Ansteuerung mit einem Arduino
  • Ansteuerung über den MAX7219 / MAX7221 (mit Bibliothek)
  • Verwendung von Displays mit integriertem MAX7219
  • Programmierung einer Laufschrift
  • Ansteuerung über den MAX7219 / MAX7229 ohne Bibliothek
  • Anhang: Ansteuerung eines zweifarbigen, TA6932-basierten Matrix Displays

Als Appetizer hier schon mal ein kleines Video:

Was ist ein LED Matrix Display und wie funktioniert es?

Ein LED Matrix Display ist ein LED Dioden Array. Jeweils ein Eingangs- bzw. Ausgangspin verbindet die LEDs einer Reihe (Row) bzw. einer Spalte (Column). Ob die Reihen oder die Spalten die Ein- oder Ausgänge sind, variiert von Display zu Display.

Durch Anlegen einer Spannung an einen Eingangspin und durch Verbinden eines Ausgangspins mit Ground bringt ihr genau eine LED am Schnittpunkt zum Leuchten.

Wenn ihr keinen Ansteuerungs-IC wie den MAX7219 oder MAX7221 verwendet, dann müsst ihr Vorwiderstände einsetzen. Die benötigte Größe hängt von den technischen Daten eurer Displays ab. Meistens liegt ihr aber bei 5 Volt mit 330 Ohm schon richtig.

Noch eine Anmerkung zum Schema oben: normalerweise findet man in Datenblättern die Reihen- und Spaltennummern von 1 bis 8. Gewöhnt euch lieber die Nummerierung 0 bis 7 an. Denn dann denkt ihr gleich „richtig“ in Bits und Bytes und das ist bei der Ansteuerung hilfreich.

Und noch etwas: wenn ich eine LED Position (einen Dot) in diesem Beitrag als Wertepaar (a/b) angebe, dann ist a die Reihe und b die Spalte. Also nicht wie x und y im Koordinatensystem.

Woher bekommt Ihr LED Matrix Displays?

LED Matrix Displays gibt es in vielen verschiedenen Ausfertigungen. Dabei variiert die Anzahl der LEDs (Dots), die Größe der Displays und die Farbe der LEDs. Darüber hinaus gibt es sie mit integriertem Ansteuerungs-IC und teilweise auch im Verbund, z.B. als 8 x 8 x 4. Sucht in dem Online-Shop eures Vertrauens nach „LED Matrix Display“ oder „Dot Matrix“. Die Preise variieren recht stark mit der Herkunft und der Menge.

Direkte Ansteuerung per Microcontroller oder Arduino

Ich verwende als Beispiel das oben schematisch abgebildete 8×8 LED Matrix Display mit Reihen-Eingang und Spalten-Ausgang. Vorab: die Verdrahtung macht keinen Spaß, da acht Eingänge, acht Ausgänge und acht Widerstände verbunden werden müssen. Außerdem sind die Reihen und Spalten den Pins ohne erkennbares System zugeordnet. Da müsst ihr ziemlich viel suchen. Teilweise ist auch nicht offensichtlich welches der Pin 1 ist. In diesem Fall müsst ihr erstmal ein wenig ausprobieren.

Der ganze erste Abschnitt dient denn auch mehr der Didaktik als der Praxis. Ansteuerungs-ICs wie der MAX7219 machen das Leben leichter. Und noch komfortabler sind die Displays mit integrierter Ansteuerung. Da komme ich dann später zu. Trotzdem sollte man erstmal das Prinzip verstanden haben.

Beschaltung

Bei 16 benötigten Ein- und Ausgängen müssen auf dem Arduino auch die analogen Pins mit einbezogen werden. Oder ihr verwendet eine Portweiterung wie den MCP23017.

So sieht die Beschaltung schematisch und praktisch aus:

Ein kleiner Beispielsketch

Im folgenden Beispielsketch werden zunächst die Arduino Pins für die Reihen und Spalten definiert. Die Eingänge (Reihen) werden auf LOW gesetzt, die Ausgänge (Spalten) auf HIGH. Damit sind alle LEDs aus. Eine LED an der Stelle „r/c“ wird angeschaltet, wenn die Reihe „r“ auf HIGH gesetzt wird und die Spalte „c“ auf LOW.

Als erste kleine Spielerei gibt es ein Lauflicht. Dabei geht jede LED einmal kurz an. Dann wird die Diagonale von (0/0) bis (7/7) zum Leuchten gebracht.

#define r0 2 // pin for row 0#define r1 3 // pin for row 1#define r2 4 // ...#define r3 5#define r4 6#define r5 7#define r6 8#define r7 9#define c0 10 // pin for column 0#define c1 11 // pin for column 1#define c2 12 // ...#define c3 13#define c4 A0#define c5 A1#define c6 A2#define c7 A3int row[] = {r0, r1, r2, r3, r4, r5, r6, r7};int column[] = {c0, c1, c2, c3, c4, c5, c6, c7}; void setup() { for(int i = 0; i<=7; i++){ pinMode(row[i], OUTPUT); } for(int i = 0; i<=7; i++){ pinMode(column[i], OUTPUT); } clearDisplay();}void loop() { for(int i=0; i<=7; i++){ for(int j=0; j<=7; j++){ switchLED(row[i],column[j],1); delay(100); switchLED(row[i],column[j],0); } }}void clearDisplay(){ for(int i = 0; i<=7; i++){ digitalWrite(row[i],LOW); } for(int i = 0; i<=7; i++){ digitalWrite(column[i], HIGH); } }void switchLED(int r, int c, bool ON){ if(ON){ digitalWrite(r, HIGH); digitalWrite(c, LOW); } else{ digitalWrite(r, LOW); digitalWrite(c, HIGH); }}

Unerwünschte Querbeeinflussung

Ersetzt im letzten Sketch einmal die Sketch Hauptschleife durch die folgende:

void loop() { switchLED(row[0],column[0],1); delay(1000); switchLED(row[0],column[1],1); delay(1000); switchLED(row[1],column[0],1); delay(1000); clearDisplay();}

Eigentlich soll der Sketch die Dots (0/0), (0/1) und (1/0) anschalten. Das tut er zwar auch, aber mit dem Dot (1/0) wird auch (1/1) angeschaltet. Falls euch nicht klar sein sollte, warum das so ist, schaut dazu noch einmal in das Schema des 8×8 Displays. Dann sollte die Problematik offensichtlich sein.

Die Lösung: Multiplexing

Ersetzt nun noch einmal die Hauptschleife durch die folgende:

void loop() { switchLED(row[0],column[0],1); delay(1); switchLED(row[0],column[0],0); switchLED(row[0],column[1],1); delay(1); switchLED(row[0],column[1],0); switchLED(row[1],column[0],1); delay(1); switchLED(row[1],column[0],0);}

In diesem Fall leuchten tatsächlich nur die Dots (0/0), (0/1) und (1/0), da jeder Dot separat für kurze Zeit angeschaltet wird. Ein Flackern sieht man nicht, dafür ist der Wechsel zu schnell.

Die Grenzen des einfachen Multiplexings

Zunehmendes Multiplexing in dieser Form führt zu einer Abnahme der Intensität. Im folgenden Beispiel ist der Dot (7,7) immer an, der Rest der Diagonale ist „gemultiplext“. Dass der Rest von Reihe und Spalte 7 auch leuchten, ist ein Nebeneffekt.

Zu beachten: Die Sketchzeilen 1 und 2 gehören noch ins Setup.

 switchLED(row[7],column[7], 1);}void loop() { for(int i=0; i<=6; i++){ switchLED(row[i],column[i],1); delay(1); switchLED(row[i],column[i],0); }}

Auf dem Foto erkennt man die Unterschiede nicht so gut wie in der Realität. LEDs sind nicht einfach zu fotografieren. Dennoch könnt ihr vielleicht erahnen, dass der Dot (7,7) heller ist.

Auch für dieses Problem gibt es eine Lösung. Über Pulsweitenmodulation (PWM, siehe mein Beitrag über Timer) lässt sich die Intensität je nach Anzahl der „gemultiplexten“ LEDs gewichten. Darauf gehe ich aber jetzt nicht näher ein und möchte die bequemere und allgemein übliche Lösung vorstellen.

Ansteuerung mit dem MAX7219 / MAX7221

Alle eben genannten Probleme lassen sich mit den Ansteuerungs-ICs MAX7219 oder MAX7221 lösen. Da beide fast identisch sind, nenne ich ab jetzt nur den MAX7219, meine aber beide.

Primär ist der MAX7219 für die Ansteuerung von 7-Segment Displays konzipiert. Er lässt sich aber auch für die Ansteuerung von LED Matrix Displays oder losen LED Arrangements verwenden. Das ist auch nicht weiter verwunderlich, da die Ansteuerung mehrerer 7-Segment Anzeigen im Grunde dieselbe Herausforderung wie die Ansteuerung eines LED Matrix Displays darstellt.

Pinout und technische Eigenschaften des MAX7219

Der MAX7219 besitzt 24 Pins:

  • Die Pins SEG X liefern die positive Spannungsversorgung
    • Ob diese mit den Reihen- oder Spaltenpins verbunden werden, hängt davon ab, wie herum die LEDs im Display verbaut sind.
  • Die Pins DIG X schalten nach GND.
  • Der MAX7219 wird per SPI angesteuert:
    • DIN ist der Data Input, also MOSI (Master Out, Slave In).
    • Ein MISO (Master In, Slave Out) gibt es nicht; es ist also eine One-Way Kommunikation.
    • CLK: Clock Pin.
    • LOAD / CS: Chip Select Pin.
  • Wenn ihr mehrere Displays verwendet, wird DOUT mit dem DIN des nächsten Displays verbunden.
  • An VCC dürfen 4 bis 5.5 Volt verwendet werden
  • An ISET wird die Höhe des Stroms für die LEDs eingestellt. Ich habe 10 kOhm verwendet. Im Datenblatt des MAX7219 gibt es eine grafische Darstellung, welcher Strom mit welchem Widerstand bei welcher Spannung bereitgestellt wird.

Verwendung der Bibliothek LedControl

Zur Ansteuerung des MAX7219 verwende ich die Bibliothek LedControl von Eberhard Fahle, die ihr von Github oder direkt über die Bibliotheksverwaltung der Arduino IDE installieren könnt. Eine sehr gute Einführung gibt es hier.

Die Bibliothek erwartet eigentlich den Spannungseingang an den Spalten und den Spannungsausgang an den Reihen. Das ist bei dem von mir verwendeten Modell anders herum. Man kann einfach entsprechend andersherum verkabeln (Segx an die Reihenpins, Digx an die Spaltenpins), muss dann aber nachher noch etwas umdenken.

Der MAX7219 besitzt nicht sonderlich viele Register. Deshalb lässt er sich auch ohne all zu viel Aufwand ohne Bibliothek ansteuern. Wie das geht, zeige ich am Ende dieses Beitrages.

Was die Komplexität der Verkabelung des LED Matrix Displays angeht, bringt der MAX7219 noch keinen großen Vorteil, aber immerhin braucht ihr die Vorwiderstände nicht:

Zu beachten ist, dass die oben abgebildete Verkabelung spezifisch für das von mir verwendete LED Matrix Display ist. Vielleicht sind die Anschlüsse eures Displays gleich, vielleicht aber auch nicht.

Ein kleiner Beispielsketch

#include <LedControl.h>//12= data pin(DIn), 11= CLK Pin, 10= Load/CS Pin, 1 = num of devicesLedControl lc88=LedControl(12,11,10,1); void setup(){ lc88.shutdown(0,false); // Wake up! 0= index of first device; lc88.setIntensity(0,2); lc88.clearDisplay(0); delay(500);}void loop(){ for(int row=0; row<=7; row++){ lc88.setLed(0,row,0,true); delay(250); } for(int col=0; col<=7; col++){ lc88.setLed(0,0,col,true); delay(250); } delay(500); lc88.clearDisplay(0); delay(2000); }

An diesem Beispiel sollten die meisten Funktionen der Bibliothek schon klar werden:

  • zunächst wird ein Display Objekt erzeugt und dabei die Anschluss Pins und die Zahl der Einzeldisplays festgelegt
  • shutdown(display, false) weckt das Display; mit true geht es schlafen
  • setIntensity(display, value) legt die Helligkeit der Dots fest mit 0 <= value < 16
  • clearDisplay(display) schaltet alle Dots eines Displays aus
  • setLed(display, row, col, true/false) schaltet genau einen Dot in Reihe row und Spalte col an oder aus.

Weitere nützliche Funktionen, die ihr selber ausprobieren könnt, sind:

  • setRow(display, row, val) – die Reihe row eines Displays wird mit dem Wert val belegt, z.B. 0b11110000 -> die ersten vier LEDs sind an, die letzten vier aus
  • setColumn(display, col, val) – wie setRow, nur eben zum Setzen von Spalten
    • diese Funktion ist erheblich langsamer als die setRow-Funktion, da sie die setLed-Funktion (achtmal pro setColumn) verwendet.

Da ich bei meinem LED Matrix Display die SEG und die DIG Anschlüsse vertauschen musste, sind auch Reihen und Spalten vertauscht. Eigentlich sollte der Sketch erst die Spalte 0 und dann die Reihe 0 füllen. Offensichtlich ist es anders herum:

Auf dem Bild oben seht ihr, dass die obere Reihe schon komplett leuchtet und nun die linke Spalte vervollständigt wird.

Eine Lösung lautet, das Display einfach um 90° gegen den Uhrzeigersinn zu drehen. Dann ist der Dot (0/0) unten links (wie in einem Koordinatenkreuz) und nicht oben links. Ihr müsst dann bei der Zeilennummerierung umdenken.

Verwendung von Displays mit integriertem MAX7219

8x8x1 LED Matrix Display

Wer es bequem haben möchte, dem rate ich zur Verwendung von Displays mit integriertem MAX7219. Die Verkabelung solcher Teile sieht schon deutlich angenehmer aus:

LED Matrix Display ansteuern • Wolles Elektronikkiste (10)

Wo der Nullpunkt (0/0) liegt, kann unter Umständen überraschend sein. Probiert es aus. Dieses LED Matrix Display macht es wie erwartet:

Hinweis: wenn ihr alle LEDs eines 8×8 Matrix Displays gleichzeitig leuchten lasst, dann kann der Strombedarf mehrere 100 mA pro Display betragen. Bei Verwendung mehrerer Displays könnt ihr dann sehr locker die Limits des Arduinos überschreiten. Mehr als 500 mA solltet ihr einem Arduino UNO bzw. eurem USB Anschluss nicht zumuten. Setzt ggf. eine separate Stromquelle ein.

8x8x4 LED Matrix Display

Wollt ihr mehrere Displays aneinanderhängen, kommt für euch vielleicht ein Verbunddisplay infrage. Vor allem sind 8x8x4 Displays weit verbreitet. Auch hier seid ihr unter Umständen überrascht, wo sich der Dot (0,0) befindet. Zum Testen habe ich den folgenden kurzen Sketch verwendet:

#include "LedControl.h"LedControl lc884=LedControl(12,11,10,4);unsigned long delaytime=3000;void setup() { for(int i=0;i<4;i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop() { lc884.setRow(0,0,B01111111); lc884.setRow(1,1,B00111111); lc884.setRow(2,2,B00011111); lc884.setRow(3,3,B00001111); }

Eigentlich hätte ich gerne das Display 0 links und das Display 4 rechts. Außerdem hätte ich gerne den Nullpunkt oben links und eine Reihenabbildung, die der Reihenfolge der Bits entspricht. D.h. ein 0b00001111 soll vier Dots einer Reihe rechts leuchten lassen und nicht links. Ich habe zwei Displays aus unterschiedlichen Quellen getestet und mit beiden konnte ich nicht alle Wünsche erfüllen. Mit einer umgekehrten Displayreihenfolge konnte ich am ehesten leben:

Display 0 ist hier rechts, dafür ist aber der Rest so wie ich es will. Diese Anordnung verwende ich im Folgenden für die Entwicklung der Laufschrift. Wenn euer Display die Dinge anders abbildet, dann müsst ihr die Sketche entsprechend anpassen.

Programmierung einer Laufschrift (Banner)

Vorbereitung: Kreieren und Darstellen von Buchstaben

Buchstaben, Zahlen und Zeichen sind auf einem Blatt kariertem Papier schnell entwickelt. Dann schreibt ihr das Ergebnis zeilenweise im Byteformat in Arrays. Im folgenden Sketch seht ihr Beispiele für A,r,d,u,i,n und o. Ich habe die Buchstaben recht schmal gemacht, da ich sie später noch „zusammenschieben“ möchte, sodass der ganze Arduino Schriftzug auf einmal auf das Display passt.

Die Buchstaben werden zunächst nacheinander auf dem Display 0 dargestellt. Dann machen wir den ersten Schritt in Richtung Laufschrift, indem wir die Buchstaben Display-weise von rechts nach links durchlaufen lassen. Mein Bezugsdisplay ist dabei das nicht sichtbare, virtuelle Display -1.

#include "LedControl.h"LedControl lc884=LedControl(12,11,10,4);unsigned long delayTime=500;byte a[8]={B00000000,B01100000,B10010000,B10010000,B10010000,B11110000,B10010000,B10010000};byte r[8]={B00000000,B00000000,B00000000,B10100000,B11010000,B10000000,B10000000,B10000000};byte d[8]={B00000000,B00010000,B00010000,B00010000,B01110000,B10010000,B10010000,B01110000};byte u[8]={B00000000,B00000000,B00000000,B10010000,B10010000,B10010000,B10010000,B01110000};byte i[8]={B00000000,B00000000,B01000000,B00000000,B01000000,B01000000,B01000000,B01000000};byte n[8]={B00000000,B00000000,B00000000,B10100000,B11010000,B10010000,B10010000,B10010000};byte o[8]={B00000000,B00000000,B00000000,B01100000,B10010000,B10010000,B10010000,B01100000};void setup() { for(int i=0;i<4;i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop() { oneMatrix(); fourMatrices(); delay(1000);}void oneMatrix(){ displayCharAndWait(a,0); displayCharAndWait(r,0); displayCharAndWait(d,0); displayCharAndWait(u,0); displayCharAndWait(i,0); displayCharAndWait(n,0); displayCharAndWait(o,0);}void displayCharAndWait(byte* x, byte displayNumber){ lc884.clearDisplay(displayNumber); for(int j=0; j<=7;j++){ lc884.setRow(displayNumber,j,x[j]); } delay(delayTime); lc884.clearDisplay(displayNumber); }void fourMatrices(){ for(int j=0; j<=10; j++){ int currentMatrix = -1; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(a,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(r,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(d,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(u,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(i,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(n,currentMatrix+j); } currentMatrix--; if( ((currentMatrix+j)>=0) && ((currentMatrix+j)<4) ){ displayChar(o,currentMatrix+j); } delay(delayTime); for(int i=0; i<=4; i++){ lc884.clearDisplay(i); } } }void displayChar(byte *x, int displayNumber){ lc884.clearDisplay(displayNumber); for(int j=0; j<=7;j++){ lc884.setRow(displayNumber,j,x[j]); }}

Wie das im Ergebnis aussieht, könnt ihr in dem Video zu Beginn des Beitrages sehen. Hier ein Ausschnitt:

Ein Zwischenschritt: statische Darstellung als unsigned long Array

Das Durchlaufen „Display für Display“ war einfach. Aber es ist auch noch nicht besonders schick. Schöner wäre ein Verschieben „Dot für Dot“. Zugegebenermaßen habe ich mich damit schwerer getan als ich dachte. Ich zeige ein paar Lösungen. Vielleicht denke ich auch zu kompliziert – wenn ihr einfachere Methoden habt, immer her damit!

Für meinen Lösungsweg Nr. 1 kommt hier erst einmal ein Zwischenschritt. Zunächst habe ich die Buchstaben so zusammengefasst, dass sie auf das Viererdisplay passen. Dazu habe ich die Zwischenräume auf ein Mindestmaß reduziert und alle 0ten, 1sten, 2ten….7ten Reihen in jeweils einem unsigned long Wert zusammengefasst. Da eine unsigned long Variable 32 bits hat, entspricht das der Breite des 4er Displays. Bei der späteren Darstellung auf dem Display muss man den Wert dann allerdings wieder in bytes „aufdröseln“. Das macht die Funktion displayBanner().

#include "LedControl.h"LedControl lc884=LedControl(12,11,10,4);long delayTime=500;unsigned long banner[8]={0b00000000000000000000000000000000, 0b01100000000001000000000000000000, 0b10010000000001000000100000000000, 0b10010101000001010010001010001100, 0b10010110100111010010101101010010, 0b11110100001001010010101001010010, 0b10010100001001010010101001010010, 0b10010100000111001110101001001100}; void setup() { for(int i=0;i<4;i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop() { displayBanner(); delay(500);}void displayBanner(){ byte currentMatrix[8]; for(int j=0; j<4; j++){ for(int i=0; i<8; i++){ currentMatrix[i] = (((banner[i])>>(j*8)) & 0b11111111); } displayMatrix(currentMatrix,j); }}void displayMatrix(byte *matrix, int matrixNumber){ for(int i=0; i<=7;i++){ lc884.setRow(matrixNumber,i,matrix[i]); }}

Und so sieht das Ergebnis aus:

Das unsigned long Array dotweise laufen lassen

Der Vorteil der Darstellung als unsigned long array ist, dass die Verschiebung wesentlich leichter über Binäroperationen zu programmieren ist als Byte für Byte. Das Banner wird schrittweise nach links verschoben und auf die Einzeldisplays aufgeteilt. Beim Nachvollziehen des Sketches vergesst nicht, dass sich das Display 0 rechts befindet.

Als kleines Feature habe ich noch eingebaut, dass das Banner kurz stoppt, wenn es vollständig auf dem Display ist. Es wird kurz heller, dann wieder dunkler und läuft dann aus dem Display. Das Ergebnis seht ihr im Video zu Beginn des Beitrages.

#include "LedControl.h"LedControl lc884=LedControl(12,11,10,4);long delayTime=150;unsigned long banner[8]={0b00000000000000000000000000000000, 0b01100000000001000000000000000000, 0b10010000000001000000100000000000, 0b10010101000001010010001010001100, 0b10010110100111010010101101010010, 0b11110100001001010010101001010010, 0b10010100001001010010101001010010, 0b10010100000111001110101001001100}; void setup() { for(int i=0;i<4;i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop() { calcCurrentBanner(); delay(500);}void calcCurrentBanner(){ unsigned long currentBanner[8]; for(int i=32; i>=0; i--){ for(int j=0; j<8; j++){ currentBanner[j] = (banner[j])>>i; } displayBanner(currentBanner); delay(delayTime); } stopAndHighlight(); for(int i=0; i<33; i++){ for(int j=0; j<8; j++){ currentBanner[j] = (banner[j])<<i; } displayBanner(currentBanner); delay(delayTime); }}void displayBanner(unsigned long *cb){ byte currentMatrix[8]; for(int j=0; j<4; j++){ for(int i=0; i<8; i++){ currentMatrix[i] = (((cb[i])>>(j*8)) & 0b11111111); } displayMatrix(currentMatrix,j); }}void displayMatrix(byte *matrix, int matrixNumber){ for(int i=0; i<=7;i++){ lc884.setRow(matrixNumber,i,matrix[i]); }}void stopAndHighlight(){ for(int i=8; i<16; i++){ for(int j=0;j<4;j++){ lc884.setIntensity(j,i); delay(20); } } delay(1000); for(int i=15; i>=8; i--){ for(int j=0;j<4;j++){ lc884.setIntensity(j,i); delay(20); } }}

Gößere Banner laufen lassen

Nun passt das, was ihr vielleicht als Banner über das Display laufen lassen wollt, nicht unbedingt auf das Display bzw. in ein unsigned long Array. Aber das geht auch. Als Beispiel nehme ich den ungekürzten Arduino Schriftzug, der sich über sieben Einzeldisplays erstreckt. Diesen verteile ich in ein zweidimensionales unsigned long Array „bannerPart[2][8]“. Dabei verschwende ich natürlich ein wenig Speicherplatz, da ich das Array nicht ganz nutze.

Die Übernahme der einzelnen Buchstaben in das Array bannerPart habe ich diesmal automatisiert. Das geschieht im Setup in den ersten beiden for-Schleifen. In calcCurrentBanner() finden sich drei for-Schleifen, die für drei Phasen stehen. In der ersten Phase wird das erste Bannerteil hineingeschoben. Während der zweiten Phase geht das erste Teil hinaus und die frei werdenden Bereiche werden mit dem zweiten Bannerteil aufgefüllt. In der dritten Phase wird das zweite Bannerteil hinausgeschoben.

#include "LedControl.h"LedControl lc884=LedControl(12,11,10,4);long delayTime=150;byte banner[7][8]={{B00000000,B01100000,B10010000,B10010000,B10010000,B11110000,B10010000,B10010000}, {B00000000,B00000000,B00000000,B10100000,B11010000,B10000000,B10000000,B10000000}, {B00000000,B00010000,B00010000,B00010000,B01110000,B10010000,B10010000,B01110000}, {B00000000,B00000000,B00000000,B10010000,B10010000,B10010000,B10010000,B01110000}, {B00000000,B00000000,B01000000,B00000000,B01000000,B01000000,B01000000,B01000000}, {B00000000,B00000000,B00000000,B10100000,B11010000,B10010000,B10010000,B10010000}, {B00000000,B00000000,B00000000,B01100000,B10010000,B10010000,B10010000,B01100000}};unsigned long bannerPart[2][8];void setup(){ unsigned long b1, b2, b3; for(int i=0; i<8; i++){ unsigned long b1, b2, b3; b1 = ((unsigned long)(banner[0][i]))<<24; b2 = ((unsigned long)(banner[1][i]))<<16; b3 = ((unsigned long)(banner[2][i]))<<8; bannerPart[0][i] = b1 + b2 + b3 + banner[3][i]; } for(int i=0; i<8; i++){ unsigned long b1, b2, b3; b1 = ((unsigned long)(banner[4][i]))<<24; b2 = ((unsigned long)(banner[5][i]))<<16; b3 = ((unsigned long)(banner[6][i]))<<8; bannerPart[1][i] = b1 + b2 + b3; } for(int i=0;i<4;i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop() { calcCurrentBanner(); delay(500);}void calcCurrentBanner(){ unsigned long currentBanner[8]; for(int i=32; i>=0; i--){ for(int j=0; j<8; j++){ currentBanner[j] = (bannerPart[0][j])>>i; } displayBanner(currentBanner); delay(delayTime); } for(int i=1; i<=32; i++){ for(int j=0; j<8; j++){ currentBanner[j] = ((bannerPart[0][j])<<i) + ((bannerPart[1][j])>>(32-i)); } displayBanner(currentBanner); delay(delayTime); } for(int i=1; i<=24; i++){ for(int j=0; j<8; j++){ currentBanner[j] = (bannerPart[1][j])<<i; } displayBanner(currentBanner); delay(delayTime); }}void displayBanner(unsigned long *cb){ byte currentMatrix[8]; for(int j=0; j<4; j++){ for(int i=0; i<8; i++){ currentMatrix[i] = (((cb[i])>>(j*8)) & 0b11111111); } displayMatrix(currentMatrix,j); }}void displayMatrix(byte *matrix, int matrixNumber){ for(int i=0; i<=7;i++){ lc884.setRow(matrixNumber,i,matrix[i]); }}

Das Ergebnis findet ihr wieder im Video.

Wenn ihr eigene Banner mit einer anderen Breite kreiert, dann müsst ihr einige Werte im Sketch anpassen. Ich hatte offengestanden keine Lust mehr den Sketch zu verallgemeinern.

Weitere Methoden

Das Verschieben mittels Byte Arrays ist etwas komplizierter als man zunächst meinen sollte. Zumindest habe ich mich damit ein wenig schwergetan. Ihr findet den Sketch am Schluss des Beitrages.

Die mit Abstand einfachste Methode wäre ein bool Array, in dem jeder Dot eine separate Variable ist. In dieses Array könnte man auch die vier leeren Displays zu Beginn und die vier leeren Displays am Ende integrieren. Macht 4 + 7 (für das Arduino Banner) + 4 = 15 Einzeldisplays. Daraus würde ein 120 x 8 Array mit 960 bool Werten entstehen. Das Durchlaufen des Banners wäre so sehr einfach zu programmieren. Aber leider belegt jede bool Variable ein ganzes Byte. Diese Verschwendung von Speicherplatz ist mir dann doch zu groß.

LED Matrix Display Ansteuerung ohne MAX7219 Bibliothek

Wie schon erwähnt, hat der MAX7219 nicht übermäßig viele Register und kann deswegen recht leicht auch ohne Bibliothek angesteuert werden. Im nächsten Sketch könnt ihr sehen wie das geht.

Ich möchte den Sketch aber auch nicht im Detail erläutern, da der Beitrag sowieso schon so lang ist. Wenn ihr euch das Datenblatt danebenlegt, sollte er nicht so schwer zu verstehen sein. Wenn ihr trotzdem Fragen habt, fragt! Nur ein paar Anmerkungen:

  • Der Sketch verwendet die Standard SPI Anschlüsse für MOSI und CLK (beim UNO Pin 11 bzw. 13). Ihr müsst also ein wenig umstöpseln.
  • MISO gibt es nicht, der MAX7219 ist nicht gesprächig.
  • Da es kein MISO gibt, lässt sich der Zustand der Dots nicht abfragen.
  • Da man bei der setLed Funktion nur einzelne Dots ändern möchte, aber nur ganze Reihen Bytes schreiben kann, muss der Sketch sozusagen Buch führen. Das macht er über das Array dots.
#include <SPI.h>const int slaveSelectPin = 10;const int totalDevs = 4;const int colsPerDev = 8;const int rowsPerDev = 8;byte dots[totalDevs][rowsPerDev] = {0}; // in diesem Array wird der Zustand der Dots gespeichertbyte a[8]={B00000000,B01100000,B10010000,B10010000,B10010000,B11110000,B10010000,B10010000};void setup(){ SPI.begin(); pinMode(slaveSelectPin, OUTPUT); digitalWrite(slaveSelectPin, HIGH); for(int device=0; device<totalDevs; device++){ wakeUp(device); // Normal Operation (shutdown beenden) displayTest(device,500); writeRegister(device,0x09,0x00); // Decode: 00 = Einzeldots, kein decoding setIntensity(device, 6); writeRegister(device,0x0B,0x07); // alle Reihen werden angezeigt clearDevice(device); } delay(500);}void loop(){ setRow(0,0,B11111000); delay(1000); setLED(0,0,5,0); delay(1000); setLED(0,0,7,0); delay(1000); displayChar(1, a);} void clearDevice(int device){ for(int row=0; row<=rowsPerDev; row++){ //alles ausschalten writeRegister(device,byte(row),0x00); }}void setIntensity(int device, int intensity){ writeRegister(device,0x0A,intensity);}void displayTest(int device, int testTime){ writeRegister(device,0x0F,0x01); //Display Test ein delay(testTime); writeRegister(device,0x0F,0x00); //Display Test aus}void wakeUp(int device){ writeRegister(device,0x0C,0x01);}void shutDown(int device){ writeRegister(device,0x0C,0x00);}void setRow(int device, byte row, byte data){ dots[device][row] = data; writeRegister(device, row+1, data); }void setLED(int device, byte row, byte col, bool on){ byte reg = row; byte dataToSend; byte mask; if(on){ mask = (1<<(col)); dots[device][row] |= mask; } else{ mask = ~(1<<(col)); dots[device][row] &= mask; } dataToSend = dots[device][row]; writeRegister(device, reg+1, dataToSend);}void displayChar(int device, byte *character){ for(int i=0; i<=7; i++){ dots[device][i] = character[i]; writeRegister(device,i+1,character[i]); }}void writeRegister(int device, byte reg, byte data){ digitalWrite(slaveSelectPin, LOW); for(int i=0; i<(totalDevs-device); i++){ SPI.transfer(0x00); SPI.transfer(0x00); } SPI.transfer(reg); SPI.transfer(data); for(int i=0; i<device; i++){ SPI.transfer(0x00); SPI.transfer(0x00); } digitalWrite(slaveSelectPin, HIGH);}

Zu guter Letzt…

…noch der Banner Sketch auf Basis der Byte Arrays. Hier habe ich als Denkmodell ein virtuelles Display verwendet, welches das physikalische Display quasi von rechts nach links durchwandert (siehe Schema unten). Ein bisschen wie ein Filmstreifen, der im Projektor hinter dem Objektiv entlang läuft.

Ich habe den Sketch so verfasst, dass ihr ihn leicht auf andere Displaygrößen anpassen könnt. Ich habe ihn z.B. auf zwei hintereinandergeschalteten 8x8x4 Matrix Display laufen lassen (dazu musste lediglich die numberOfPhysicalDisplays von vier auf acht geändert werden:

Der Sketch ist recht kompakt, aber einigermaßen schwer „verdaulich“. Ich habe versucht, ihn durch Kommentare halbwegs verständlich zu gestalten. Viel Spaß beim Nachvollziehen meiner Logik!

#include "LedControl.h"const unsigned int delayTime = 150;const int numberOfCharacters = 7; // = A,r,d,u,i,n,oconst int numberOfPhysicalDisplays = 4; // 4 Matrix Displaysconst int displayWidth = 8; // 8x8 Formatconst int displayHeight = 8;int numberOfSteps; // Anzahl Verschiebeschritteint numberOfVirtualDisplays; // Anzahl virtuelle Displays LedControl lc884=LedControl(12,11,10,numberOfPhysicalDisplays);byte banner[7][8]={{B00000000,B01100000,B10010000,B10010000,B10010000,B11110000,B10010000,B10010000}, {B00000000,B00000000,B00000000,B10100000,B11010000,B10000000,B10000000,B10000000}, {B00000000,B00010000,B00010000,B00010000,B01110000,B10010000,B10010000,B01110000}, {B00000000,B00000000,B00000000,B10010000,B10010000,B10010000,B10010000,B01110000}, {B00000000,B00000000,B01000000,B00000000,B01000000,B01000000,B01000000,B01000000}, {B00000000,B00000000,B00000000,B10100000,B11010000,B10010000,B10010000,B10010000}, {B00000000,B00000000,B00000000,B01100000,B10010000,B10010000,B10010000,B01100000}};void setup(){ numberOfVirtualDisplays = numberOfPhysicalDisplays + numberOfCharacters; // das virtuelle Gesamtdisplay besteht aus 4 leeren Displays + Anzahl der Zeichen numberOfSteps = numberOfVirtualDisplays * displayWidth; for(int i=0;i<numberOfPhysicalDisplays; i++){ lc884.shutdown(i,false); lc884.setIntensity(i,8); lc884.clearDisplay(i); }}void loop(){ for(int i=0; i<= numberOfSteps; i++){ calcVisibleBannerPart(i); }}void calcVisibleBannerPart(int step){ int currentFirstVirtualDisplay = step/displayWidth; // Erstes virtuelles Display, dass auf dem physikalischen Display abgebildet wird int bitPosition = step % displayWidth; // Bit-Position, an der die virtuellen Displays auf zwei benachbarte physikalische Displays verteilt werden byte matrixToDisplay[8]; // abzubildende Matrix for(int currentPhysicalDisplay=0; currentPhysicalDisplay<numberOfPhysicalDisplays; currentPhysicalDisplay++){ // Gehe die physikalischen Displays durch if( (currentFirstVirtualDisplay + currentPhysicalDisplay) == (numberOfPhysicalDisplays - 1)){ for(int i=0; i < displayHeight; i++){ matrixToDisplay[i] = banner[0][i] >> (8 - bitPosition); } displayMatrix(matrixToDisplay,(numberOfPhysicalDisplays-1 - currentPhysicalDisplay)); // mein 0tes Display ist rechts! } if( ((currentFirstVirtualDisplay + currentPhysicalDisplay) > (numberOfPhysicalDisplays - 1)) && (currentFirstVirtualDisplay + currentPhysicalDisplay) < (numberOfCharacters + numberOfPhysicalDisplays - 1) ){ for(int i=0; i < displayHeight; i++){ matrixToDisplay[i] = (((banner[currentFirstVirtualDisplay + currentPhysicalDisplay - numberOfPhysicalDisplays][i]) << bitPosition) + ((banner[currentFirstVirtualDisplay + currentPhysicalDisplay - numberOfPhysicalDisplays+1][i]) >> (8- bitPosition))) ; } displayMatrix(matrixToDisplay,(numberOfPhysicalDisplays-1 - currentPhysicalDisplay)); } if( (currentFirstVirtualDisplay + currentPhysicalDisplay) == (numberOfCharacters + numberOfPhysicalDisplays-1)){ for(int i=0; i < displayHeight; i++){ matrixToDisplay[i] = banner[numberOfCharacters-1][i] << bitPosition; } displayMatrix(matrixToDisplay,(numberOfPhysicalDisplays-1 - currentPhysicalDisplay)); } } delay(delayTime);} void displayMatrix(byte *matrix, int matrixNumber){ for(int i=0; i<=7;i++){ lc884.setRow(matrixNumber,i,matrix[i]); }}

Anhang: Ansteuerung eines zweifarbigen TA6932 basierten Displays

Es gibt auch zweifarbige Displays mit Dots, die rot oder grün leuchten können. Diese werden intern über einen TA6932 Chip gesteuert. Eine gleichnamige Bibliothek gibt es hier auf GitHub oder ihr installiert sie über die Arduino Bibliotheksverwaltung.

Mit der Bibliothek ist die Ansteuerung sehr einfach. Mit displayCache(row) = value legt ihr fest, welche Dots einer Reihe (row) leuchten sollen. Die roten Dots sind als Reihen 0 bis 7 definiert. Die grünen Dots sprecht ihr als Reihen 8 bis 15 an. Das sollte durch den folgenden Sketch klarer werden.

#include <TA6932.h>#define PIN_TA6932_STB 8#define PIN_TA6932_CLK 9#define PIN_TA6932_DIN 10TA6932 tm(PIN_TA6932_STB, PIN_TA6932_CLK, PIN_TA6932_DIN);void setup() { tm.begin(); tm.displayCache[0] = 0b00000001; // red dot at 0/0 tm.updateDisplay(); delay(2000); tm.displayCache[0] = 0b00000011; // red dots at 0/0 and 1/0 tm.updateDisplay(); delay(2000); tm.displayCache[0] = 0b00011011; // red dots at 0/0,1/0,3/0,4/0 tm.updateDisplay(); delay(2000); tm.displayCache[1] = 0b00000001; // red dot at 0/1; tm.updateDisplay(); delay(2000); tm.displayCache[1] = 0b11110000; // red dots at 4/1,5/1,6/1,7/1 tm.updateDisplay(); delay(2000); tm.displayCache[3] = 0b11110000; // red dots at 4/3,5/3,6/3,7/3 tm.updateDisplay(); delay(2000); tm.displayCache[11] = 0b11110000; // green dots at 4/3,5/3,6/3,7/3 (in addition!) tm.updateDisplay(); delay(2000); tm.displayCache[3] = 0b01010101; // red dots at 6/3,4/3,2/3,0/3 tm.displayCache[11] = 0b10101010; // green dots at 7/3,5/3,3/3,1/3 tm.updateDisplay(); delay(2000); byte value = 0b10101010; for(int i=0; i<8; i++){ tm.displayCache[i] = value; value = ~value; // inverts all bits tm.displayCache[i+8] = value; } tm.updateDisplay();}void loop() {}
LED Matrix Display ansteuern • Wolles Elektronikkiste (2024)

FAQs

What is a matrix LED display? ›

"Dot Matrix" is an unique category of LED Displays and also found in LCD and OLED products. The concept of LED Dot Matrix Display is the same as LCD Dot Matrix and OLED Dot Matrix. It is able to show characters, numbers or graphics by light up different pixels(dots) of a Display.

How does a dot matrix display work? ›

Structure and operation of LED dot matrix displays

In a LED dot matrix display the LEDs are located at the column and row intersections of the matrix. LEDs in the same row are connected together as are LEDs in the same column. Figure 1 shows two common configurations for LED matrix displays.

How many LEDs are needed to form an 8x8 LED matrix display Click board? ›

8x8 R click is a 64 LED matrix display Click board™, composed of SMD LEDs organized in 8 rows by 8 columns.
...
Specifications.
TypeLED Matrix
InterfaceSPI
CompatibilitymikroBUS
Click board sizeM (42.9 x 25.4 mm)
Input Voltage5V
3 more rows

How do you control an LED matrix? ›

To control an individual LED, you set its column LOW and its row HIGH. To control multiple LEDs in a row, you set the row HIGH, then take the column high, then set the columns LOW or HIGH as appropriate; a LOW column will turn the corresponding LED ON, and a HIGH column will turn it off.

What is matrix display MSI? ›

Matrix Display is a MSI exclusive technology which supports the Multi-display Mode and the Surround View Mode. The Multi-display Mode provides multiple displays shown on multiple monitors (including the build-in display) individually.

What is 8x8 LED matrix? ›

8×8 matrix consists of 64 dots or pixels. There is a LED for each pixel and these LEDs are connected to total of 16 pins. Generally, there are two types of dot matrix – common cathode and common anode. They look almost the same in appearance.

What is dot matrix format? ›

A dot matrix is a 2-dimensional patterned array, used to represent characters, symbols and images. Most types of modern technology use dot matrices for display of information, including mobile phones, televisions, and printers. The system is also used in textiles with sewing, knitting and weaving.

How do you make a large LED matrix display? ›

Large LED Dot Matrix Display Board - YouTube

What is LED matrix Arduino? ›

What is an LED Matrix? LED matrixes consist of an array of LEDs arranged in a grid. This display has a total of 64 LEDs in 8 rows and 8 columns: Most LED matrixes have red LEDs, but they are also available with green or blue LEDs. Some even let you control the color of each LED individually.

How many dots are on 8x8 dot matrix? ›

The Dot Matrix Display

A typical single color 8×8 dot matrix unit has 16 pins, 8 for each row and 8 for each column.

How use 8x8 LED matrix Arduino? ›

How to control 8x8 1088AS LED Matrix with Arduino, without drivers ...

How do you make an array of LEDs? ›

Make your own 10x10 LED Matrix - YouTube

How does RGB LED matrix work? ›

Each color of each LED is driven by one bit of a shift register and all of the shift registers are then daisy-chained together, allowing you to drive all of the LEDs by clocking in high or low bits for the red, green, and blue LEDs individually.

How do you wire a RGB LED matrix? ›

Make your own 15x10 RGB LED Matrix - Part 1 - YouTube

How do you control a dot matrix? ›

How to control 8x8 dot Matrix with MAX7219 and Arduino - YouTube

How do I use 2 monitors for gaming? ›

If you don't have a docking station and both monitors have a DisplayPort port, you can connect the two screens with a DisplayPort cable. Once everything is plugged in, and your PC or laptop is turned on, both monitors will display two separate desktops.

Can a gaming laptop run a monitor? ›

The answer is yes! You can play games on a monitor with higher resolution and refresh rate (Hz) compared to what the screen the laptop came with is capable of. If you connect an external monitor to your laptop, the monitor can run at the maximum refresh rate that it supports.

How do I setup my MSI monitor? ›

Connecting your monitor to your PC
  1. Turn off your computer, connect the HDMI/DisplayPort cable from your monitor to the computer.
  2. Assemble the AC power adapter & power cord. ( ...
  3. Connect the AC adapter to the monitor power jack. ...
  4. Plug the power cord into the electrical outlet.(Figure C)
  5. Turn on the monitor.(Figure D)

Why we use LED matrix? ›

An LED matrix is a two dimensional array of LEDs that can be used to display symbols, characters or even images. Based on the orientation of the LEDs in the matrix, there can be two types of LED matrices. They are Common Row Anode and Common Row Cathode.

What is the 8 matrix? ›

The 8×8 LED matrix module is a very useful and low-cost way to add display in your electronic circuits. It has 16 pins to achieve a different combination to ON/OFF the LEDs. It fits properly into any standard solderless breadboard.. It is a Great display for electrical and test equipment.

How do I create a dot matrix display? ›

LED Dot-Matrix Display
  1. Introduction: LED Dot-Matrix Display. This is a simple HOW-TO make your own personalised LED Dot-Matrix display. ...
  2. Step 1: Plan. The first task is to plan the project. ...
  3. Step 2: PCB. ...
  4. Step 3: Get the Parts. ...
  5. Step 4: Soldering. ...
  6. Step 5: Neaten It Up. ...
  7. Step 6: Programming. ...
  8. Step 7: The Finished Thing.

What is matrix printing? ›

Dot matrix printing, sometimes called impact matrix printing, is a computer printing process in which ink is applied to a surface using a relatively low-resolution dot matrix for layout.

What is matrix printers? ›

A dot matrix printer is an impact printer that prints using a fixed number of pins or wires. Typically the pins or wires are arranged in one or several vertical columns. The pins strike an ink-coated ribbon and force contact between the ribbon and the paper, so that each pin makes a small dot on the paper.

How do you tint a dot matrix? ›

How to Fix The Dot Matrix - BLACKOUT The Dots! - YouTube

How do LED display boards work? ›

An LED display consists of red, green and blue LEDs mounted in a fixed pattern. These three colours combine to form a pixel. By adjusting the intensity of the diodes, billions of colours can be formed. When you look at the LED screen from a certain distance, the array of coloured pixels are seen as an image.

How do you make an LED light show? ›

DIY LED Light Show Props (PEX Wreath, Mega Star, Tune To Sign ...

How do you make LED wall panels? ›

How to make lighted floating wall panels - YouTube

What is matrix screen? ›

An active matrix display is a type of flat-panel display in which the screen is refreshed more frequently than in conventional passive-matrix displays. The most common type of active-matrix display is based on a technology known as Thin Film Transistor (TFT).

What are some examples of matrix display devices? ›

Unsourced material may be challenged and removed. A dot-matrix display is a low cost electronic digital display device that displays information on machines such as clocks, watches, calculators, and many other devices requiring a simple alphanumeric (and/or graphic) display device of limited resolution.

What size is provided LED matrix? ›

An 8 x 8 LED matrix display is used in this project to display the information. LED matrices are available in different styles like single color, dual color, multi-color or RGB LED matrix. They are also available in different dimensions like 5 x 7, 8 x 8, 16 x 16, 32 x 32 etc.

How do LED arrays work? ›

The LED array arranges LEDs in rows and columns. The LEDs in the grid have their two connections, their cathodes and their anodes, connected to the other LEDs. By making these connections correctly, a microcontroller can drive any one LED on while leaving others off.

Top Articles
Latest Posts
Article information

Author: Velia Krajcik

Last Updated:

Views: 5956

Rating: 4.3 / 5 (74 voted)

Reviews: 89% of readers found this page helpful

Author information

Name: Velia Krajcik

Birthday: 1996-07-27

Address: 520 Balistreri Mount, South Armand, OR 60528

Phone: +466880739437

Job: Future Retail Associate

Hobby: Polo, Scouting, Worldbuilding, Cosplaying, Photography, Rowing, Nordic skating

Introduction: My name is Velia Krajcik, I am a handsome, clean, lucky, gleaming, magnificent, proud, glorious person who loves writing and wants to share my knowledge and understanding with you.