2D array with variables

For my 2 x 16 x 16 RGB LED matrix, I want to use a 2D array on an Arduino NANO.
The "zig-zag" structure of this display is much to difficult (for me!) to work with. So I defined an array with all the LED numbers as a standard X-Y matrix. When I compile and upload my sketch, nothing happens, although on the serial monitor, it shows the right values.
Where did I go wrong ???

Here is the code that does NOT work (compiles perfectly, tho...)

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(512, 13, NEO_GRB + NEO_KHZ800);

int n;
int a;
int matrix [16][32] =
{
  {  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271},
  { 31,  30,  29,  28,  27,  26,  25,  24,  23,  22,  21,  20,  19,  18,  17,  16, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272},
  { 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303},
  { 63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304},
  { 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335},
  { 95,  94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 337, 336},
  { 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367},
  {127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368},
  {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399},
  {159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400},
  {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431},
  {191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432},
  {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463},
  {223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464},
  {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495},
  {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496}
};

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

void loop()
{
  for (n = 0; n < 16; n++)
  {
    a = matrix[n][n];
    Serial.println(a);
    strip.setPixelColor(a, 200, 0, 0);
    strip.show();
    delay(200);
    strip.setPixelColor(a, 0, 0, 0);
    strip.show();
    delay(200);
  }
}

When I fill in a (valid) number, it DOES work (albeit that always the same pixel lights up)

void loop()
{
  for (n = 0; n < 16; n++)
  {
    a = matrix[15][15]; // <<<---------------------- !!!
    Serial.println(a);
    strip.setPixelColor(a, 200, 0, 0);
    strip.show();
    delay(200);
    strip.setPixelColor(a, 0, 0, 0);
    strip.show();
    delay(200);
  }
}

Any help would be extremely appreciated !
Tanx in advance !!!

sorry misread problem on first reply.. deleted it.

I'd check it's just not all happening too fast and increase the delays to 2000 to see if you can see anything.

Well your code works on my Uno.

What Arduino are you using?

I get the sequence:-

0
30
34
60
68
90
102
120
136
150
170
180
204
210
238
240
0

Do you get this printed out?

Thanks Grumpy and ESP,

I use the Arduino NANO and I DO get the correct printout in both cases. I tried longer delays, but the result stays the same. As you can see : variable "a" is set in both cases before I call the pixel function. I used this pixel library many times before in other projects, but never with the result of an array... So the main question remains :

Why does this work :

a = matrix[15][15];   //         <<<---
Serial.println(a);
strip.setPixelColor(a, 200, 0, 0);

and this does NOT work :

