19x19 LedMatrix mit TLC5940 und 74HC595

Hallo zusammen :slight_smile:

Ich stehe momentan wieder mal auf’n Schlauch…

Wie im Titel beschrieben, habe ich eine 19 x 19 LED Matrix gebaut.
Da habe ich momentan leider noch Schwierigkeiten:
Im Code-Beispiel erstelle ich ein 3D-Array, welches überall eine “255” rein schreibt und somit jede LED weiß sein müsste.
Leider habe ich aber nur ein eher blaues LED-Muster, wobei der die rechte Seite, sowie die Mitte ohne Licht ist.

Als Library für die TLC5940-Ansteuerung habe ich die Tlc5940Mux-Library von Alex Leone genommen.

Eine 3x3 Matrix, welche anfangs als Prototyp gebaut wurde, funktionierte problemlos, jedoch nicht mit einem 3D-Array, sondern mit der Lösung von hier.

Ich vermute, dass mein Problem an der größeren Anzahl der TLCs liegt, da ich anfangs auch nur einen getstet hatte,

#include "Tlc5940Mux.h"

#define  NUM_TLCS     6 //Anzahl der TLCs
#define  NUM_ROWS    19 //Anzahl der Zeilen
#define  NUM_COLUMNS 19 //Anzahl der Spalten

volatile uint8_t isShifting;
         uint8_t shiftRow;

int led_rot;
int led_gruen;
int led_blau;

int clockPin = 8;	//SRCLK
int dataPin  = 7;	//SER

void zeilen( unsigned long wert )
{
  //digitalWrite(9, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, ((unsigned long)1<<wert) >> 16 ); //Register 3
  shiftOut(dataPin, clockPin, MSBFIRST, ((unsigned long)1<<wert) >> 8  ); //Register 2
  shiftOut(dataPin, clockPin, MSBFIRST, ((unsigned long)1<<wert)       ); //Register 1
  //digitalWrite(9, HIGH);
}

//INTERRUPT ROUTINE
ISR(TIMER1_OVF_vect)
{
  if (!isShifting) {
    disable_XLAT_pulses();     //XLAT auf LOW
    isShifting = 1;
    sei();                     //Zeit neu starten
    TlcMux_shiftRow(shiftRow); //Ausgabe TLC
    zeilen(shiftRow);          //Ausgabe '595
    shiftRow++;                //Nächste Spalte
    if (shiftRow == NUM_ROWS) {//Setze Spalten zurück, wenn MAX erreicht
      shiftRow = 0;
    }
    enable_XLAT_pulses();      //XLAT auf HIGH
    isShifting = 0;
  }
}

byte pixbuff[NUM_ROWS][NUM_COLUMNS][3];

void setup()
{
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  TlcMux_init(); //TLC initialisieren
}

void loop()
{
  fill_all_255();
  Render();
}

void Render()
{
  Display();
}

void fill_all_255()
{
  for(int i = 0; i < NUM_ROWS; i++)
  {
    for(int j = 0; j < NUM_COLUMNS; j++)
    {
      pixbuff[i][j][0] = 255;
      pixbuff[i][j][1] = 255;
      pixbuff[i][j][2] = 255;
    }
  }
}

void Display()
{
  for(int i = 0; i < NUM_ROWS; i++)
  {
    for(int j = 0; j < NUM_COLUMNS; j++)
    {
      pixel(i, j, pixbuff[i][j][0], pixbuff[i][j][1], pixbuff[i][j][2]);
    }
  } 
}

void pixel(uint8_t row, uint8_t column, byte rot, byte gruen, byte blau)
{
   led_rot   = map( rot,   0, 255, 0, 4095   ); //Skaliere ROT-Wert
   led_gruen = map( gruen, 0, 255, 0, 4095   ); //Skaliere GRÜN-Wert
   led_blau  = map( blau,  0, 255, 0, 4095   ); //Skaliere BLAU-Wert

   TlcMux_set( row, column,      led_rot/1.8 ); //Setze ROT
   TlcMux_set( row, column + 32, led_gruen   ); //Setze GRÜN
   TlcMux_set( row, column + 64, led_blau    ); //Setze BLAU
}

Als HW habe ich 3 Schieberegister (74HC595) und 6 LED-Treiber (TLC5940) genommen.
Dabei habe ich das Schieberegister wie in 595.JPG und den TLC5940 wie in TLC5940.JPG angeschlossen.

Ich hoffe, dass jemand selbiges Problem bereits hatte und mir einen Tipp geben kann :slight_smile:

Danke im Voraus!!!

Bist du sicher, dass der Timer läuft? Nur weil du da eine ISR schreibst heißt das noch nichts. Da müssen noch so Dinge getan werden wie die Clock Select Bits setzen, den Prescaler einstellen und das Interrupt Enable Bit aktivieren.

Wenn man sonst nichts macht, kannst du da aber auch ruhig millis() oder micros() verwenden und einfach in loop() abfragen die Zeit vergangen ist. So super genau muss das nicht sein. Und wenn du dich mit Timern nicht auskennst verwende eine Lib dafür: http://playground.arduino.cc/Code/Timer1 http://playground.arduino.cc/Main/MsTimer2

Ganze Arrays auf einen bestimmten Wert zu setzen geht übrigens etwas einfacher mit memset(). Das geht auch mit mehrdimensionalen Arrays, da die einem in C nur mit einem zusammenhängenden Speicherbereich vorgegaukelt werden.

Schonmal danke für deine flotte Antwort :)

Allgemein hatte ich ja schonmal Erfolge bei der 3x3 Matrix verzeichnen können. Daher weiß ich, dass die Library insgesamt funktioniert.

Der Timer1 wird in der TLC5940Mux-Library gestartet. Habe jetzt mal flott einen Schnipsel rausgesucht - glaube, dass das der komplette Start ist. :sweat_smile:

    TCCR1A = _BV(COM1B1);  // non inverting, output on OC1B, BLANK
    TCCR1B = _BV(WGM13);   // Phase/freq correct PWM, ICR1 top
    OCR1A = 1;             // duty factor on OC1A, XLAT is inside BLANK
    OCR1B = 2;             // duty factor on BLANK (larger than OCR1A (XLAT))
    ICR1 = TLC_PWM_PERIOD; // see tlc_config.h
#ifdef TLC_ATMEGA_8_H
    TIFR |= _BV(TOV1);
    TIMSK = _BV(TOIE1);

Das mit dem Memset werde ich mir aber mal genauer angucken :) Aber in der Theorie wird mein Array doch richtig befüllt und ausgelesen oder??

Ok, dann sollte es gehen :)

Aber in der Theorie wird mein Array doch richtig befüllt und ausgelesen oder??

Ja, das funktioniert natürlich. Aber ein Einzeiler ist schöner :) Ist Geschmackssache

Serenifly: Ja, das funktioniert natürlich. Aber ein Einzeiler ist schöner :) Ist Geschmackssache

Wie gesagt, werde die schönere Variante natürlich übernehmen :)