Having a problem with adding a matrix

I would appreciate help; I can't find the problem in the code. Matrix 1 works as expected according to the XYTable1 array, and I want Matrix 2 (LED_PIN2) to work according to the XYTable2 array. I can't figure out where the problem is.

#include <FastLED.h>
#include <Adafruit_NeoPixel.h>
// #ifdef __AVR__
//   #include <avr/power.h>
// #endif
// #define NUM_LEDS  100
uint16_t XY(uint8_t x, uint8_t y, uint8_t matrixIndex);

#define LED_PIN   1
#define LED_PIN2   18
#define COLOR_ORDER       GRB         // Color order of LED string [GRB]
#define CHIPSET           WS2812B     // LED string type [WS2182B]
#define BRIGHTNESS        50          // Overall brightness [50]
#define LAST_VISIBLE_LED  102         // Last LED that's visible [102]
#define MAX_MILLIAMPS     5000        // Max current in mA to draw from supply [500]
#define SAMPLE_WINDOW     100         // How many ms to sample audio for [100]
#define DEBOUNCE_MS       20          // Number of ms to debounce the button [20]
#define LONG_PRESS        500         // Number of ms to hold the button to count as long press [500]
#define PATTERN_TIME      10          // Seconds to show each pattern on autoChange [10]
#define kMatrixWidth      16          // Matrix width [15]
#define kMatrixHeight     16          // Matrix height [11]
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)                                       // Total number of Leds
#define MAX_DIMENSION ((kMatrixWidth>kMatrixHeight) ? kMatrixWidth : kMatrixHeight)   // Largest dimension of matrix


Adafruit_NeoPixel matrix_M1 = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel matrix_M2 = Adafruit_NeoPixel(NUM_LEDS, LED_PIN2, NEO_GRB + NEO_KHZ800);

#define NUM_MATRICES 2
#define RANDOM_PATTERN_TIME (random(10, 20))  // Change the range according to your preferences

CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS];

uint8_t patternCounters[NUM_MATRICES] = {0, 0};
uint16_t patternDurations[NUM_MATRICES] = {10, 0}; // Array to store pattern durations

bool isRunning[NUM_MATRICES] = {false, false};
// uint8_t patternCounter = 0; // Added this line
// void runPride2015(uint8_t matrixIndex, uint16_t duration, const uint8_t XYTable[kMatrixHeight][kMatrixWidth]);
void runPlasma(uint8_t matrixIndex, uint16_t duration);
void runPacifica(uint8_t matrixIndex, uint16_t duration);
void checkTimer();

#include "Fire2012.h"
#include "Pacifica.h"
// #include "Pride2015.h"
// #include "Rainbow.h"
#include "Plasma.h"
#include "XYUtils.h"


const uint8_t XYTable1[kMatrixHeight][kMatrixWidth] = {
      {},
      {},
      {32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47},
      {63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48},
      {64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79},
      {95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80},
      {96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111},
      {127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112},
      {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143},
      {159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144},
      {160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175},
      {191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176},
      {192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207},
      {},
      {},
      {}

    };   

const uint8_t XYTable2[kMatrixHeight][kMatrixWidth] = {
  {},
  {},
  {},
  {63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48},
  {64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79},
  {95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80},
  {96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111},
  {127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112},
  {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143},
  {159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144},
  {160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175},
  {191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176},
  {192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207},
  {},
  {},
  {}

};   

// #define RANDOM_PATTERN_TIME (random(10, 20))  // Change the range according to your preferences
const uint8_t (*xyTables[])[kMatrixHeight][kMatrixWidth] = {&XYTable1, &XYTable2 /*, ... add more XYTables if needed */};


uint16_t XY(uint8_t x, uint8_t y, uint8_t matrixIndex) {
    if (matrixIndex == 0) {
        // XYTable1 is associated with matrixIndex 0
        if (x < kMatrixWidth && y < kMatrixHeight) {
            return XYTable1[y][x];
        }
    } else if (matrixIndex == 1) {
        // XYTable2 is associated with matrixIndex 1
        if (x < kMatrixWidth && y < kMatrixHeight) {
            return XYTable2[y][x];
        }
    }
    return 0; // or some default value
}