for (n = 0; n < 16; n++) {
a = matrix[n][n];        //         <<<---
Serial.println(a);
strip.setPixelColor(a, 200, 0, 0);
...

??? while both Serial outputs are correct ...

Nevertheless : thanks for your interest !!

PaulVdB:
For my 2 x 16 x 16 RGB LED matrix, I want to use a 2D array on an Arduino NANO.
The "zig-zag" structure of this display is much to difficult (for me!) to work with. So I defined an array with all the LED numbers as a standard X-Y matrix. When I compile and upload my sketch, nothing happens, although on the serial monitor, it shows the right values.
Where did I go wrong ???

Your matrix array is chewing up way too much memory.

PaulVdB:
When I fill in a (valid) number, it DOES work (albeit that always the same pixel lights up)

void loop()

{
  for (n = 0; n < 16; n++)
  {
    a = matrix[15][15]; // <<<---------------------- !!!
    Serial.println(a);
    strip.setPixelColor(a, 200, 0, 0);
    strip.show();
    delay(200);
    strip.setPixelColor(a, 0, 0, 0);
    strip.show();
    delay(200);
  }
}

My guess is that, in this case, the compiler sees that the only number from matrix it needs is matrix[15][15], which equals 240. So this line

    a = matrix[15][15];

gets changed to

    a = 240;

and then the entire matrix array is treated as though it doesn't exist, thus saving a lot of memory.

I have an idea of how to get rid of that huge array.

The pixel at coordinates a, b is pixel number

(a*16)+(((a%2)==0)?(b%16):(15-(b%16)))+((b<16)?0:256)

unless I made a mistake somewhere.

Let's break that down.

(a*16)       // this pixel is in the correct row
+            // next, we will need the correct pixel within that row
(
((a%2)==0)   // check if row number is even
?
(b%16)       // for even-numbered rows, we count to the right
:
(15-(b%16))  // for odd-numbered rows, we count to the left
)
+            // we still need to deal with the second half of each row
(
(b<16)       // check if we are within the first half of the row
?
0            // if it's the first half of the row, we're done
:
256          // if it's the second half of the row, we add 256
)

Your matrix array is chewing up way too much memory.

Well given it is 16 by 32 and an int it will "only" take up
16 * 32 * 2 = 1024 bytes
And given that he is using a nano, that will fit with 1K left for everything else. So while it is inefficient I can't see it being a problem.

Grumpy_Mike:
And given that he is using a nano, that will fit with 1K left for everything else. So while it is inefficient I can't see it being a problem.

Keep in mind that the "everything else" includes running 512 pixels, each of which can be individually set to its own color, and you can see it being a problem.

odometer:
Keep in mind that the "everything else" includes running 512 pixels, each of which can be individually set to its own color, and you can see it being a problem.

Doh!

Yes that is it.

It runs on a Mega flashing the LEDs.

Which leaves the OP with the original problem as to how to define an LED number from an X and Y coordinate location.

He has already said it is a zig zag layout, which is properly called a "serpentine raster".

The conversion from X - Y values to strip values are just a little more involved than a straight raster but that's what software is for.

In the case of even numbered columns the conversion is simply :-

LED number = Y + (X * number of LEDs in a column)

However for odd numbered columns the conversion is :-
LED number = (X * number of LEDs in a column) + (number of LEDs in a column -1 -Y)

To determine if the X coordinate is odd or even, simply look at the least significant bit of the X value and if it is a zero then it is an even column or if it is a one it is an odd column. So all the software has to do is to examine the X - coordinate and decide what formula to use. It is simple enough to make a function that returns the LED number given the X & Y values.

int getLEDpos(int x, int y){ // for a serpentine raster
   int pos;
   if(x & 0x1) { // is X odd
      pos = x * yMax + (yMax -1 - y) ;
   } else { // x is even
      pos = x * yMax + y;
   } 
   return pos;
}

Where yMax is the number of LEDs in a column.
If this gives you a sideways display then simply invert the X and Y and swap over the xMax and yMax numbers.
Note there are four ways a serpentine raster can be wired this assumes column wiring moving from left to right. Make the appropriate changes if yours is not like that.

Thanks all for your contributions.
The presented formula's are really great and certainly worth storing in a safe place :slight_smile:

But my final goal is to make (simple) animations, and I guess those formulas will slow down the animation alot.

But what really puzzles me is that when I give a variable a value, it works fine. BUt when I derive a variable from a for next loop, it doesn't work.
a = 10 --> works !
for (a= ...)etc. it doesn't work.

Isn't "a" the same if it is directly declared, or if it comes out a for-next loop ???

My (humble) guess is that the NANO is the culprit. I'll try later with UNO and MEGA.
Nevertheless : if some one has more info about this : please post.

Thanks in advance !

a = 10 --> works !
for (a= ...)etc. it doesn't work

Please post an example of it not working

void setup()
{
  Serial.begin(115200);
  int a;
  a = 123;
  Serial.println(a);
  for (a = 0; a < 8; a++)
  {
    Serial.println(a);
  }
}

void loop()
{
}

Works for me

123
0
1
2
3
4
5
6
7

What are you doing that is different ?

If you really want to keep the conversion table instead of using equations, then at least store the array in program memory:

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(512, 13, NEO_GRB + NEO_KHZ800);

int n;
int a;
const int matrix [16][32] PROGMEM = {
  {  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271},
  { 31,  30,  29,  28,  27,  26,  25,  24,  23,  22,  21,  20,  19,  18,  17,  16, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272},
  { 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303},
  { 63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304},
  { 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335},
  { 95,  94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 337, 336},
  { 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367},
  {127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368},
  {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399},
  {159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400},
  {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431},
  {191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432},
  {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463},
  {223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464},
  {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495},
  {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496}
};

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

void loop() {
  for (n = 0; n < 16; n++) {
    a = pgm_read_word_near(&matrix[n][n]);
    Serial.println(a);
    strip.setPixelColor(a, 200, 0, 0);
    strip.show();
    delay(200);
    strip.setPixelColor(a, 0, 0, 0);
    strip.show();
    delay(200);
  }
}

But what really puzzles me is that when I give a variable a value, it works fine. BUt when I derive a variable from a for next loop, it doesn't work.

You had your answer in reply #4

odometer:
My guess is that, in this case, the compiler sees that the only number from matrix it needs is matrix[15][15], which equals 240. So this line

    a = matrix[15][15];

gets changed to

    a = 240;

and then the entire matrix array is treated as though it doesn't exist, thus saving a lot of memory.

The use of a variable means the compiler does not know what elements of the array your code is going to use and so can't optimise it out of existence and therefore has to include it all. If you reduce the number of LEDs you specify the strip has so that the strip buffer and that matrix buffer will fit in the 2K memory of the Uno then some of it will work, but you are reducing the number of LEDs you have drastically.

But my final goal is to make (simple) animations, and I guess those formulas will slow down the animation alot.

No they will not, there is hardly anything being done there.

PaulVdB:
For my 2 x 16 x 16 RGB LED matrix, I want to use a 2D array on an Arduino NANO.
The "zig-zag" structure of this display is much to difficult (for me!) to work with.

Challenge accepted!

/*
  note that this is in row,column ordering.
  @row - a value from 0 to 15 (inclusive)
  @col - a value from 0 to 31 (inclusive)

  There's not much point making these byte, as C++ will promote them to do the arithmetic anyway.
*/

int getIndex(int row, int col) {
  // work out which block of 32 we are in

  int block = row/2;

  // move the 'right' half of the screen back onto the left half
  if(col >= 16) {
    block += 8;
    col -= 16; // after this, col wioll be a value from - to 15
  }

  // work out where we are within that block of 32

  int offset;

  if((row %2) == 0) {
    offset = col;
  }
  else {
    offset = 31 - col; 
  }
 
  return block * 32 + offset;
} 

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

  for(int row = 0; row <16; row++) {
    for(int col = 0; col < 32; col++) {
      int index = getIndex(row, col);
      if(index < 100) Serial.print(' ');
      if(index < 10) Serial.print(' ');
      Serial.print(index);
      Serial.print(' ');
    }
    Serial.println();
  }

}

