Gibt es eine Begrenzung bei mehrdimensionalen arrays?

Hallo und guten Abend,
gibt es eine Begrenzung bei mehrdimensionalen arrays?

byte LED_array [14][64]= {{1,1,1 . . . Funktioniert

byte LED_array [15][64]= {{1,1,1 . . . Funktioniert nicht

Der Gesamtaufbau des arrays macht was er soll, aber eben nur bis 14 Felder.

Speicherauslastung bei 14 Felder=
Globale Variablen verwenden 1.172 Bytes (57%) des dynamischen Speichers, 876 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.

Speicherauslastung bei 15 Felder=
Globale Variablen verwenden 1.236 Bytes (60%) des dynamischen Speichers, 812 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.

Das kann's doch auch nicht sein.

Ich steuer damit 8x8 Displays mit Zeichen, keine Buchstaben. Deshalb die Ansteuerung der einzelnen LED's mit 1 + 0. Und bis zu 14 Felder funktioniert auch alles.

Vorab vielen Dank.
Thomas

Thomas_W59:
gibt es eine Begrenzung bei mehrdimensionalen arrays?

Ja, den Speicher.

byte LED_array [0][64];
void setup() {
  LED_array [1][1] = 99;
}
void loop() {}
Der Sketch verwendet 456 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
Globale Variablen verwenden 9 Bytes (0%) des dynamischen Speichers, 2.039 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
byte LED_array [1][64];
void setup() {
  LED_array [1][1] = 99;
}
void loop() {}
Der Sketch verwendet 456 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
Globale Variablen verwenden 73 Bytes (3%) des dynamischen Speichers, 1.975 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
byte LED_array [15][64];
void setup() {
  LED_array [1][1] = 99;
}
void loop() {}
Der Sketch verwendet 456 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
Globale Variablen verwenden 969 Bytes (47%) des dynamischen Speichers, 1.079 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
byte LED_array [22][64];
void setup() {
  LED_array [1][1] = 99;
}
void loop() {}
Der Sketch verwendet 456 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
Globale Variablen verwenden 1.417 Bytes (69%) des dynamischen Speichers, 631 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
byte LED_array [31][64];
void setup() {
  LED_array [1][1] = 99;
}
void loop() {}
Der Sketch verwendet 456 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
Globale Variablen verwenden 1.993 Bytes (97%) des dynamischen Speichers, 55 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
Wenig Speicher verfügbar, es können Stabilitätsprobleme auftreten.

Wie in dem anderen Thread gesagt, 64 Bits passen bequem in nur 8 Bytes oder 2 unsigned long

Die Bit- und Byte-Nummer kann man einfach mit Divisionen ausrechnen.

Mit Bytes:

25 / 8 = 3
25 % 8 = 1 //Modulo = Rest einer Division

d.h. Bit 25 ist das 1. Bit in Byte Nr. 3 (von 0 an gezählt!). Weil 8 + 8 + 8 + 1 = 25

Oder mit unsigned long:

47 / 32 = 1
47 % 32 = 15

d.h. Bit 47 ist das 15. Bit in unsigned long Nr. 1

Die Speicherauslastung kann bei Verwendung von String Objekten dramatisch ansteigen. Verwendest Du sowas in Deinem Code?

Ob 812 Byte für Stack und Heap reichen, kann der Compiler leider nicht sagen.

“Undefiniertes Verhalten” ist jedenfalls immer auf RAM-Probleme zurückzuführen, wenn es mit x Elementen klappt, mit x+1 aber nicht.

int freeRam () 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

kannst du ja mal “zum Spass” einbauen und auswerten.

Hallo und guten Abend,
vielen Dank für die Antworten!

@Serenifly
Na, dann werde ich mich wohl mal mit den unsigned long beschäftigen müssen. Und das direkt bei meinem ersten Arduino-Projekt. Aber man muss sich ja Ziele setzen :wink: Das letzte mal das ich mich mit Speicherauslastung beim hobbymässigen Programieren beschäftigt habe war unter DOS bei Turbo Pascal. Na dann mal los.

Falls mir jemand eine Hilfe geben möchte - nehm ich gerne :wink:

Auf 8x8 Led-Modulen sollen jeweils zufallgesteuert Zeichen (Kreuz, nur ein Rahmen, Rahmen mit Punkten drin u.s.w.) erscheinen. Jede 1 steht für eine LED ein - jede 0 für eine LED aus. Dazu habe ich 1 Variable definiert.

byte LED_array [21][64]= {1,1,1,1…,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1}, … u.s.w. bis das array voll ist. Dieses array lese ich (für den ersten array-Wert zufallsgesteuert) wieder aus und bekomme auch schön meine Anzeigen.

Das muss dann wohl ersetzt werden.

Bei den unsigned long muss ich das array erst per Makro füllen?

Definition: unsigned long LED_array [21][64];

Um die Variable zu füllen ein Doppel-Schleife —> bitWrite ( (LED_array [zähler_1 → 0-21], [Zähler_2 → 0-64]), [Zähler_2 → 0-64], Variablenwert 0 oder 1 )

Und zum auslesen eine Doppel-Schleife —> LED_array([zähler_1 → 0-21],[Zähler_2 → 0-64]) = bitRead ( [Zähler_2 → 0-64], Variablenwert 0 oder 1 )

Hab ich da das Prinzip so richtig verstanden? Wenn ich es mir so ansehe – ehr wohl nicht. Ist mir nicht wirklich klar das ganze. Ist das “unsigned long” vielleicht schon von der Definition her ein eindimensionales array?

Aber vielleicht kann mir einer der Cracks hier helfen, Bitte.

Vorab vielen Dank.
Thomas

Definition: unsigned long LED_array [21][64];

Hä? :confused: Das ist ja noch schlimmer. Ein unsigned long hat schon 32 Bit!!! Das heißt du braucht nur 2 davon! Die Idee ist dass du nicht ein ganzes Byte verschwendest nur um ein Bit zu codieren. Sondern jedes Bit ausnutzt. Das würde wie gesagt auch mit einem Array aus Bytes gehen. Du musst nur mal alle Bits nutzten!

unsigned long LED_array [2][2] = { { 0xAAAAAAAA, 0xAAAAAAAA }, { 0, 0 } };

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

  print_line(LED_array[0]);

  write_bit64(LED_array[1], 0, 1);
  write_bit64(LED_array[1], 5, 1);
  write_bit64(LED_array[1], 10, 1);
  write_bit64(LED_array[1], 45, 1);
  write_bit64(LED_array[1], 63, 1);
  print_line(LED_array[1]);
}

void loop() 
{
}

void write_bit64(unsigned long* line, byte bit_nr, byte value)
{
  bitWrite(line[bit_nr / 32], bit_nr % 32, value);
}

byte read_bit64(unsigned long* line, byte bit_nr)
{
  return bitRead(line[bit_nr / 32], bit_nr % 32);
}

void print_line(unsigned long* line)
{
  for (int i = 63; i >= 0; i--)
    Serial.print(read_bit64(line, i));

  Serial.println();
}

Die erste Zeile ist mit Konstanten vorbesetzt. Die zweite Zeile wird im Code verändert

Es gibt auch noch bitSet() und bitClear() direkt zum setzen und löschen von Bits

EDIT:
Die Reihenfolge der Bits in der print Funktion war vertauscht. Man sollte vielleicht eher die höherwertigen Bits zuerst drucken:

for (int i = 63; i >= 0; i--)

Übrigens sind auch Binär-Literale möglich. z.B.:

unsigned long LED_array [2][2] = { { 0xFFFFFFFF, 0b01010101010101010101010101010101 }, { 0, 0 } };

Das wird zu:

0101010101010101010101010101010111111111111111111111111111111111
1000000000000000001000000000000000000000000000000000010000100001

Da sieht man dass was im Array auf Index 0 steht eine niedrigere Wertigkeit hat und somit rechts gedruckt wird. So ist es mathematisch richtig, wenn auch vielleicht auf den ersten Blick etwas verwirrend. Man kann es aber auch anders drucken. Ist nur eine Darstellungssache

Uih uih uih - starker Tobac - aber ich werde mich in den nächsten Tagen mal dran versuchen das zu verstehen. Wie gesagt - Hobbyprogrammierer.

Aber vielen Dank für Deine Bemühungen.
Thomas

Der Zustand einer 8x8 LED Matrix wird am einfachsten durch 8 byte beschrieben, denke ich.
Das kannst du dann auch so aufschreiben, oder in Testausgaben an Serial so ausgeben, wie es auf der Matrix aussieht.
8 Byte brauchen genausoviel RAM wie 2*32 bit long.

byte X[8] = {
  B10000001,
  B01000010,
  B00100100,
  B00011000,
  B00011000,
  B00100100,
  B01000010,
  B10000001 };
  
void setup() {
  Serial.begin(9600);
  for (byte i=0; i < sizeof(X); i++)
     Serial.println(X[i], HEX);
}

void loop() {}

Auf jeden Fall nur 1 Bit je Led, wenns nur einfarbig an/aus ist, da hat Serenifly schon recht.
Aber ob in 2 long oder 8 byte, da ist es eher die Frage, was dir leichter zu verstehen fällt.

Wie viele solcher 8x8 LEDMatrix Elemente hast du ?

Ja, stimmt. Bei den 8x8 Matrizen gibt man ja normal sowieso den Zeichensatz vor. Also ein Array aus Byte Arrays zu je 8 Bytes. Und man kann den Zeichensatz ins Flash schreiben. Dann belegt er gar kein RAM. Das gibt es auch fertig.

Wobei ich glaube dass er hier versucht einen Bildspeicher für alle LEDs aufzubauen

Ergänzend habe ich gerade noch ein kleines Bild dazu gezeichnet, mittels dem man sich das alles vielleicht noch besser verinnerlichen kann. Ein Bild sag oft mehr als 1000 Romane.

8x8.png

Was mich noch interessiert ist die “gesamte” Aufgabenstellung: Wieviel Displays sollen angesteuert werden? Nur eins? Eine ganze Reihe? Sollen die Inhalte wechseln? Vielleicht sind hier ja noch viel mehr Fallen verborgen als man zunächst denkt und man müsste das ganze Konzept neu durchdenken.

(Ich erwähne das nur, weil ich mich vor einiger Zeit in meiner Arduino-Euphorie auf ein Lösungsprogramm für [*hust] Sudoku-Rätsel gestürzt habe… Anfangs dachte ich mit den 9x9 = 81 Feldern (Bytes) komme ich gut zurecht. Dann aber stellte sich heraus, dass die dazu notwendige “Abstreichliste” für überflüssige Ziffern noch erheblich größer war. Also 9x9 in 10 Ebenen = 810 Bytes RAM inkl. der Eingabe. Hier machte der UNO im Ram schnell schlapp und ich musste etwas neues erfinden… Was auf dem PC oft im Handumdrehen erledigt ist, macht einen auf den kleinen µC doch recht schnell das Leben schwer.)

Hallo und guten Abend,
nach einigen Tagen Abwesenheit möchte ich mich erstmal für die Hilfen bedanken.

Ich habe etwas Zeit in mein Wissen investiert (Bit / Byte) und mir nach diversen Versuchen die aktuellen Eclipse IDE (jetzt Sloeber) installiert. Für einen Anfänger ist die Übersichtlichkeit sehr hilfreich.

@RudiDL5
Ich möchte für meine kleine Freundin (3 Jahre) ein elektronische Memory bauen. Dazu plane ich 9 8x8 LED Feldern (MAX7219 Dot LED Matrix Modul) wie auf dem Bild dargestellt aufzubauen.!(http://G:\Daten_Arduino\Projekte_TW\Bilder Melina\LED-Pannels.jpg)
Im Feld “X” soll ein Zeichen erscheinen, z.B. eine schräge Linie. Dann geht Feld “X” aus und die Felder 1 bis 8 sollen mit diversen Zeichen zufällig gefüllt werden, eins davon die schräge Line welche auch im Feld “X” dargestellt war. Mit den neben den LED-Feldern plazierten Tastern soll jetzt das hoffentlich in Erinnerung gebliebene Zeichen markeirt werden. Wenn’s richtig war soll dann noch ein Smartie aus einer Vorratsbox gespendet werden - etwas Anreiz muss ja sein.

Ich habe mir im Excel was geschrieben um die Hex-zahlen für die Zeichen zu bekommen. Dazu muss ich nur links die Farben in den Feldern ändern - der Rest passiert von alleine.
!(http://G:\Daten_Arduino\Projekte_TW\Bilder Melina\Memory_1.JPG)

Ich habe also etliche (21) Muster. Die Variable “byte X[8]” kann ich vorbelegen, wobei ich das mit einem 2-dimensionale array machen möchte. Dann kann ich direkt zufallsbedingt die 5te Graphik ansprechen.

Bisher habe ich die LED-Felder so angesprochen:

int zaehler=-1;
for(int row=0;row<8;row++) {
for(int col=0;col<8;col++) {
zaehler=zaehler+1;
{
if (Anzeigefeld_0[zaehler]>0)
{
lc.setLed(0,row,col,true);
}
else
{
lc.setLed(0,row,col,false);
}
}
}
}

“Anzeigefeld_0” war bisher so definiert: int Anzeigefeld_0={1,1,0,0,0,1… und ich bin einfach die Einsen und Nullen abgegangen. Aber das hat mir dann die Speicherprobleme eingebracht.
Das ist jetzt meine nächste Aufgabe - wie mache ich die LED Ansteuerung mit der Definition “byte X[8]”. Aber Ihr seht, ich arbeite dran. Aufgeben gilt nicht.

Schönen Abend noch
Thomas

LED-Pannels.jpg

Hallo Thomas,
die Beschreibung ist nun wohl verständlich. Ich bleibe aber mal bei meinem o.g. Beispiel: Dort habe ich die Bytes für ein Display in Muster[0…7] hinterlegt. Mit bitRead(x,n) kannst du nun alle Bits je Muster auslesen und senden:

for( byte musterRow = 0; musterRow < 8; musterRow++ )
   {
     for( byte musterCol = 0; musterCol < 8; musterCol++ )
        {
          lc.setLed( 0, musterRow, musterCol, bitRead( Muster[musterRow], 7 -musterCol ) );
        }  
   }

Versuchs mal damit, vielleicht kommst du damit bei deiner Sache 'n Schritt weiter.
LG, Rudi

Hallo an die Helfer,
vielen Dank für die Topic-Hilfe.

Dank Eurer Hilfe und etwas ernsthafterem Denken/Testen hab ich jetzt hier ein stabieles System mit bisher 5 LED-Pannels (die restlichen sind auf dem Postweg) und auch schon 8 funktionierende Taster welche mir die Eingabe an das Programm mitteilen. Sehr geholfen hat mir als Anfänger (Arduino und C++) der Sloeber Editor. Die Fehler werden wesentlich besser dargestellt.

Als nächstes kommt die Spiele-Logik und dann ja auch noch die Hardware. Mangels 3D-Drucker werde ich das Spielgerät wohl aus Holz bauen.

Schönen Abend noch
Thomas