Search code examples
c++arduinoneopixel

How do I appropriately call constructors and pass objects around?


I have the following code, but something is wrong with it. It compiles, but nothing happens on the NeoPixel matrix. I've loaded up a strand test to verify that the hardware is working properly. Through some manual debugging, I've worked out that the line containing PixelArt art = PixelArt(matrix); triggers the issue. If I comment that out, I get a panel of orange light coming out of the light matrix as expected. Putting it back in simply results in darkness.

What about including that one line is causing issues? I'm new to C++ and this is driving me up the wall.

For some code context, I plan on including more modes, each with a series of submodes. PixelArt would show off different pixel art pictures as its sub modes. Other modes would include different animation patterns. The different modes should all share a reference to the same matrix object.

#include <Adafruit_NeoMatrix.h>
#include <gamma.h>

#define MODE_PIN 2
#define SUB_MODE_PIN 3

#define MATRIX_PIN 9
#define MATRIX_COLUMNS 16
#define MATRIX_ROWS 16
#define MATRIX_NUM_PIXELS (MATRIX_COLUMNS * MATRIX_ROWS)

class Mode {
  public:
    Mode(Adafruit_NeoMatrix &neomatrix) : matrix{&neomatrix} {}
    virtual void toggleSubMode() = 0;
    virtual void update(uint64_t timestamp) = 0;
  protected:
    Adafruit_NeoMatrix * const matrix;
};

class PixelArt : public Mode {
  public:
    PixelArt(Adafruit_NeoMatrix &neomatrix):Mode(neomatrix) {}
    void toggleSubMode();
    void update(uint64_t timestamp);
};

void PixelArt::toggleSubMode() {
  // Stubbed.
}

// Green: 0x80c000
// Brown: 0xc04000
// Tan:   0xffa040
uint32_t link[16][16] = { [REDACTED FOR BREVITY] };

void PixelArt::update(uint64_t timestamp) {
  matrix->clear();

  for (uint16_t row = 0; row < 16; row++) {
    for (uint16_t column = 0; column < 16; column++) {
      matrix->setPassThruColor(link[row][column]);
      matrix->drawPixel(column, row, 0);
      matrix->setPassThruColor();
    }
  }

  matrix->show();
}

//

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
  MATRIX_COLUMNS,
  MATRIX_ROWS,
  MATRIX_PIN,
  NEO_MATRIX_TOP | NEO_MATRIX_LEFT | NEO_MATRIX_COLUMNS | NEO_MATRIX_ZIGZAG,
  NEO_GRB | NEO_KHZ800
);

PixelArt art = PixelArt(matrix);

void setup() {
  matrix.begin();
  matrix.show();
  matrix.setBrightness(30); // Max ~80
}

uint8_t mode = 0;

void loop() {
//  art.update(millis());

  matrix.fillScreen(matrix.Color(255, 127, 0));
  matrix.show();
}

Solution

  • My suggestion would be that because the code runs on a microcontroller, it may run out of memory. Especially if the target board is an Arduino Uno or similar, with small dynamic memory. After compilation, the memory usage calculation is done for compile-time variables. The run-time variables and function calls may exceed the available memory.

    Compiled for an Arduino Uno, the compiler calculates a 1204 bytes (58%) of dynamic memory usage with PixelArt object. Without it is 168 bytes (8%).

    Try reducing the inheritance and function call levels.