LED-Matrix // DLO 7135 (5x7)

Hallo,

Ich bin Arduino Neuling und bräuchte mal Hilfe.

Also ich habe diesen 5x7 DotMatrix Baustein, dieser wird parallel angesteuert.
Den Standart Satz "Hello World" habe ich mal "zufuss" programmiert. Es wird je nach Buchstabe die einzelnen Port
auf "High" oder "Low" gesetzt so wie es in der Tabelle halt steht. zwischen den einzelnen Zeichen ist eine kurze
Pause "delay(500)" z.B. damt man zeit zum lesen hat.

Soweit nichts besonderes und soll nur ein Übungsbeispiel sein.

Aber wie zerlege ich einen festgelegten Satz z.B. "Hello World" in die einzelnen Buchstaben? Wie gebe ich diese dann aus?
Zuvor müssten doch die Zeichen festgelegt werden, z.B. "A"=1000001 (8bit). Wie mache ich das?

Ich bräuchte mal ein konkretes Programmbeispiel.

LG
Bajazzo

Wie unten festgestellt ist das unnötig kompliziert. Der Teil mit der Iteration über den String stimmt zwar, aber da der Chip ein ROM hat entspricht der Wert des Zeichens dann direkt dem Byte das man ausgeben kann

Ganz simpel. Strings sind char Arrays. Und jeder char hat einen Wert von 0-127 entsprechend der ASCII Tabelle. Und das Leerzeichen als erstes darstellbares Zeichen hat den Wert 0x20 = 32. Man muss also nur über den String iterieren und jeweils 0x20 abziehen.

Dann greift man mit diesem Index in eine Tabelle die im Flash steht.

Man fängt mit der Font Definition an

const byte PROGMEM font[]= 
{
   .....
}

Hier musst du den kompletten ASCII Zeichensatz ab dem Leerzeichen eintragen:

Man kann aber auch z.B. bei '0' anfangen. Dann muss man als Offset aber auch '0' = 0x30 = 48 nehmen. Für das erste definierte Zeichen muss du durch die Subtraktion auf den Index 0 kommen.
Und dann kannst du natürlich keine Leerzeichen und Satzzeichen darstellen! Lohnt sich also nicht wirklich.

Über den String zu iterieren geht einfach so:

char str[] = "Hello World";

int length = strlen(str);
for(int i = 0; i < length; i++)
{
      char currentChar = str[i];
      byte currentByte = pgm_read_byte_near(&font[currentChar - 0x20]);

      ... //hier dann mit dem Byte was machen
}

Die Daten des Font stehen im Flash Speicher (durch PROGMEM)! Mit pgm_read_byte near wird das entsprechende Byte aus dem Flash ins RAM kopiert. Dazu übergibt man die Adresse des entsprechenden Wertes. Diese wird dann intern in eine Adresse im Flash umgerechnet.

Bajazzo:
Aber wie zerlege ich einen festgelegten Satz z.B. "Hello World" in die einzelnen Buchstaben? Wie gebe ich diese dann aus?
Zuvor müssten doch die Zeichen festgelegt werden, z.B. "A"=1000001 (8bit). Wie mache ich das?

Die Zeichen müssen nicht festgelegt werden, laut Datenblatt Deines Bausteins hat der eine ASCII-Zeichentabelle eingebaut.

Die ASCII-Zeichentabelle bis zum dezimalen Zeichencode 127 ist Standard und steht damit fest.
So auf den ersten Blick im Datenblatt fällt mir als "Sonderzeichen" erstmal nur Zeichen 127 auf, das ist bei Deinem Baustein ein "voller Block" und weicht daher von Standard-ASCII ab. Alles andere sieht identisch aus.

Zur Dekodierung brauchst Du also nur die ASCII-Codes der Buchstaben in Deinem String.

