Grundlagen zu einer 8x8 LED Matrix

Hallo Arduino-Community,
ein Freund und ich sind dabei auf einer 8x8 LED Matrix das berühmte Spiel "Snake" zu programmieren.
Wir benutzen 16 74HC595 Schieberegister, 64 zweifarbige LEDS(grün und rot) und einen Arduino Mega (ATmega1280).
Nun haben wir die Matrix fertig gebaut und ich wollte anfangen einzelne Leds anzusprechen, was jedoch nicht so funktioniert wie ich mir das vorstelle.
Ich hatte mir das so gedacht, dass man mit einem byte Matrix[8]; array jede einzelne Zeile der Matrix ansprechen kann und das die Bits
der einzelnen Bytes jeweils die LEDS "wiederspiegeln". Sprich das meine erste LED Reihe folgendermaßen funktionieren würde:

Matrix[1] = 85 //0b01010101

, wodurch jeweils die 2. LED immer leuchten soll, was Sie aber nicht tun.
Es werden jeweils die einzelnen Reihen der Matrix damit angesprochen und nun wollte ich wissen wie ich jeweils die einzelnen LEDS der einzelnen Reihen ansteuern kann.
Hier der Quellcode:

Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix[8];

void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  Matrix[1] = 85;
}


void loop() {

    digitalWrite(latchPin, LOW);

    shiftOut(dataPin, clockPin, MSBFIRST, Matrix[1]); //0b01010101 
    
    digitalWrite(latchPin, HIGH);
}

und hier ein bild der Matrix, wenn der Arduino diese mit dem Quellcode ansteuert:

Die LED in der 3 Reihe spinnt manchmal, hat nix mit dem Progg zutun.

Wenn Ihr noch weitere Informationen benötigt, lasst es mich wissen. Bin hier relativ neu und freue mich über Tipps und Tricks rund ums programmieren.
Wenn es irgendwelche Tutorial's gibt könnt ihr mir die auch gerne senden :).
Danke schonmal im Vorraus,
idl0r

  1. In C++ fanngen Arrays mit Index 0 an
  2. hast du wahrscheinlich bei der Verdrahtung Zeilen und Spalten vertauscht
  3. würde ein Plan der Beschaltung helfen
  4. Wenn du die Schieberegister über die seriellen Ausgänge in Reihe geschaltet hast, dann musst du die Zeilen alle hintereinander herausshiften. Wenn alles parallel geschaltet ist, hast du die Sache falsch verdrahtet. Clock und Latch schon parallel, aber Data nicht.

Wie ich das verstehe hast Du je ein LED auf einen Ausgang des 595 geschalten und alle 16 Schieberegister in Serie ( Dout auf Din).

Um ein Bild darzustellen mußt Du jedesmal alle Daten der 64 LED hinausschiften also jedesmal 16 Byte.
So wie ich das sehe stimmt es wie die LED leuchten außer Reihe 3 da scheint ein Verdrahtungsfehler zu sein. Ein 595 steuert jeweils eine Kolonne an.

Grüße Uwe

Hallo ,
hier ist der Plan wie unsere Matrix geschaltet wird: ImageShack - Best place for all of your image hosting and image sharing needs
es wurde nach diesem prinzip verdrahtet: http://www.arduino.cc/en/Tutorial/ShiftOut
also eine reihe aus 8 shiftregistern für rot nach "shiftout" (außer das unsere reihen untereinander sind und nicht nebeneinander)
und eine reihe aus 8 shiftregistern für grün nach "shiftout"
Ich lade noch die Fritzing-Datei hoch dann kannste dir vllt einen besseren Überblick verschaffen.
MfG: idl0r

Untitled_Sketch.zip (95.4 KB)

@ Uwe, könnten Sie mir vllt ein Programmierbeispiel geben um z.B. die LED ganz unten links nur zum leuchten zubringen? wäre Ihnen sehr dankbar dafür

Dann ist ja alles richtig außer daß Du das eine LED kontrollieren mußt.
Du mußt also immer 8 Byte übertrragen auch wenn Du nur 1 LED ändern willst.

Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix1[] = {85, 170,85, 170,85, 170,85, 170};
byte Matrix2[] = {170, 85, 170,85, 170,85, 170,85};



void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  }


void loop() {

    digitalWrite(latchPin, LOW);
  for (int i = 0;i<8;i++)
{
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[i]); 
}   
    digitalWrite(latchPin, HIGH);

