Go Down

Topic: Laufschrift LED Matrix (Read 14018 times) previous topic - next topic

fl3xizzz

Hey Leute,
brauche mal wieder eure Hilfe. Ich habe eine 8x8 LED Matrix gebaut mit einem Max7219, es läuft alles, ich kann sie ansteuern Sachen darstellen und und und... Nun fragt ihr euch sicherlich wo ist dann sein Problem :D

Also
ich kann die kanne Dynamische Laufschrift programmieren. Ich kann einen Buchstaben den ich voher definiert habe reinschieben per Bittverschiebung, aber ich kriege es einfach nicht hin einen zweiten nach zu schieben. Vielleicht kann mir jemand erst mal die logik erklären wie man dieses Problem lösen kann.

Freue mich auf eure Antworten :-)

jurs


ich kriege es einfach nicht hin einen zweiten nach zu schieben. Vielleicht kann mir jemand erst mal die logik erklären wie man dieses Problem lösen kann.


Mal angenommen, Du hast einen 8x8 Font, so dass immer ein Buchstabe gleichzeitig in Deine Matrix hineinpasst.  Dann denkst Du Dir rechts daneben eine weitere 8x8 Matrix mit dem nächsten Buchstaben. Und setzt beide Buchstaben nebeneinander zunächst mal in Gedanken bzw. im RAM in eine 8x16 Matrix ein, ungefähr so mit einem "E" und einem "C", hier ist es mal mit einem Byte pro Pixel dargestellt (im RAM-Speicher reicht zur Zwischenspeicherung ein Bit pro Pixel bei einfarbig geschalteten LEDs):

Code: [Select]

.XXXXXX..XXXXXX.
.X.......X......
.X.......X......
.XXXXX...X......
.X.......X......
.X.......X......
.XXXXXX..XXXXXX.
................


Dann denkst Du Dir ein sich von links nach rechts verschiebendes Fenster mit 8x8 Größe über diese Matrix gelegt. Wenn Du mit den linken 8x8 Pixeln anfängst und das Fenster achtmal um einen Schritt nach rechts verschiebst, dann schiebt sich das "E" langsam links aus dem sich verschiebenden 8x8 Fenster heraus und das "C" rollt rein.

Nach acht Schiebeschritten wechselst Du die Buchstaben: Das "C" wandert nach links, der nächste Buchstabe rechts daneben und Du slidest das virtuelle Fenster wieder acht Schritte nach rechts.  Immer das, was in diesem virtuellen Fenster gerade drin ist, stellst Du auf der Matrix tatsächlich dar. Immer acht Schritte schieben, dann den nächsten Buchstaben.

Quasi als Phasenanimation mit acht Schritten bis zum nächsten Buchstaben.

fl3xizzz

Danke für deine ausführlich Antwort. Mein Problem fängt da an wo das E reingeschoben ist. Ich habe das E reingeschonen eine Leertaste oder 2 kriege ich auch hib aber dann wie stelle ich das mit dem C an weil ein Teil des E und C sind ja gleichzeitig dann da ich weiß nicht wie ich das kombiniere.

Ich hoffe du weißt was ich meine :D

jurs


wie stelle ich das mit dem C an weil ein Teil des E und C sind ja gleichzeitig dann da ich weiß nicht wie ich das kombiniere.


Übergang von E auf C in acht Phasen:
Code: [Select]

.XXXXXX..XXXXXX.
.X.......X......
.X.......X......
.XXXXX...X......
.X.......X......
.X.......X......
.XXXXXX..XXXXXX.
................
<---1-->
<---2-->
  <---3-->
   <---4-->
    <---5-->
     <---6-->
      <---7-->
       <---8-->


Phase 1 ist die Darstellung des "E", Phase 8 die Darstellung des "C" und 2-8 sind die Übergangsphasen dazwischen, die dargestellt werden müssen.

Dargestellt wird aus der 8x16 Übergangsmatrix jeweils ein Ausschnitt von 8x8.
Von links nach rechts acht Phasen und der Übergang von einem auf den nächsten Buchstaben ist abgeschlossen.
Und das dann für jeden nachfolgenden Buchstaben genauso.