Hier ein kurzes Demoprogramm, dass Dir einen String in einzelne Buchstaben aufdröselt, und danach die einzelnen Buchstaben in die gesetzten Bits des ASCII-Codes zerlegt und darstellt.

void setup() {
  Serial.begin(9600);
  char testString[]="Hello World!";
  char textbuf[41];
  Serial.println();
  Serial.println("Buchst.\tDezimal\t= Binaer");
  for (int i=0;i<strlen(testString);i++)
  {
    Serial.print(testString[i]);
    Serial.print('\t');
    byte b=testString[i];
    Serial.print(b);
    Serial.print('\t');
    Serial.print("= ");
    for (int j=7;j>=0;j--) Serial.print(bitRead(b,j));
    Serial.println();
  }
}

void loop() {}

Jedes der unteren 7 Bits im Code entspricht einer Datenleitung (D0...D6) Deines Bausteins.
Das achte Bit ("High Bit") spielt keine Rolle, da Dein Baustein keine Zeichen mit einem ASCII-Code über 127 darstellen kann.

Ob ein bestimmtes Bit in einer Zahl gesetzt ist, kannst Du mit der Arduino-Komfortfunktion "bitRead" feststellen.

Stimmt. Da hätte mich mir mal das Datenblatt anschauen sollen. Da kann man sich natürlich die Indirektion über das Array sparen :slight_smile:
War eigentlich klar. Habe sogar mal so eine ähnliche Anzeige mit 4 Stellen programmiert. Ist aber schon ewig her :roll_eyes:

Das mit der Zeichentabelle ist eher für Matrizen ohne Character ROM relevant.

Das mag ich übrigens persönlich nicht so gern:

for (int i=0;i<strlen(testString);i++)

Da ruft er bei jeder Iteration strlen() auf und iteriert einmal pro Zeichen über den gesamten String. Geht natürlich, ist aber unnötig.

Hallo,

Erst mal Danke für die Antworten bisher. Genau so etwas habe ich gesucht, zumindest für einen
Teil des Programms. Was bedeutet die "41" "char textbuf[41] " ?
Es ist richtig das der Baustein einen ASCII Generator drin hat.
Ich werde mich mal näher mit dem Programm von Jurs beschäftigen.

Als nächstes müsste ich die binären Werte zum Baustein senden, wie mache ich das am besten?

Vorab ein grober Ablauf:
Eingänge vom Baustein definieren "int D0=30 ... int D6=36" ---> Satz erstellen der angezeigt werden soll ---> Satz in ASCII Werte zerlegen ---> ASCII Werte in binäre Werte umwandeln und zum Baustein senden (D0-D6) dazwischen jeweils ein kurzes delay.

Ich weis das man heutzutage meist alles auf LC-Display legt, diese sind auch leichter anzusteuern.

Bajazzo:
Erst mal Danke für die Antworten bisher. Genau so etwas habe ich gesucht, zumindest für einen
Teil des Programms. Was bedeutet die "41" "char textbuf[41] " ?

Das ist eine Reservierung von RAM für einen String von 40 Zeichen Länge plus abschließendes Leerzeichen.

Kannst Du rauslöschen.

Ursprünglich wollte ich die Serial-Ausgabe des Programms wohl in einem Rutsch in einen String formatieren und ausgeben und habe stattdessen dann doch Code geschrieben, mit dem die Ausgaben auf Serial zusammengestückelt und nacheinander ausgegeben werden.

Bajazzo:
Als nächstes müsste ich die binären Werte zum Baustein senden, wie mache ich das am besten?

Hast Du das Datenblatt gelesen?
Abschnitt "Data Loading Example"?

Soweit ich das sehe, ist die Reihenfolge beim Schreiben wie folgt:

  1. CE - Chip Enable auf LOW schalten
  2. WR - Write auf LOW schalten
    3.. Helligkeitswert in BL0 und BL1 codieren (oder ständig HIGH halten für max. Helligkeit)
  3. Daten an D0 bis D6 codieren
  4. WR - Write auf HIGH schalten
  5. CE - Chip Enable auf HIGH schalten