delay (1000);

   digitalWrite(latchPin, LOW);


  for (int i = 0;i<8;i++)
{
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix2[i]); 
}   
    digitalWrite(latchPin, HIGH);
delay (1000);
}

Hey,
also erstmal ein großes Dankeschön an uwefed, funktioniert das programm.
Jetzt habe ich aber nochmal eine frage bezüglich des "refreshens" der Matrix.
Ich will jetzt von oben links "2 Punkte" nach oben rechts laufen lassen,
sprich ich könnte dem Array ja für die erste Stelle den Wert 128 geben(10000000) und nur oben links die LED würde leuchten.
Dann im nächsten durchlauf wird ja i zu 2 und ich würde der 2 Stelle des Arrays auch 128 geben(Oben links und der 2. von oben links wären an).
Dann im 3. Durchlauf würdeich der ersten Arraystelle (sprich i-2, da i=3) eine 0 zuweisen wodurch sich diese beiden Punkte immer weiter nach rechts verschieben würden,
jedoch wird die Matrix immer erst ganz am ende refresht wenn das Array bereit alle werte übergeben bekommen hat.
WIe könnte ich also die einzelnen Schritte für mich "sichtbar" machen? Ich hatte mir das so in codeform gedacht:

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix1[] = {0, 0, 0, 0, 0, 0, 0, 0};
byte Matrix2[] = {170, 85, 170,85, 170,85, 170,85};



void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  }


void loop() {
  int Zaehler = 0;
  digitalWrite(latchPin, LOW);
  for (int i = 0;i<8;i++)
{
  if (Zaehler == 1){
    Matrix1[i-2] = 0;
    Matrix1[i]   = 128;
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[i]); 
    digitalWrite(latchPin, HIGH);
    delay (1000);
  }
  else
    Matrix1[i] = 128;
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[i]); 
    digitalWrite(latchPin, HIGH);
    delay (1000);
    Zaehler++;
}

Wenn ich diesen Code ausführe wird jedoch nur nach einiger Zeit die gesamte obere Reihe an LEDS ausgegeben.
Habe ich einen Denkfehler im Code? oder wie "refresh" man eine Matrix richtig?
MfG: idl0r

Mach innerhalb der loop() Schleife eine Kontrolle mit millis() um eine Triggerung der Update des Displays zu haben und die einzelnen Schritte des Spiels zu berechnen. Da das Display nicht flackert kannst Du die Zeit beliebig wählen.
Grüße Uwe

Hey Leute,
erstmal danke an uwefed für die info mit dem refreshen, hab das mal umgesetzt und funktioniert soweit :slight_smile:
Jetzt wollte ich nochmal etwas nachfragen und zwar habe ich das gefühl dass die einzelnen bits, welche die
LEDS ja repräsentieren immer weiter "durchgepusht" werden.
Ich wollte jetzt einfach mal ein Programm schreiben welches schrittweise die LEDS von Oben links nach unten Links
anschaltet und das habe ich mir so gedacht, dass ich einfach sage ich habe ein Array of byte mit 8 stellen.
Die erste Stelle ist 128, sprich die oberste LED ist an, die restlichen Stellen des Arrays sind 0, was bewirken soll
dass nur oben links die LED leuchten soll.
Dann halbiere ich diese 128 zu 64, damit die untere LED angeschaltet wird und die obere ausgeschaltet.
Nun funktioniert das auch halbwegs, aber aus irgendeinem grund bleibt im 2 Durchlauf die LED in der oberen Reihe an
und rückt einen platz weiter, sprich die erste LED ist nichtmehr an, sondern die 2., dann im 3 durchlauf ist die LED der 1. Reihe auf der 3 LED und
die der 2. Reihe auf der 2 LED und der der 3 Reihe auf der 1 LED usw.
Dadurch ergibt sich eine Diagonale beim 8 durchlauf, was ich jedoch nicht nachvollziehen kann, da ich ja nur die erste Stelle des arrays jeweils rausshifte.
Hier mein Quellcode dazu:

 //Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix1[] = {0, 0, 0, 0, 0, 0, 0, 0}; 
byte Matrix2[] = {0, 0, 0, 0, 0, 0, 0, 0};

int Zaehler = 0;
int Rows = 8;
int RunterZaehlen = 128;

long time[8];
void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
for(int i = 0; i<8; i++){
 time[i] = millis() + i*i*i;
}
}

void LeereArray(){ 
  digitalWrite(latchPin, LOW);
  for(int i = 0; i<8; i++){ 
      Matrix1[i] = 0;
      shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[i]); 
  }
  digitalWrite(latchPin, HIGH);
  delay(1000);
}  