Das muß eben nur in eine geeignete Datenstruktur gepackt werden, mit der das vom Algorithmus her bequem abgearbeitet werden kann.

fl3xizzz

wie setze ich das im Code um? kannst du mir ein kleines Beispiel machen? weil da ist der Punkt an dem ich nicht weiter komme...

ich habe ja immer 8 Zahlen für einen Buchstaben und dann muss ich ja die zwei Buchstaben mit den Werten kobinieren und das kriege ich nicht hin die zusammen zu rechnen...

jurs


ich habe ja immer 8 Zahlen für einen Buchstaben und dann muss ich ja die zwei Buchstaben mit den Werten kobinieren und das kriege ich nicht hin die zusammen zu rechnen...


Kannst Du dann mal Deinen Font (Deine Zahlen für die Zeichen) als Font-Datei posten, den Du verwendest?
Dann kann ich Dir was als Ansatz für diesen Font zusammenschreiben.

Allerdings nur zur testweisen Ausgabe auf der seriellen Schnittstelle, denn ich habe nicht so eine 8x8 Matrix.
Die Ausgabe von Serial auf LED umschreiben müßtest Du dann selbst.
Oder ich muß mir mal selbst so ein 8x8 Modul in China bestellen, die kosten glaube ich nicht so sehr viel.

Serenifly

Am besten du speicherst das Muster in einem int Array:

int pattern[8] =
{
   B0111 1110 0111 1110,
   B0100 0000 0100 0000,
   B0100 0000 0100 0000,
   B0111 1110 0100 0000,
   B0100 0000 0100 0000,
   B0100 0000 0100 0000,
   B0111 1110 0111 1110,
   B0000 0000 0000 0000
}

Ohne die Leerzeichen!! Die habe ich mal einfügt, damit man es besser lesen kann und sieht was was ist.

Das reicht für 16 Bits pro Zeile. Für mehr macht man einfach ein zwei-dimensionales Array draus und hängt in jeder Zeile noch mehr ints dran. Man kann auch long verwenden für 32 Bit pro Variable. Um das auzulesen gibt es bitRead():
http://arduino.cc/en/Reference/BitRead

Das gibt dir den Wert des jeweiligen Bits einer Variable zurück. Du kannst dann eine for-Schleife machen und einfach den Start-Index jedesmal eins höher setzen um mit einem anderen Bit anzufangen. Das sind dann wahrscheinlich mindestens 3 for-Schleifen ineinander, aber sowas solltest du schon haben.

fl3xizzz

- - - x x x x x    248
- - - x - - - -    8
- - - x - - - -    8
- - - x x x x -    120
- - - x x x x -    120
- - - x - - - -    8
- - - x - - - -    8
- - - x x x x x    248

so sieht ein E bei mir aus

Serenifly

#8
Dec 07, 2013, 12:02 am Last Edit: Dec 07, 2013, 02:40 am by Serenifly Reason: 1
Ok, dann hast du es schon in Bits gespeichert. :)
Du willst dann wahrscheinlich ein mehr-dimensionales Array aus Bytes. Das ist einfacher für die Erstellung eines vollständigen Fonts. Das vorher war eher für eine festen String der sich nie ändert.

Für sowas ist auch der Modulo-Operator gut:
http://arduino.cc/de/Reference/Modulo

z.B. 8 % 8 = 0
       9 % 8 = 1

Damit kann man Teile von zwei Buchstaben anzeigen. z.B. Bits 3-0 eines Bytes und danach Bits 7-4 eines weiteren Bytes. Dann hast du Teile von zwei Buchstaben. Im nächsten Durchlauf sind es dann Bits 2-0 und Bits 7-3, usw.

z.B. dieser Testcode:
Code: [Select]

for(int i = 0; i < 3*8 + 1; i++)     //3 Zeichen mit je 8 Bit
{
Serial.print("Buchstabe ");
               Serial.print(i / 8);
Serial.print(" - ab Index ");
               Serial.print(7 - (i % 8));

if(i % 8 > 0)
{
Serial.print(" * Buchstabe ");
                       Serial.print(i / 8 + 1);
Serial.print(" - bis Index ");
                       Serial.print(8 - (i % 8));
}
Serial.println();
}


Das liefert:
Quote