LT - Lamp Test am besten immer auf HIGH stehen haben, sonst ist der Lampentest aktiv, egal wie die übrigen Leitungen gesetzt werden.

Ja die Reihenfolge der Übertragung hab ich mir angesehen.

Wie vebinde ich die binären werte mit den zuvor definierten Ausgängen D0-D6 ?
Oder muss ich doch ein ShiftRegister Baustein verwenden? 74164, 74299, 74594... etc.
Es muss doch machbar sein werte parallel auszugeben ohne Logikbaustein.

Das wäre das Testprogramm was Schritt für Schritt die Buchstaben ausgibt....

/*
LED-Matrix DLO 7135

Text " POWER ON "

*/
int L=13; //LED Pin 13

int D0=40;
int D1=41;
int D2=42;
int D3=43;
int D4=44;
int D5=45;
int D6=46;

int CE=30;
int WR=31;

int BL0=32;
int BL1=33;

void setup()
{

pinMode(L,OUTPUT);

pinMode(D0, OUTPUT);
pinMode(D1, OUTPUT);
pinMode(D2,OUTPUT);
pinMode(D3,OUTPUT);
pinMode(D4,OUTPUT);
pinMode(D5,OUTPUT);
pinMode(D6,OUTPUT);

pinMode(CE,OUTPUT);
pinMode(WR,OUTPUT);

pinMode(BL0,OUTPUT);
pinMode(BL1,OUTPUT);
}

// Das Hauptprogramm ist eine Endlosscheleife
void loop()
{

digitalWrite(CE,LOW); // Chip Enable
digitalWrite(WR,LOW); //WRite Enable

// "P"

digitalWrite(BL0,HIGH);
digitalWrite(BL1,HIGH); // 1/1 der Helligkeit

digitalWrite(D0, LOW);
digitalWrite(D1,LOW);
digitalWrite(D2,LOW);
digitalWrite(D3,LOW);
digitalWrite(D4,HIGH);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// "O"
digitalWrite(D0, HIGH);
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,HIGH);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// "W"
digitalWrite(D0, HIGH);
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,LOW);
digitalWrite(D4,HIGH);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// "E"
digitalWrite(D0, HIGH);
digitalWrite(D1,LOW);
digitalWrite(D2,HIGH);
digitalWrite(D3,LOW);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// "R"
digitalWrite(D0, LOW);
digitalWrite(D1,HIGH);
digitalWrite(D2,LOW);
digitalWrite(D3,LOW);
digitalWrite(D4,HIGH);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// " "
digitalWrite(D0, LOW);
digitalWrite(D1,LOW);
digitalWrite(D2,LOW);
digitalWrite(D3,LOW);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,LOW);

delay (250);

// "O"
digitalWrite(D0, HIGH);
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,HIGH);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (250);

// "N"
digitalWrite(D0, LOW);
digitalWrite(D1,HIGH);
digitalWrite(D2,HIGH);
digitalWrite(D3,HIGH);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,HIGH);

delay (500);

// " "
digitalWrite(D0, LOW);
digitalWrite(D1,LOW);
digitalWrite(D2,LOW);
digitalWrite(D3,LOW);
digitalWrite(D4,LOW);
digitalWrite(D5,LOW);
digitalWrite(D6,LOW);

delay (500);

digitalWrite(L,HIGH);
delay (1000);
digitalWrite(L,LOW);

delay (1500);
}

Wie ihr seht ist es nichts kompliziertes, bin halt noch Anfänger und BASIC-Zeiten sind schon lange vorbei....

Zwei Möglichkeiten:

1.) Du definierst die Pins in einem Array:

const byte pins[] = { 40, 41, 42, 43, 44, 45, 46 };

Dann machst du das (glaube ich):

