Herausforderung:
ich möchte einer Klasse zwei Arrays mit Pin Definitionen übergeben können.
Eins für Reihen Pins, eins für Spalten-Pins für ein LED-Multiplexing
Es soll nicht schon vorab eine Maximal-Größe dieser Arrays in der Klasse festgelegt werden.
Was ich durch bin:
- sind flexible array member nur am Ende der Klasse zulässig
(ansonsten kommt ein flexible array member 'Led Matrix::output' not at end of 'class LedMatrix') - Macht man mehrere flexible Arrays am Ende - das darf man nicht. Bekommt keine Warnung und sucht sich einen Wolf, warum man sich die Speicherbereiche überschreibt
- Aktuell habe ich halt zwei #defines gemacht und so eine Maximal-Größe der Arrays vorgegeben
#define MATRIX_MAXCOLS 16
#define MATRIX_MAXROWS 8
aber genau das wollte ich vermeiden. Außerdem seht ihr in der .h, eigentlich gibts noch ein drittes Array für einen output-buffer, den ich nur gem. Zeilenanzahl brauche
Gibts da eine einfache Lösung wie ich das dynamisch gestalten könnte, ohne dass ich Maximal-Größen vorab in der Klasse festlege?
Mini-Muster
Beispiel für eine 3x6 Pin Matrix
kompiliert bei mir für den Uno:
sketch.ino
#include "LedMatrix.h"
const uint8_t matrixColPin[] // Only 02 - 13, A0 - A7 - otherwise adopt digitalWriteFast() or don't use it!,
{2, 3, 4, 5, 6, 7};
const uint8_t matrixRowPin[]
{A1, A2, A3};
LedMatrix display;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println(F("Matrix Strandtest"));
//helper
const byte noOfCols = sizeof(matrixColPin) / sizeof(matrixColPin[0]);
const byte noOfRows = sizeof(matrixRowPin) / sizeof(matrixRowPin[0]);
//begin display
display.begin(noOfCols, matrixColPin, noOfRows, matrixRowPin);
}
void loop() {
// put your main code here, to run repeatedly:
//delay(1000); // testweise verlangsamen
display.update();
}
LedMatrix.cpp
#include "LedMatrix.h"
void digitalWriteFast(uint8_t pin, uint8_t x)
// faster write without checks - use only on UNO, without PWM
// based on https://timodenk.com/blog/port-manipulation-and-arduino-digitalwrite-performance/
// added support for A0-A7 / Port C
{
if (pin / 14) {
PORTC ^= (-x ^ PORTC) & (1 << ((pin - 14) % 8)); // Analog-Pins
}
else if (pin / 8) { // pin >= 8 // 13..8
PORTB ^= (-x ^ PORTB) & (1 << (pin % 8));
}
else { // 7..0
PORTD ^= (-x ^ PORTD) & (1 << (pin % 8));
}
}
LedMatrix::LedMatrix()
{}
void LedMatrix::begin(const uint8_t _noOfCols, const uint8_t _colPin[], const uint8_t _noOfRows, const uint8_t _rowPin[])
{
const uint8_t noOfCols = _noOfCols;
const uint8_t noOfRows = _noOfRows;
Serial.print(F("D035 noOfCols=")); Serial.println(noOfCols);
Serial.print(F("D036 noOfRows=")); Serial.println(noOfRows);
for (byte i = 0; i < noOfCols; i++)
{
colPin[i] = _colPin[i];
Serial.print(colPin[i]); Serial.print(" ");
}
Serial.println();
for (byte i = 0; i < noOfRows; i++)
{
rowPin[i] = _rowPin[i];
Serial.print(rowPin[i]); Serial.print(" ");
}
Serial.print(F("\nD047 col pins:"));
for (byte i = 0; i < noOfCols; i++)
{
pinMode(colPin[i], OUTPUT);
digitalWrite(colPin[i], colOff);
Serial.print(colPin[i]); Serial.print(" ");
}
Serial.print(F("\nD055 row pins:"));
for (byte i = 0; i < noOfRows; i++)
{
pinMode(rowPin[i], OUTPUT);
digitalWrite(rowPin[i], rowOff);
Serial.print(rowPin[i]); Serial.print(" ");
}
Serial.println();
}
void LedMatrix::update(void)
{
updateColWise();
}
void LedMatrix::updateColWise(void)
{
static uint32_t previousTimestamp = 0;
//static byte current = 0; // aktuelle Spalte
uint32_t timestamp = micros();
if (timestamp - previousTimestamp > 3500) // muss je nach cols/rows angepasst werden damit es nicht flackert (digitalWrite 500)
{
// tut noch nix - klar ;-)
previousTimestamp = timestamp;
}
}
LedMatrix.h
#pragma once
#include <Arduino.h>
#if defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#endif
// MISSING 8bit, 16bit oder 32bit variablen
#define MATRIX_MAXCOLS 16 // böse, das soll weg
#define MATRIX_MAXROWS 8 // böse, das soll weg
void digitalWriteFast(uint8_t pin, uint8_t x);
class LedMatrix {
public:
LedMatrix();
void begin(const uint8_t noOfCols, const uint8_t _colPin[], const uint8_t noOfRows, const uint8_t _rowPin[]);
void update(void); // regelmäßiges Update des Displays (tick, run)
private:
void updateColWise(void);
const uint8_t rowOn = false; // je nach Hardware: ich brauche geschaltes GND in der Reihe --> common row cathode (somit rowOn=false)
const uint8_t rowOff = !rowOn; // invers
const uint8_t colOn = !rowOn; // zur Reihe, ich brauch 5V auf der Spalte daher true
const uint8_t colOff = !colOn; // invers
const uint8_t noOfCols = 0;
const uint8_t noOfRows = 0;
uint16_t output[MATRIX_MAXROWS]; // böse, das soll nicht fixe Größe haben
uint8_t colPin[MATRIX_MAXCOLS], rowPin[MATRIX_MAXROWS]; // böse, das soll nicht fixe Größe haben
};