Buchstabe 0 - ab Index 7       //alle Zeichen des 1. Buchstabens: Index 7 bis 0
Buchstabe 0 - ab Index 6 * Buchstabe 1 - bis Index 7  //1. Buchstabe von Index 6 bis 0. Dann den ersten Index (7) des zweiten Buchstabens
Buchstabe 0 - ab Index 5 * Buchstabe 1 - bis Index 6  //Index 5-0 und Index 7-6
Buchstabe 0 - ab Index 4 * Buchstabe 1 - bis Index 5  //Index 4-0 und Index 7-5
Buchstabe 0 - ab Index 3 * Buchstabe 1 - bis Index 4
Buchstabe 0 - ab Index 2 * Buchstabe 1 - bis Index 3
Buchstabe 0 - ab Index 1 * Buchstabe 1 - bis Index 2
Buchstabe 0 - ab Index 0 * Buchstabe 1 - bis Index 1
Buchstabe 1 - ab Index 7
Buchstabe 1 - ab Index 6 * Buchstabe 2 - bis Index 7
Buchstabe 1 - ab Index 5 * Buchstabe 2 - bis Index 6
Buchstabe 1 - ab Index 4 * Buchstabe 2 - bis Index 5
Buchstabe 1 - ab Index 3 * Buchstabe 2 - bis Index 4
Buchstabe 1 - ab Index 2 * Buchstabe 2 - bis Index 3
Buchstabe 1 - ab Index 1 * Buchstabe 2 - bis Index 2
Buchstabe 1 - ab Index 0 * Buchstabe 2 - bis Index 1
Buchstabe 2 - ab Index 7
Buchstabe 2 - ab Index 6 * Buchstabe 3 - bis Index 7
Buchstabe 2 - ab Index 5 * Buchstabe 3 - bis Index 6
Buchstabe 2 - ab Index 4 * Buchstabe 3 - bis Index 5
Buchstabe 2 - ab Index 3 * Buchstabe 3 - bis Index 4
Buchstabe 2 - ab Index 2 * Buchstabe 3 - bis Index 3
Buchstabe 2 - ab Index 1 * Buchstabe 3 - bis Index 2
Buchstabe 2 - ab Index 0 * Buchstabe 3 - bis Index 1
Buchstabe 3 - ab Index 7


Wenn man dann einen String hat, kann man über die Nummer des Buchstabens auf den jeweiligen Character Zugreifen. Bei einem kompletten Font kommt man über den char code auf den Speicherplatz des Buchstabens. Und über den Modulus kommt man auf die Anzahl der darzustellenden Bits des Buchstabens.

jurs


- - - x x x x x    248
- - - x - - - -    8
- - - x - - - -    8
- - - x x x x -    120
- - - x x x x -    120
- - - x - - - -    8
- - - x - - - -    8
- - - x x x x x    248

so sieht ein E bei mir aus



Das ist jetzt aber nur die Codierung für ein einzelnes Zeichen.

Wenn Du eine Lauftext-Funktion haben möchtest, bei der Du mit  einem einzigen Funktionsaufruf, z.B.
Code: [Select]

  showLauftext("Hallo Welt!");

beliebige Texte über die LED-Matrix scrollen lassen kannst, benötigst Du aber einen kompletten "Font", also alle Zeichen vom Leerzeichen (ASCII-32) bis mindestens zum Kleinbuchstaben z (ASCII-122). Also gute 90 verschiedene Zeichen als einen kompletten Font, der dann aus Platzgründen im Sketch am besten in Form von PROGMEM-Konstanten abgespeichert wird.

Hast Du keinen solchen kompletten Font in passender Größe für Deine LED-Matrix?
Soll ich mal im Internet nach einem passenden Font suchen?

Oder willst Du nur nach Bedarf genau diejenigen Buchstaben einzeln codieren, die in Deinen Texten Verwendung finden und gar keinen kompletten Font zur Ausgabe beliebiger Texte ins Programm packen?

Serenifly

Einen Font Editor gibt es hier:
http://www.instructables.com/id/LED-Scolling-Dot-Matrix-Font-Graphics-Generator-/?ALLSTEPS

Da sind glaube ich schon fertige Fonts drin.