void printByte(byte data)
{
    for(int i = 0; i < 7; i++)
    {
         digitalWrite(pins[i], bitRead(data, i));
    }
}

2.)
Du sprichst die Ports direkt an:

Auf den AVRs sind immer 8 Pins zu einem Port zusammengefasst. Dann sucht man sich Pins heraus die auf einem Port liegen. Hier ist das Mega Pin Mapping:
http://greentechhobby.com/images/Arduino/ArduinoMega.pdf

PORTA wäre z.B. ein Möglichkeit. Das sind Pins 22-29. Da siehst du dass die mit PA0 bis PA7 bezeichnet sind. PA0 bedeutet PORTA, Pin 0.

Dann kann man einfach das machen:

byte data = 123;
PORTA = data;

Fertig :slight_smile: Eine Zeile um ein ganzes Byte auf die I/Os zu schreiben

Genauso kannst du auch die Pins auf Ausgang setzen:

    for(int i = 0; i < 7; i++)
    {
         pinMode(pins[i], OUTPUT);
    }

Oder direkt:

DDRA = 0xFF;

DDR = Data Direction Register, wobei 1 = OUTPUT, 0 = INPUT

EDIT:
Man hat nur 7 Pins, also sollte man auch nur bis 6 iterieren :cold_sweat:
Das wäre mit sizeof(pins) nicht passiert (aber nur bei Byte Arrays! Das gibt die Größe in Bytes zurück)

Das ist ja mal was. Ich habe nicht gewusst das auf den Boards Pins als Port schon definiert sind.
Es steht auch nicht in dem Buch.
Dann werde ich mal versuchen so hin zu bekommen. Ein spezielles Projekt habe ich ja noch nicht....
Ich möchte halt später diese Textausgaben mit integrieren.

LG
Bajazzo

Der Arduino ist für Anfänger gedacht. Deshalb hat man das abstrahiert damit man jeden Pin mit einer Nummer ansprechen kann. In den meisten Fällen ist das Super und geht viel einfacher als mit den Port Registern zu hantieren. Der Code ist auch schon portabel von einem Prozessor-Typ zu einem anderen. Entsprechend wird in Anfänger Bücher auch kaum bis gar nicht darauf eingangen.

Aber abgesehen davon dass es Geschwindigkeit kosten (was in den meisten Fällen nicht relevant ist), ist dieser Fall hier die größte Schwäche davon. Man kann nicht so einfach mehrere Pins auf einmal setzen. Der Standard Weg ist da wie gesagt ein Array.

Dich hindert aber nichts daran je nach Bedarf auf die Arduino Abstraktion zu verzichten und die Prozessor-Registern direkt anzusprechen. Das geht genauso mit allen anderen internen Komponenten des Prozessors. Damit kann man Sachen machen die mit der Arduino Software nicht implementiert sind.

Hallo,

Wäre es möglich ein komplettes Programm hier einzustellen ? Allerdings nicht mit der PORTA Funktion sondern
mit Pin Arrays.
Im Netz habe ich nichts passendes gefunden ausser das mit den 74ér Ic´s.

Danke !

LG

Bajazzo:
Wäre es möglich ein komplettes Programm hier einzustellen ?

Ich habe Dir mal eine putChar-Funktion gemacht, so wie ich das Datenblatt verstanden habe:

Writepin auf LOW ziehen, die Helligkeitsbits an BL0/BL1 und ASCII-Bits an den 7 Datenleitungen ausgeben und den Writepin wieder auf HIGH setzen.

Ungetestet:

#define LEDPIN 13

#define CHIPENABLE 30
#define WRITEPIN 31
#define BL0 32
#define BL1 33

byte dataPins[]={40,41,42,43,44,45,46};
byte numDataPins=7;

