MAX7219 5x7 dot Matrix Column Anode Wiederholfrequenz

Moin,
dies ist mein erstes Posting in diesem Forum.

Folgende Ausgangssituation:

  • Arduino nano auf Steckbrett
  • 5* 5x7 dot matrix-Anzeigen kaskadiert (TA-07xx, also ColumnAnode) mit 5* MAX7219 auf selbsterstellter Platine (Schaltplan siehe Anhang)
  • LedControl Bibliothek, um die MAX7219 anzusteuern (Bibliothek anbei, aber da ist nix dran geändert worden von mir)

Dadurch, dass es ColumnAnode Matrix-Anzeigen sind (die hatte ich halt in der Grabbelkiste...), musste der Anschluß an den jeweiligen MAX7219 etwas anders als im Datenblatt gemacht werden, bzw. etwas anders als die normalen 8x8 Anzeigen.

Ziel:

  • Darstellung verschiedener (wechselnder) Texte auf dem 5* 5x7 Display. Der Text soll dabei möglichst mittig im Display verteilt sein.
  • Das ganze soll später mal eine Anzeige für einen DIY-Audio-Verstärker werden. Mittels eines Dreh-Encoders möchte ich die Quellenwahl realisieren und auch die Lautstärke einstellen, aber das sind Aufgaben für später...

Was ich NICHT brauche:

  • irgendwelche ausgefallenen Scroll-Effekte

Was habe ich bereits realisiert:

Ich konnte durch die Definition meines eigenen Fonts (siehe *.ino) Zeichen auf dem Display darstellen. Es ist etwas umständlich, aber durch die Funktion

lc.setColumn

kann ich exakt definieren, in welcher Spalte die einzelnen Buchstaben/ Zeichen beginnen...

Zunächst mal habe ich drei statische Texte definiert:

"Vinyl"
"MP3"
"-73.5dB"

Wie man am Code erkennt, wird jede Spalte, in der LEDs leuchten, mit einem SPI-Transfer an das Display gesendet. Das macht die Funktion "lc.setColumn" eigenständig.
Eigentlich ist es ja noch schlimmer: setColumn ruft für jede LED separat einen SPI-Transfer auf...

Im ersten Schritt lasse ich die Texte einfach alle 3 s wechseln. Später soll dann ein Dreh-Encoder dafür sorgen...

Problem:

Wie man am Video erkennt, werden die Texte immer von links nach rechts "aufgebaut". Der Wechsel zwischen zwei Anzeigen geht mir also zu langsam.

Woran liegt das und wie kann ich das am einfachsten beheben? So, wie ich das Datenblatt des MAX7219 verstanden habe, ist es doch auch möglich, diesen mehr als nur die 16 Bytes zu schicken. Damit werden die Daten bis zum "letzten" MAX7219 durchgeshiftet und erst dann käme das "LOAD". Das könnte doch helfen, oder? Aber wie realisiert man das am effektivsten in SW?

Ich muss zugeben, ich bin SW-Anfänger.

Lösungsansatz:

Zunächst mal möchte ich den Font statt im SRam im Programmspeicher haben. Also muss ich mich mit PROGMEM beschäftigen.
Dann würde ich irgendwie versuchen, eine komplette "Seite" (also eine ganze 5* 5x7 Anzeige) in irgendeinen Buffer zu schreiben, der dann komplett in einem Rutsch an und durch alle MAX7219 geschickt wird. Am sinnvollste wäre für die statischen Texte der Quellenwahl natürlich, wenn die komplette Anzeige schon fertig in einem Speicher steht.

Allein das WIE ist mir aktuell noch nicht klar.

Im ersten Schritt würde der Wechsel der statischen Seiten (also später dann die Quellen-Anzeige) anstehen, erst dann würde ich mich um die dynamischen Sachen, wie die Anzeige der Lautstärke kümmern...

Was sagen die Experten zu meinem Problem? Die Schwierigkeit ist nicht nur, dass es keine ColumnCathode-Displays sind, auch 5x7 DotMatrix ist nicht sooo üblich. Normal nutzen die meisten immer diese 8x8 Matrix-Anzeigen. Diese sind mir aber deutlich zu groß.

Danke

edit: code direkt im Beitrag:

#include "LedControl.h"

byte data = 6;  // data-pin
byte clk = 8;   // clk-pin
byte load = 7;  // load-pin
byte devices=5; // number of devices (MAX7219)
LedControl lc=LedControl(data,clk,load,devices);

unsigned long delaytime=3000;

void setup() {
  for(byte address=0;address<devices;address++) {
    lc.shutdown(address,false); // ICs, wakeup call
    lc.setIntensity(address,15); //ICs, brightness (0..15
    lc.clearDisplay(address); // ICs, clear display
  }
}

void clear_all_displays(){
  for(byte address=0;address<devices;address++) {
    lc.clearDisplay(address); // ICs, clear display
  }
}

void set_all_intesities() {
    for(byte address=0;address<devices;address++) {
    lc.setIntensity(address,15); //ICs, brightness (0..15
  }
}