Ist eine Excel Datei, die ein Addin benötigt

jurs


Einen Font Editor gibt es hier:
http://www.instructables.com/id/LED-Scolling-Dot-Matrix-Font-Graphics-Generator-/?ALLSTEPS

Da sind glaube ich schon fertige Fonts drin.


Henning Karlson hat auf seiner Seite auch zwei kleine 8x8 Fonts, die er für seine UTFT-Library verwendet:
http://www.henningkarlsen.com/electronics/r_fonts.php

Die habe ich da jetzt mal einfach abgegriffen und in ein Testprogramm gepackt. Über das Entfernen von Kommentarstrichen kann das Programm also schon mal zwei verschiedene 8x8 Fonts darstellen.

Um RAM-Speicher zu sparen, sind die Fonts nicht im RAM abgelegt, sondern im PROGMEM-Speicher. Dadurch kann auf die Daten nicht einfach per Array-Index zugegriffen werden, sondern das Auslesen der Fontdaten aus dem PROGMEM erfolgt über die Funktion pgm_read_byte.

Da ich keine 8x8 LED Matrix habe und auch nicht weiß, wie die angesteuert wird, habe ich mal testweise eine Ausgabe der Animationsphasen auf Serial gemacht. Für die Ansteuerung echter LEDs muss noch die Funktion "void showPhase(byte phase)" angepasst werden. Wo im Testprogramm steht "Serial.print("X");" muß der Code zum Einschalten der LED stehen, wo im Testprogramm steht "Serial.print(" ");" muss der Code zum Ausschalten der LED stehen. Bei der Ausgabe auf Serial erfolgt die Ausgabe von links-oben nach rechts-unten. Falls die Steuer-Reihenfolge auf der LED-Matrix eine andere ist, müssen ggf. auch die Schleifen zur Ausgabe der einzelnen Bits angepaßt werden.

Code ist als Anhang beigefügt.

fl3xizzz

Danke schön für die guten Antworten :-)
Das mit der Font ist auch richtig gut aber soweit bin ich ja noch nicht. Modulo ist mir bekannt, ich blicke aber noch nicht so ganz dahinter wie du das mit dem zusammen führen der Buchstaben meinst :/ vielleicht kannst du es noch mal erklären.


jurs


ich blicke aber noch nicht so ganz dahinter wie du das mit dem zusammen führen der Buchstaben meinst :/ vielleicht kannst du es noch mal erklären.


Siehe meine  Reply #1 und  Reply #3.

Ein einzelner Buchstabe ist doch in Form von 8 Stück 8-Bit Zahlen ("Byte") gespeichert.
Nehmen wir mal das "A" wie es im tinyFont codiert ist:
0x38,0x6C,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, // A

In diesen acht 8-Bit-Zahlen  steht jedes gesetzte 1-Bit für eine eingeschaltete LED und jetzes nicht gesetzte 0-Bit für eine ausgeschaltete LED. Wenn Du die acht Zahlen mal in der Binärdarstellung darstellst, kann man die Buchstaben sogar schon richtig sehen, achte in der Binärdarstellung darauf, wo die "1" Bits stehen:

Code: [Select]

Buchstabe "A"
HEX   BIN
0x38= 0b00111000
0x6C= 0b01101100
0xC6= 0b11000110
0xFE= 0b11111110
0xC6= 0b11000110
0xC6= 0b11000110
0xC6= 0b11000110
0x00= 0b00000000

Erkennst Du das "A" in der Binärdarstellung?
Diese 64 Bits in der Binär-Matrix entsprechen den 64 LEDs in Deiner LED-Matrix.
Ein 1-Bit in der Binär-Matrix entspricht einer eingeschalteten LED.

Und wenn jetzt nicht 8 Bits nebeneinander in einer Zeile stehen, sondern 16 Bits, dann hast Du zwei Buchstaben nebeneinander stehen, so wie in Reply #3 mit der den beiden Buchstaben "E" und "C" als Kombination "EC" dargestellt (dort allerdings mit "X" für ein gesetztes Bit dargestellt).