void Snake(){
  int RunterZaehlen = 128;
  for(int i = 0; i< 8;i++){
      digitalWrite(latchPin, LOW);
      Matrix1[1] = RunterZaehlen; 
      RunterZaehlen = RunterZaehlen / 2;
      if(millis()>time[i]){
      shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[1]);
      digitalWrite(latchPin, HIGH);
      delay(1000);
      }
      
  }
  }


void loop() {
  Snake();
  /*if(Zaehler == 1){
  LeereArray();
  }*/
}

![](http://arduino.cc//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix1[] = {0, 0, 0, 0, 0, 0, 0, 0};
byte Matrix2[] = {0, 0, 0, 0, 0, 0, 0, 0};

int Zaehler = 0;
int Rows = 8;
int RunterZaehlen = 128;

long time[8];
void setup() {
//set pins to output so you can control the shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

for(int i = 0; i<8; i++){
time = millis() + iii;
}
}
void LeereArray(){

  • digitalWrite(latchPin, LOW);*
  • for(int i = 0; i<8; i++){*
    _ Matrix1 = 0;_
    _ shiftOut(dataPin, clockPin, MSBFIRST, Matrix1*);
    }
    digitalWrite(latchPin, HIGH);
    delay(1000);
    }
    void Snake(){
    int RunterZaehlen = 128;
    for(int i = 0; i< 8;i++){
    digitalWrite(latchPin, LOW);
    Matrix1[1] = RunterZaehlen;
    RunterZaehlen = RunterZaehlen / 2;
    if(millis()>time){
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[1]);
    digitalWrite(latchPin, HIGH);
    delay(1000);
    }*_

* }*
* }*
void loop() {
* Snake();*
_ /if(Zaehler == 1){
LeereArray();
}/

}[/img]
Hier hab ich das ganze zur besseren Übersicht nochmal fotografiert:
1:

2:

3:

Danke schonmal für die Hilfe :slight_smile:
MfG: idl0r
P.S: das ganze geht immer bis unten rechts :wink: und fängt ab der Hälfte von oben links wieder neu an, deshalb
sieht man da auch immer die Hälfte der "alten" bits_

)

long time[8]; das muß eine unsigned long Variable sein!!

Du mußt die einzelnen Bits des Matrixarrays setzen und dann alle 8 Werte des Arrays IMMER gemeinsam auf einen Rutsch verschicken.

Grüße Uwe

Um die ganze Sache mit dem Shiftout zu beschleunugen kann man auch die SPI Schnittstelle nehmen die ist mindestens um Faktor 5 schneller als das "normale Shifout". Das alles in eine Funktion geschrieben und dann wird das alles auch noch übersichtlicher

volvodani:
Um die ganze Sache mit dem Shiftout zu beschleunugen kann man auch die SPI Schnittstelle nehmen die ist mindestens um Faktor 5 schneller als das "normale Shifout". Das alles in eine Funktion geschrieben und dann wird das alles auch noch übersichtlicher

Da idl0r jedes LED einzeln über den Ausgang der Schieberegister ansteuert und nicht multiplext ist die Übertragungsgeschwindigkeit kein Problem.
Grüße Uwe

uwefed:
Du mußt die einzelnen Bits des Matrixarrays setzen und dann alle 8 Werte des Arrays IMMER gemeinsam auf einen Rutsch verschicken.

Grüße Uwe

Verstehe ich das jetzt richtig, dass ich ein bit array mit 64 stellen machen soll, sprich für jede LED ein bit, oder soll ich weiterhin mit dem 8 byte array arbeiten? Weil dann verstehe ich nicht ganz was du meinst mit "einzelne bits setzen",weil das tue ich doch indem ich bytes reinschiebe oder?
Und wie kann ich denn ein gesamtes Array auf einen "Rutsch" verschicken/ausgeben? Das geht doch nur über eine Schleife, was dann wieder nicht auf einen rutsch wäre, sondern durchgang für durchgang oder?
MfG: idl0r