// characters and numbers
  byte c_A[3]=      {B01111100,B01010000,B01111100};
  byte c_B[3]=      {B01111100,B01010100,B01101100};
  byte c_M[5]=      {B01111100,B01000000,B01111100,B01000000,B01111100};
  byte c_P[3]=      {B01111100,B01010000,B01110000};
  byte c_V[3]=      {B01111000,B00000100,B01111000};
  byte c_d[3]=      {B00011100,B00010100,B01111100};
  byte c_i[1]=      {B01011100};
  byte c_l[1]=      {B01111100};
  byte c_n[3]=      {B00011100,B00010000,B00011100};
  byte c_o[3]=      {B00011100,B00010100,B00011100};
  byte c_y[3]=      {B00011010,B00001010,B00011110};
  byte n_0[3]=      {B01111100,B01000100,B01111100};
  byte n_1[3]=      {B01000100,B01111100,B00000100};
  byte n_2[3]=      {B01011100,B01010100,B01110100};
  byte n_3[3]=      {B01000100,B01010100,B01111100};
  byte n_4[3]=      {B01110000,B00010000,B01111100};
  byte n_5[3]=      {B01110100,B01010100,B01011100};
  byte n_6[3]=      {B01111100,B01010100,B01011100};
  byte n_7[3]=      {B01000000,B01010000,B01111100};
  byte n_8[3]=      {B01111100,B01010100,B01111100};
  byte n_9[3]=      {B01110100,B01010100,B01111100};
  byte c_plus[3]=   {B00010000,B00111000,B00010000};
  byte c_minus[3]=  {B00010000,B00010000,B00010000};
  byte c_dot[1]=    {B00000100};

void write_Vinyl() {
  clear_all_displays();
// character "V"
  lc.setColumn(3,1,c_V[0]);
  lc.setColumn(3,2,c_V[1]);
  lc.setColumn(3,3,c_V[2]);
// character "i"
  lc.setColumn(3,5,c_i[0]);
// character "n"
  lc.setColumn(2,2,c_n[0]);
  lc.setColumn(2,3,c_n[1]);
  lc.setColumn(2,4,c_n[2]);
// character "y"
  lc.setColumn(1,1,c_y[0]);
  lc.setColumn(1,2,c_y[1]);
  lc.setColumn(1,3,c_y[2]);
// character "l"
  lc.setColumn(1,5,c_l[0]);
}

void write_MP3() {
  clear_all_displays();
// character "M"
  lc.setColumn(3,2,c_M[0]);
  lc.setColumn(3,3,c_M[1]);
  lc.setColumn(3,4,c_M[2]);
  lc.setColumn(3,5,c_M[3]);
  lc.setColumn(2,1,c_M[4]); 
// character "P"
  lc.setColumn(2,3,c_P[0]);
  lc.setColumn(2,4,c_P[1]);
  lc.setColumn(2,5,c_P[2]);
// number "3"
  lc.setColumn(1,2,n_3[0]);
  lc.setColumn(1,3,n_3[1]);
  lc.setColumn(1,4,n_3[2]);
}

void write_testVolume(){
  clear_all_displays();
// character "-"
  lc.setColumn(4,1,c_minus[0]);
  lc.setColumn(4,2,c_minus[1]);
  lc.setColumn(4,3,c_minus[2]);  
// number "7"
  lc.setColumn(4,5,n_7[0]);
  lc.setColumn(3,1,n_7[1]);
  lc.setColumn(3,2,n_7[2]);  
// number "3"
  lc.setColumn(3,4,n_3[0]);
  lc.setColumn(3,5,n_3[1]);
  lc.setColumn(2,1,n_3[2]);  
// character "."
  lc.setColumn(2,3,c_dot[0]);
// number "5"
  lc.setColumn(2,5,n_5[0]);
  lc.setColumn(1,1,n_5[1]);
  lc.setColumn(1,2,n_5[2]);
// character "d"
  lc.setColumn(1,4,c_d[0]);
  lc.setColumn(1,5,c_d[1]);
  lc.setColumn(0,1,c_d[2]);
// character "B"
  lc.setColumn(0,3,c_B[0]);
  lc.setColumn(0,4,c_B[1]);
  lc.setColumn(0,5,c_B[2]);
}

void loop() { 
  write_Vinyl();
  delay(delaytime);
  write_MP3();
  delay(delaytime);
  write_testVolume();
  delay(delaytime);
}

myMAX7219_02.ino (3.61 KB)

LedControl.cpp (5.28 KB)

verwende die SPI library. Die ist schneller als das schiftout.

Diese funktioniert aber nur mit den SPI-Pins.
Berechne erst die Daten für als MAX und schiebe aber dann die Daten für alle MAX7219 hinaus.

Grüße Uwe

Hi

Wenn ich das richtig sehe, bietet diese Lib nicht die Möglichkeit, erst den Inhalt zu generieren und dann das Gesamtpaket abzuschicken.
Du könntest als Notpflaster mit der Methode .shutdown die Anzeige dunkel schalten, den Inhalt einspielen, die Anzeige hell schalten.
Nicht sonderlich schön, aber der sichtbare Aufbau sollte dann weg sein.

MfG

Hi,

danke...

Die "Notlösung" mit .shutdown funktioniert soweit. Für die Anzeige der Quellenwahl kann ich damit leben. Mal sehen, wie ich die Lautstärkeanzeige realisiere...

Kennt denn einer eine andere Bibliothek für den MAX7219 mit der ich erst den gesamten Inhalt generieren kann und die dann in einem Rutsch die Sachen durch die ICs schiebt?

@Uwe: Du meinst, ich sollte evtl. von der vorgefertigten Lib ganz weg und alle SPI-Transfers selbst erstellen? Puh, ... klingt nach ner Menge Code.

Danke

Hi

Ich müsste Diese hier benutzen - zumindest das Beispiel 'MadFly' habe ich schon öfter 'mit eingebunden' :slight_smile:

Die kann zwar 'den ganzen unnützen Kram', man muß Ihn aber ja nicht benutzen.
Ob oder was man dann von der Lib rauswerfen kann (oder überhaupt muß ?), wird Dir überlassen bleiben, sollte Dir der Platz ausgehen :wink:

MfG

Bei meinem MP3-Player habe ich die Programmbibliothek MaxMatrix mit einem anderen Font vervendet.