Und nun legst Du über die 16x8 Darstellung der zwei Buchstaben ein 8x8 großes Fenster drüber, das Du Schritt für Schritt von links nach rechts verschiebst. Dann hast Du bei jedem Verschiebeschritt eine 8x8 große Zwischenphase im Ausschnitt, die dann dargestellt wird. So erscheint dann eine Phasenanimation, die in acht Schritten einen Buchstaben langsam nach links rausrollen läßt, während von rechts der nächste Buchstabe reinrollt.

jurs

Nachdem ich inzwischen auch so ein 8x8-LCD-Matrix Modul mit Max7219 besitze, habe ich das weiter oben skizzierte Konzept zur Darstellung einer Laufschrift einmal in ein Beispielprogramm umgesetzt.

Code: [Select]

// Laufschrift-Demo für 8x8 LED Matrix mit Max7219
// By 'jurs' for German Arduino Forum

/* Used Pins */
int Max7219_pinCLK = 10;
int Max7219_pinCS = 9;
int Max7219_pinDIN = 8;

#define NUMCHARS 37 // Kleiner Zeichensatz aus 37 Zeichen (0..9, A..Z und Leerzeichen)
const char chars[NUMCHARS+1]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
const unsigned char disp1[NUMCHARS][8]={
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x10,0x30,0x50,0x10,0x10,0x10,0x10,0x10},//1
{0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E},//2
{0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0},//3
{0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8},//4
{0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},//6
{0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},//7
{0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},//9
{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},//J
{0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C},//S
{0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x8},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0},//W
{0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41},//X
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},//Y
{0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F},//Z
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},// [Space]
};


void Write_Max7219_byte(unsigned char DATA)
{
  unsigned char i;
  digitalWrite(Max7219_pinCS,LOW);
  for(i=8;i>=1;i--)
  {  
    digitalWrite(Max7219_pinCLK,LOW);
    digitalWrite(Max7219_pinDIN,DATA&0x80);//Obtain the MSB of the data
    DATA = DATA<<1;
    digitalWrite(Max7219_pinCLK,HIGH);
  }
}


void Write_Max7219(unsigned char address,unsigned char data)
{
  digitalWrite(Max7219_pinCS,LOW);
  Write_Max7219_byte(address);
  Write_Max7219_byte(data);
  digitalWrite(Max7219_pinCS,HIGH);
}

void writeChar2Matrix(byte* databytes)
{
  int i;
  for(i=0;i<8;i++)
  {
    Write_Max7219(i+1,databytes[i]);
  } 
}

void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00);       //decode: BCD
Write_Max7219(0x0a, 0x03);       //Brightness
Write_Max7219(0x0b, 0x07);       //
Write_Max7219(0x0c, 0x01);       //
Write_Max7219(0x0f, 0x00);       //
}



void setup()
{
  pinMode(Max7219_pinCLK,OUTPUT);
  pinMode(Max7219_pinCS,OUTPUT);
  pinMode(Max7219_pinDIN,OUTPUT);
  delay(50);
  Init_MAX7219();
}



void textloop(char* text)
{
  byte i,j,k;
  byte data[8];
  byte thischar, nextchar;
  for(j=0;j<strlen(text);j++)
  {
    thischar=strchr(chars,text[j])-chars; // Index des Buchstaben im disp1 Array
    // Index des nächsten Buchstaben im disp1 Array
    if (j+1<strlen(text)) nextchar=strchr(chars,text[j+1])-chars;
    else nextchar=strchr(chars,' ')-chars;
   
    for (k=0;k<8;k++)
    {
      for (i=0;i<8;i++)
      {
        data[i]=((unsigned int)disp1[thischar][i]<<8 | disp1[nextchar][i]) >>8-k;
      }
      writeChar2Matrix(data);
      delay(50);
    }
  }
}

void loop()
{
textloop(" LED 8X8 MATRIX LAUFSCHRIFT ");
}


Für ein reales Programm müßte man sicher noch RAM-Speicher sparen und die Font-Definition in den PROGMEM-Flashspeicher verschieben und anstelle der delay-Logik eine delayfreie Animation realisieren. Ist also mehr eine Proof-of-Concept-Demo, wie es gehen könnte, der Schrift das Laufen beizubringen.

Nur zur Vervollständigung des Threads mit ein wenig Demo-Code.  ;)

Go Up