Sekundenuhr mit Arduino - Problem

Hall zusammen,

ich habe gerade mein erstes Arduino Projekt zu realisieren. Ich möchte auf einer LED Matrix (8x8) die Zahlen 00 - 59 im Sekundentakt hochlaufen lassen. Hierfür habe ich für jede Zahl eine eigene Matrix einem Array zu gewiesen und wollte die dann nacheinander aufrufen. Ich bin mir sicher das das einfacher geht, als ich das gemacht habe. Aber irgendwie muss man ja mal anfagen. Das Problem ist jetzt, das bei Kompilieren der Fehler kommt das ich mit den Variablen den Arbeitsspeicher überschritten habe. Was kann ich anders machen?

Gruss Nick

MAX7219_clock_Test.ino (22.8 KB)

Willkommen im Forum!

Du könntest den Font für einzelne Ziffern definieren und dann die Ziffern zu einer Zahl zusammensetzen.

Hallo,

du hast für jede Zahl 0-59 ein 2 dimensionales Array angelegt. Das ist Fleißarbeit. Jedoch Wahnsinn und sprengt jeden Speicher. Sind mindestens 960 Byte nur für die Ziffern.

Man muß eigentlich nichts weiter machen, also nur die einzelnen Segmente anzulegen. Diese werden dann je nach Bedarf aufgerufen bzw. angezeigt. Bedeutet max. 14 Array + Doppelpunkt. Die Segemente kann man bestimmt noch zusammenkürzen. Eine 33 setzt du dann aus zwei 3en zusammen usw.

Wollte ich auch gerade schreiben.
Du brauchst ja nur die Zahlen 0 bis 9. Warum also alles mehrfach machen?

Und statt dem ganzen Delay-Kram mach eine Schleife die von 0 bis 59 zählt.
Und etwas besser wird das Timing auch, wenn Du das berühmt-berüchtigte-super-notwendige-Blink-without-delay-Beispiel befolgst.

Hallo,

danke für die schnellen Antworten!

Die Überlegung hatte ich auch, erst die Zahlen 0-9 anzulegen und dann die Zahlen zusammen zusetzen. Ich dachte so komme ich erstmal schneller zu Ziel, das andere kann ich noch nicht. Dann suche ich mal ;-).

Gruss Nick

Nick001:
Was kann ich anders machen?

Erst programmieren lernen, dann programmieren.

Deine Bastelei an Deinem 8x8 Zeichensatz war sicher eine ziemliche Fleißarbeit, aber Nullen und Einsen kannst Du auch als Bits codieren statt als Bytes. Durch Bitcodierung würdest Du 8 Bits in einem einzigen Byte speichern können.

Also statt:

bool array_00[8][8]= {{0,1,1,0,0,1,1,0},
                      {1,0,0,1,1,0,0,1},
                      {1,0,0,1,1,0,0,1},
                      {1,0,0,1,1,0,0,1},
                      {1,0,0,1,1,0,0,1},
                      {0,1,1,0,0,1,1,0},
                      {0,0,0,0,0,0,0,0},
                      {0,0,0,0,0,0,0,0}};

Setze:

byte array_00[8]= {
  B01100110,
  B10011001,
  B10011001,
  B10011001,
  B10011001,
  B01100110,
  B00000000,
  B00000000
};

Damit wäre der Speicherbedarf dann schon mal auf ein Achtel reduziert. Und im Programmcode würden die Bits per bitRead()-Makro aus dem Byte herausgezogen werden.

Und Du könntest alle Deine 64 Zeichen in einem einzigen 2D Array codieren und unterbringen:

byte cArray[60][8]= ...

Das würde dann auch den Zugriff auf den Zeichensatz erleichtern, weil Du nicht auf 60 einzelne Arraynamen zugreifen brauchst, sondern mit einem Index von 0 bis 59 auf das gewünschte Zeichen innerhalb des definierten Arrays.

Und wenn Du eine Laufbandanzeige baust, dann brauchst Du sogar nur 12 verschiedene Zeichen:

  • die Ziffern 0 bis 9
  • den Doppelpunkt als Trennzeichen für Zifferngruppen
  • das Leerzeichen als Trennzeichen zwischen verschiedenen Zeitangaben
    (Allerdings käme dabei die Programmierung eines scrollenden Laufbands erschwerend hinzu.)