void setup()
{                
  pinMode(LEDPIN,OUTPUT);
  digitalWrite(WRITEPIN,HIGH);
  pinMode(WRITEPIN,OUTPUT); 
 
  pinMode(BL0,OUTPUT);
  pinMode(BL1,OUTPUT); 
  
  for (int i=0;i<numDataPins;i++) pinMode(dataPins[i],OUTPUT);
  pinMode(CHIPENABLE,OUTPUT);
}

void putChar(char c, byte brightness)
{
  digitalWrite(WRITEPIN,LOW);
  digitalWrite(BL0,bitRead(brightness,0));
  digitalWrite(BL1,bitRead(brightness,1));
 
  for (int i=0;i<numDataPins;i++) 
    digitalWrite(dataPins[i],bitRead(c,i));
  digitalWrite(WRITEPIN,HIGH); 
}



void loop()                     
{
  char text[]="Hello World! ";
  byte i,j;
  
  for (i=0b01; i<=0b11; i++) // 2 brightness bits BL0/BL1
  {
    for (int j=0;j<strlen(text);j++)
    {
      putChar(text[j], i);
      delay(250);
    }
  }
}

Die Schleife steuert den Text in allen drei Helligkeitsstufen einmal durch.

Wenn im Sketch nebenbei noch andere Dinge "gleichzeitig" laufen sollen, müßtest Du von delay() auf eine verzögerungsfreie millis()-Logik umstellen.

Hallo,

Danke fürs Einstellen, so kann ich wenigstens verfolgen und sehen welche Funktionen die einzelnen Programmschritte
haben.....

Das Programm läuft. ich habe es allerdings ein wenig abgeändert.
Nun werden die einzelnen Buchstaben in der Helligkeit herabgesetzt "Fading" so zusagen.

// Beispiel Programm für den LED-Matrix Baustein DLO7135 mit Helligkeits "Fading" 


#define LEDPIN 13      // LED 13 auf dem Board

#define CHIPENABLE 9  //  nCE Pin3
#define WRITEPIN 10   //  nWR Pin4
#define BL0 11        //  nBrightness Pin 6
#define BL1 12        //  nBrightness Pin 5

byte dataPins[]={2,3,4,5,6,7,8};  // Data Pins 8-14 
byte numDataPins=7;

void setup()
{                
  pinMode(LEDPIN,OUTPUT);
  pinMode(WRITEPIN,OUTPUT);
  digitalWrite(WRITEPIN,HIGH);
   
 
  pinMode(BL0,OUTPUT);
  pinMode(BL1,OUTPUT); 
  
  for (int i=0;i<numDataPins;i++) pinMode(dataPins[i],OUTPUT); // Data Pins als OUTPUT festlegen
  pinMode(CHIPENABLE,OUTPUT);
}

void putChar(char c, byte)
{
  digitalWrite(WRITEPIN,LOW);
    
  digitalWrite(BL0,HIGH);  // Volle Helligkeit der Matrix
  digitalWrite(BL1,HIGH);
 
  for (int i=0;i<numDataPins;i++) 
    digitalWrite(dataPins[i],bitRead(c,i));
  digitalWrite(WRITEPIN,HIGH); 
}



void loop()                     
{
  char text[]=" LED 13 wird fuer 2 Sek eingeschaltet ";  // Text der angezeigt werden soll
  byte i,j;
  
  {
    for (int j=0;j<strlen(text);j++)
    {
      putChar(text[j], i);
      delay(200);
      
      //  Text wird in der Helligkeit herabgestuft Fading Effekt
      
      digitalWrite(BL0,LOW);  // Helligkeit wird auf 1/2 eingestellt
      digitalWrite(BL1,HIGH);
      delay (50);
      
      digitalWrite(BL0,HIGH);  // Helligkeit wird auf 1/7 eingestellt
      digitalWrite(BL1,LOW);
      delay (50);
    }
    
  digitalWrite(LEDPIN,HIGH);  //LED 13 einschalten
  delay (2000);
  digitalWrite(LEDPIN,LOW);   //LED 13 ausschalten 
  }
}