void setup() {
 
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.addLeds<WS2812B, LED_PIN2, GRB>(leds2, NUM_LEDS);
  matrix_M1.begin();
  matrix_M1.show(); // Initialize all pixels to 'off'
  matrix_M2.begin();
  matrix_M2.show(); // Initialize all pixels to 'off'

  FastLED.setBrightness(50);
  Serial.begin(57600);

  for (int i = 0; i < NUM_MATRICES; i++) {
    patternCounters[i] = random(3); // Initialize each matrix with a random pattern
    patternDurations[i] = i+6; // Set initial duration for each matrix

  }
}

void checkTimer() {
    EVERY_N_SECONDS(RANDOM_PATTERN_TIME) {
    nextPattern();
  }
}

void nextPattern() {
  for (int i = 0; i < NUM_MATRICES; i++) {
    isRunning[i] = false;
    patternCounters[i] = random(3);
    patternDurations[i] = random(2, 40); // Update duration for each matrix
  }
}



void runMatrix(uint8_t matrixIndex) {
    // Generate a random duration for the current matrix
    uint16_t randomDuration = random(2, 28);
    // Serial.println(matrixIndex);

    switch (patternCounters[matrixIndex]) {
        case 0:
            runPacifica(matrixIndex, randomDuration);
            break;
        case 1:
            runPlasma(matrixIndex, randomDuration);
            break;
        case 2:
            runPlasma(matrixIndex, randomDuration);
            break;
        // Add more cases if you have more patterns
    }
}



void loop() {
  for (int i = 0; i < NUM_MATRICES; i++) {
    if (!isRunning[i]) {
      // Select a random pattern for each matrix if it's not currently running
      patternCounters[i] = random(3);
      patternDurations[i] = random(1, 15); // Update duration for each matrix
      // runMatrix(i, *xyTables[i]);
      runMatrix(i);


    }
  }
  checkTimer();
}
void runPacifica(uint8_t matrixIndex, uint16_t duration) {
  isRunning[matrixIndex] = true;
  Pacifica pacifica = Pacifica(patternDurations[matrixIndex], matrixIndex);
  unsigned long startTime = millis();
  while (isRunning[matrixIndex] && (millis() - startTime) < (duration * 1000)) {
    pacifica.runPattern();
    delay(50);
  }
  isRunning[matrixIndex] = false;
}


void runPlasma(uint8_t matrixIndex, uint16_t duration) {
  isRunning[matrixIndex] = true;
  Plasma plasma = Plasma(patternDurations[matrixIndex], matrixIndex);  // Pass XYTable to the constructor
  unsigned long startTime = millis();
  while (isRunning[matrixIndex] && (millis() - startTime) < (duration * 1000)) {
    plasma.runPattern();
    delay(50);
  }
  isRunning[matrixIndex] = false;
}

Perhaps if you DESCRIBED the problem, help could be offered.

Hello shir111

I did a quick code review.

You can turn the two-dimensional array into a three-dimensional array

e.g.

const uint8_t XYTable [number] [kMatrixHeight][kMatrixWidth] 

Have a nice day and enjoy coding in C++.

As I mentioned initially, the code works for Matrix 1, but when I try to activate another matrix, the second matrix doesn't light up (only one works).

Are you using UNO or MEGA?
If UNO or MEGA this pin is Serial pin.
#define LED_PIN 1
Use as digital pin not recommended.

This can be very dim.

These might suggest trying to put data where buffers do not exist.

What is your board? Perhaps you have a memory issue.
You try to use a two matrices of 256 (16x16) leds each. If you work on Uno or Nano, these boards doesn't have enough memory for 512 NeoPixel leds.
.

Have you debugged your code by serial.Print() the index values and the the value found in that array entry?