Dein Programm ist viel zu kompliziert und verbraucht nicht nur viel zu viel RAM, sondern es enthält auch viel zu viel Code. Sowohl die Datenstrukturen als auch die Programmlogik sind deutlich suboptimal gewählt.

Nick001:
Dann suche ich mal ;-).

Ich habe hiermit begonnen.

Naja, es gibt ein direktes Projekt für diese Anwendung und riesig Zeit habe ich nicht. :slight_smile: Ein Kirchturm der auf jeder Seite 6x4 Öffnungen hat soll für eine Themenwoche = "Zeit" beleuchtet werden. Hier hat mich ein Freund gebeten ob ich mich einarbeiten kann. Ich möchte mit hellen Leds 4 Matrixen mit den 24 Punkten machen. Dafür wollte ich die 8x6 auf teilen auf zwei Seiten.

Ich habe mir jetzt schon ein paar Tutorials angesehen und ein paar Sachen gelernt. Nur so sehr in die Tiefe gehen die nicht. Der letzte Tipp mit den Bytes hat mich schon mal weitergebracht. Gibt es eine gute deutsche Online Literatur wo man entsprechende Befehle finden kann? Vielen Dank für Eure Hilfe!

So, ich habe es jetzt erstmal mit Bytes relisiert und es funktioniert. Das Ganze programmtechnisch eleganter zu lösen mache ich nach der Hardware, wenn ich noch Zeit habe.

Ich hätte nochmal ein Frage. Ursprünglich wollte ich den Max7219 für die Matrix verwenden. Hier wollte ich die Ausgänge über P-Mosfets/Transistoren verstärken und damit jeweils drei LED eines Stripes an 12V betreiben. Jetzt bin ich gerade über das Problem Multiplexen und die damit verbunde Helligkeitseinbuße auf LED Stripes mit WS2818 gestoßen. Könnte ich hiermit mein Projekt eventuell leichter lösen?

Vielen Dank für Eure Hilfe!

Wenn man wirklich RAM sparen will, packt man Fonts per PROGMEM ins Flash

Ich habe das bei meiner Wordclock in der ersten Verison mit einem MAX7221 mit der MAX7219 Lib aus dem Playground.

So als Gedanken ansatz.

Ich habe mir dann 0-5 Links Fonts gemacht und 0-9 Rechts und dann hat man insgesamt nur 14 "Arrays" die man entsprechen aufruft damit bekommt man dann die Zahlen.
Es ist aber keine Fertige 8*8 Matrix Lib.
Da es vom Prinzip so ging
-"LEDs setzten links"
-"LEDs setzten rechts"
=> gesetzten LED anzeigen

dadurch konnte man in der Selben Reihe "mehrere" LEDs setzen ohne sich das ergebnis vorher zu zerstören.
Gruß
DerDani

Habe gerade nochmal nachgesehen, bin auf MaxMatrix umgeschwenkt.

Matrix_53.png

Nick001:
Jetzt bin ich gerade über das Problem Multiplexen und die damit verbunde Helligkeitseinbuße auf LED Stripes mit WS2818 gestoßen.

Max7219 bedient gemultiplext eine 8x8 Matrix. WS2818 kenne ich nicht, meinst Du WS2812? Letztere haben mit Multiplexen nichts zu tun, die schaltet man logisch in Reihe, also DOUT an DIN, und schiebt dann seriell Bits durch, eigentlich wie beim Schieberegister.

Hallo Agmue,

ich bin nur darauf gekommen, da ich eh ja nachher mit LED Strips arbeiten möchte. Ich habe bereits einige Wortuhren gebaut (mit vorgefertigtem Skript) und dort sind wir nachher auch auf diese LED Strips mit einzeln ansteuerbaren LEDs gegangen da die Helligkeit bedeutend höher ist und der aufwand viel geringer. Ich habe heute mal mit einem Reststück von so einem Strip rumgespielt. Ich bekomme die alle einzeln ans Leuchten, nur fehlt mir jetzt die Idee, hier loszulegen. Eigentlich müßte ich doch auch nur Binärcodes "reinschieben" die dann einer Zahl entsprechen wenn die LEDs an gehen. Mir würde das ganze rumgebastel um den Max 7219 entfallen...