void Snake(){
  int RunterZaehlen = 128;
  for(int i = 0; i< 8;i++){
      digitalWrite(latchPin, LOW);
      Matrix1[1] = RunterZaehlen; 
      RunterZaehlen = RunterZaehlen / 2;
      if(millis()>time[i]){
      shiftOut(dataPin, clockPin, MSBFIRST, Matrix1[1]);
      digitalWrite(latchPin, HIGH);
      delay(1000);
      }
      
  }

Hier änderst Du ein Bit und überträgst 1 Byte nicht die ganzen 8 Byte der Matrix.
Die Schieberegister stellen immer die letzten 8 übertraggenen Byte dar!!!!
Grüße Uwe

Hallo uwefed,
ich verstehe jetzt aber nicht ganz wie Sie das meinen mit dem Übertragen des ganzen Arrays. Ich kann doch immernur pro durchlauf einen Byte übertragen oder gibt es hier einen Befehl/"trick", welcher das gesamte
Array überträgt?
Wäre Ihnen für ein Codebeispiel sehr dankbar, da dies meist verständlicher und anschaulicher ist.
Herzlichen dank schonmal für die Hilfe,
idl0r

Jeder Aufruf von Shiftout schiebt 8 bit raus. Deine Matrix deckt eine Menge von 64 bit ab. Das heißt um die 64bit-Matrix komplett ansteuern zu können, müssen zwischen 2 Latch-Pulsen 8 Shiftouts durchgeführt werden.

hey leute,
hab bis jetzt hier rumprobiert und hab es schon fast geschafft, aber irgendetwas stimmt noch nicht ganz.
Die LEDS sollen ja, jetzt als Übung, einfach mal von Oben links nach unten links ausgegeben werden, das dachte ich mir folgendermaßen:

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

byte Matrix1[] = {0, 0, 0, 0, 0, 0, 0, 0};

int Zaehler = 0;

int RunterZaehlen;

unsigned long time[8];

void setup() {
//set pins to output so you can control the shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

for(int i = 0; i<8; i++){
time = millis() + iii;
}
LeereArray();
}
void LeereArray(){

  • digitalWrite(latchPin, LOW);*
  • for(int i = 0; i<8; i++){*
    _ Matrix1 = 0;_
    _ shiftOut(dataPin, clockPin, MSBFIRST, Matrix1*);
    }
    digitalWrite(latchPin, HIGH);
    delay(1000);
    }
    void Snake(){
    for(int i = 0; i< 8;i++){
    digitalWrite(latchPin, LOW);
    Matrix1[1] = RunterZaehlen;
    RunterZaehlen = RunterZaehlen / 2;
    if(millis()>time){
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1);
    digitalWrite(latchPin, HIGH);
    delay(1000);
    }
    }
    }
    void FuenfVier(){
    for(int i = 0; i<8; i++){
    digitalWrite(latchPin, LOW);
    Matrix1[0] = RunterZaehlen;
    RunterZaehlen = RunterZaehlen / 2;
    for(int i = 1; i<8; i++){
    Matrix1 = 0;
    }
    if(millis()>time){
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix1);
    digitalWrite(latchPin, HIGH);
    delay(1000);
    }
    }
    }
    void loop() {
    RunterZaehlen = 128;
    FuenfVier();
    }
    [/quote]*

    Müsste die LED nicht hier von oben links nach unten links durchgeshiftet werden? ich verändere doch
    immer den Wert um die Hälfte, sprich es wird immer die nächst untere LED angeschaltet und die obere ausgeschaltet.
    Desweiteren habe ich ja eine Schleife die den restlichen Teilen der Matrix sagt(1-7) dass diese den Wert 0 erhalten sollen,
    aber die LEDS gehen von oben links nach oben rechts, zwar schrittweise, aber das ist ja nicht das Bild was ich erzielen will.
    Danke nochmal dass Ihr soviel Geduld mit mir habt :confused:
    MfG: idl0r_

idl0r:
Hallo uwefed,
ich verstehe jetzt aber nicht ganz wie Sie das meinen mit dem Übertragen des ganzen Arrays. Ich kann doch immernur pro durchlauf einen Byte übertragen oder gibt es hier einen Befehl/"trick", welcher das gesamte
Array überträgt?
Wäre Ihnen für ein Codebeispiel sehr dankbar, da dies meist verständlicher und anschaulicher ist.
Herzlichen dank schonmal für die Hilfe,
idl0r

2 Dinge.
Bitte sag du, sonst fühle ich mich unendlich alt.

Das Kodebeispiel hab ich bereits im Reply #5 gegeben:

...
digitalWrite(latchPin, LOW);
  for (int i = 0;i<8;i++)
  {
    shiftOut(dataPin, clockPin, MSBFIRST, Matrix2[i]); 
  }   
digitalWrite(latchPin, HIGH);
...

Ich kann Dir sonst nur sagen bitte lies die Antworten besser durch, die Lösungen hast Du bereits bekommen.

Grüße Uwe