I am using ESP32, and it's not a memory issue because I managed to run the code on two matrices with the same array. I want to create a situation where each matrix will have its own array.
I use only 5 percent of the memory

Why do you have both libraries?

Also what do you expect from these empty brackets ?

You have named a function "XY".

I refuse to analyse a code where 99% of all hits of the function-name "XY" are
different things than the function-call for this function named "XY"

Are you a bit confused? Me too.

// void runPride2015(uint8_t matrixIndex, uint16_t duration, const uint8_t XYTable[kMatrixHeight][kMatrixWidth]);

#include "XYUtils.h"

const uint8_t XYTable1[kMatrixHeight][kMatrixWidth] = {

const uint8_t XYTable2[kMatrixHeight][kMatrixWidth] = {

const uint8_t (*xyTables[])[kMatrixHeight][kMatrixWidth] = {&XYTable1, &XYTable2 /*, ... add more XYTables if needed */};

Is there a function-call to function
named
uint16_t XY(uint8_t x, uint8_t y, uint8_t matrixIndex) {

at all?

search for XY( or XY (. it seems unused anyway unless it's in the code we don't have like what's in

#include "Plasma.h"
#include "XYUtils.h"

that code is a big mess anyway with many stuff unused (like xyTables) :slight_smile:

This code is not obfuscated; it is divided into files. I posted only the problematic part.

We really need all the code to properly analyse and find the problem, otherwise we are all just doing guesswork at the best.

Good job for posting your code in the code tags.

how do you know it's the problematic part?

the code is weird for example in the sense that you use both Adafruit_NeoPixel and FastLED. why is that ?

or XYTable1 and XYTable2 are part of xyTables and used in the XY() function which are unused in the code you shared

runPacifica and runPlasma are blocking and we have not clue what plasma.runPattern(); or pacifica.runPattern(); do...

long story short we need a cristal ball to decipher what you are saying, and mine is still in the dishwasher...

2 Likes

you can believe me:

in 98% of all cases the cause of the "problem" was in a different part of the code than the user thought.

Additional: How should somebody get a clue and the overview about your code works if you only present the assumed problematic part ?

There is no problem in the presented part of the code.

as a first approach to analyse the problem
print to the serial monitor if matrix 2 is really used

uint16_t XY(uint8_t x, uint8_t y, uint8_t matrixIndex) {
    if (matrixIndex == 0) {
        // XYTable1 is associated with matrixIndex 0
        if (x < kMatrixWidth && y < kMatrixHeight) {
            return XYTable1[y][x];
        }
    } else if (matrixIndex == 1) {

       Serial.println("Hey the matrixIndex is 1 !");

        // XYTable2 is associated with matrixIndex 1
        if (x < kMatrixWidth && y < kMatrixHeight) {
            return XYTable2[y][x];
        }
    }
    return 0; // or some default value
}

Next tip:
for analysing purposes use very easy to recognise values in matrix1 and very easy to distinguish
example all values starting with 1
100
101
102
...
values in matrix2
all values starting at 2
200
201
202
...
then print the values that are used to the serial monitor

best regards Stefan

I'm seeking! Thank you.
Do you perhaps have an idea of how I can run two matrices in parallel, and each one will activate a different function? I manage to make them work one after the other, but not in parallel.

you need to first start writing the matrix animation functions as a non blocking code. each time you call the animation function, it looks if a step needs to be taken and if so takes that step and then return.

if you have blocking code such as

you are stuck for many seconds into the while loop and thus the animation on the other matrix stops


it would be better also to create a class so that the matrix state is embeded into the class and you don't need to drag along different arrays and for loops


For extra information and simple examples look at

I want each function to run for a specific duration. For example, if I have 2 matrices, both should be able to run the same function, but each of them will receive random durations, and they will run concurrently.

that's fine you can have them do and run whatever you want but if you want to see both animations at the same time and not one after the other, you need non blocking code. that's where you need to start. read the links I provided