Gruss Nick

Mit Max7219 geht ein 4x6-Font leidlich, siehe Foto.

Nick001:
Ich bekomme die alle einzeln ans Leuchten, nur fehlt mir jetzt die Idee, hier loszulegen. Eigentlich müßte ich doch auch nur Binärcodes "reinschieben" die dann einer Zahl entsprechen wenn die LEDs an gehen. Mir würde das ganze rumgebastel um den Max 7219 entfallen...

Ideensammlung:

  • siehe jurs #5
  • matrix.print(F("Howdy")); aus Adafruit_NeoMatrix-master\examples\matrixtest\matrixtest.pde
  • FastLED\examples\XYMatrix\XYMatrix.ino (wird hier im Forum gut unterstützt)

Danke für die Tipps! Ich habe mir das durchgelesen, da fehlt mir (momentan) noch das Grundwissen. Ich würde gerne verstehen was ich mache. Habe eigentlich alles soweit, nur fehlt mir eine Funktion. Ich habe jetzt die Zahlen Null bis neun als Unterfunktionen geschrieben und lasse einen Zähler hochlaufen. Ich möchte dann entsprechend dem Zähler die Ziffern aufrufen. Hierfür habe ich die Namen der Unterfunktionen in ein Array geschrieben, aus dem ich dann mit der Zählernummer den entsprechenden Namen aus dem Array aufrufe. Nur fehlt mir der Befehl in dem ich aus dem Arrayinhalt den Programmaufruf mache...

LED8806.ino (7.95 KB)

Was hältst Du von switch/case anstelle der vielen Funktionen?

Korrekturvorschlag bei 4x6=24 Pixeln Intervall 0 .. 23 und 24 .. 47:

  for(i=0; i<24; i++) strip.setPixelColor(i, 0);
...
  for(i=24; i<48; i++) strip.setPixelColor(i, 0);

wobei Du zehn() und eins() zusammenfassen kannst, wenn Du einen Offset 0 oder 24 mitgibst. Das ist dann auch sparsam für die dritte und vierte Ziffer.

Hierfür habe ich die Namen der Unterfunktionen in ein Array geschrieben, aus dem ich dann mit der Zählernummer den entsprechenden Namen aus dem Array aufrufe

Du hast ein Array aus Strings! Das ist völlig sinnlos. Was du vielleicht meinst ist ein Array aus Funktionszeigern:

typedef void(*funcPtr)(void);      //Kurzschreibweise für Funktionszeiger auf Funktion ohne Rückgabewert und Parameter

funcPtr functions[] = { eins, zwei };   //Array aus Funktionszeigern
const int NUM_OF_FUNCS = sizeof(functions) / sizeof(functions[0]);    //Anzahl der Elemente im Array

void setup()
{
  Serial.begin(9600);

  for (int i = 0; i < NUM_OF_FUNCS; i++)    //über Funktionen iterieren
  {
    if (functions[i] != NULL)   //abfragen ob Zeiger gültig ist
      functions[i]();   //Funktion aufrufen
  }
}

void loop()
{
}

void eins()
{
  Serial.println("eins");
}

void zwei()
{
  Serial.println("zwei");
}

Fertig, funktioniert und ich verstehe auch mein Programm. Habe für mich einiges gelernt durch das kleine Projekt! Vielen Dank für die Hilfe!

@agmue

Danke das mit Switch/Case hat sehr gut geklappt. Das mit dem Korrekturvorschlag habe ich umgesetzt, komischerweise klappt es in beiden Varianten...

@Serenifly

So meinte ich das mit den Funktionszeigern. Warum funktioniert der Code nicht, wenn ich das rüberkopiere? Ich bekomme die erste Fehlermeldung in der zweiten Zeile bei funcPtr functions[] ?

Der Code funktioniert bei mir

Die Funktionen die du in das Array einträgst müssen natürlich existieren