void loop() {
  // put your main code here, to run repeatedly:

}

I see that other people have replied a little more compactly. I really don't think you need to worry about speed. Adding and multiplying is something that microprocessors can do pretty quickly.

ALL very interesting replies, all worth saving.
But there's ONE tip who kills 'em all : the PROGMEM tip from DAVID 2018

david_2018:
If you really want to keep the conversion table instead of using equations, then at least store the array in program memory:

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel strip = Adafruit_NeoPixel(512, 13, NEO_GRB + NEO_KHZ800);

int n;
int a;
const int matrix [16][32] PROGMEM = {
 {  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271},
 { 31,  30,  29,  28,  27,  26,  25,  24,  23,  22,  21,  20,  19,  18,  17,  16, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272},
 { 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303},
 { 63,  62,  61,  60,  59,  58,  57,  56,  55,  54,  53,  52,  51,  50,  49,  48, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304},
 { 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335},
 { 95,  94,  93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81,  80, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 337, 336},
 { 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367},
 {127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368},
 {128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399},
 {159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400},
 {160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431},
 {191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432},
 {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463},
 {223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 479, 478, 477, 476, 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, 464},
 {224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495},
 {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496}
};

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

void loop() {
 for (n = 0; n < 16; n++) {
  a = pgm_read_word_near(&matrix[n][n]);
   Serial.println(a);
   strip.setPixelColor(a, 200, 0, 0);
   strip.show();
   delay(200);
   strip.setPixelColor(a, 0, 0, 0);
   strip.show();
   delay(200);
 }
}

But again : THANKS ALL !!!
I hope that other people can get use of this threat !

I hope that other people can get use of this threat !

Threats don't mean much here.

PaulS:
Threats don't mean much here.

Partly agree, PaulS... I found many answers to my questions by browsing the threats.And never had an unanswered question...
But agree : the forum is sooo big that sometimes you can't see the forest through the trees anymore... (But yeah ... who? what? is perfect ???)
In that case only option : Start a new threat ... 8)

So please excuse me if I start a new thread (after 30 mins browsing) ... :slight_smile:

Nevertheless : {(0x3E8 * "thanks")} to everyone on this forum ... :slight_smile:

Nevertheless : {(0x3E8 * "thanks")} to everyone on this forum ... :slight_smile:

You can not multiply a string by a number! 8)

PaulS:
You can not multiply a string by a number! 8)

NO ? ? ? Lemme check the forum ...