600 WS2812B LEDs mit Arduino Mega TPM2 und Jinx wenig FPS

Hallo zusammen,
ich möchte eine LED Matrix bauen welche 600LEDs beinhaltet.Dabei ist es Ziel nur einen Arduino zu verwenden.Dabei stoße ich jetzt aber auf das Problem das wenn ich im Programm Jinx den Output starte ich in etwa 0,25 bis 1 FPS am Streifen sehe und das bei einer Baud rate von 1152000 ich habe auch versucht die Baudrate zu ändern auf 500.000 und eine Million bei 500.000 kommt es mir um einen Ticken flüssiger vor und bei einer Million funktioniert gar nix mehr. Das alles waren Versuche im TPM2 Protokoll. Ich habe dann mal versucht die LEDs mit dem Glediatorprotokoll zum laufen zu bringen. was auch funktioniert sehr flüssig und reibungslos. Jedoch nur bis 300 LEDs alles darüber will Jinx den Patch nicht mehr vollständig ausfüllen. Und dessen Folge ist auch dass der Steifen keine Lust mehr hat anzuspringen. bei Glediator bin ich bei meinem Sketch gezwungen, eine Baudrate von einer Million zu verwenden. Ach ja und beim TPM2 Protokoll mit 300LEDs werden es trotzdem nicht mehr FPS!!!
Ich weiß jetzt nicht wie ich die 600LEDs mit einem Arduino ansteuern soll und das am Ende flüssig angezeigt werden soll. Ich hoffe es kann mir einer von euch helfen und sage schonmal im voraus Danke.
TPM2 Code

/**
 * TPM2 Example
 * with Adafruits NeoPixel library
 *
 * Copyright (c) 2019 Stephan Ruloff
 * https://github.com/rstephan/TPM2
 * 
 * GPL v2 only
 */
#include <Adafruit_NeoPixel.h>

#include "TPM2.h"

#define PIN 3
#define NO_OF_LEDS 600

uint8_t buffer[NO_OF_LEDS * 3];
TPM2 tpm2Driver(&Serial, buffer, sizeof(buffer));
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NO_OF_LEDS, PIN, NEO_GRB + NEO_KHZ800);


void CallbackRx(uint8_t* data, uint16_t len)
{
  uint16_t i, led;
  uint32_t c;

  for (i = 0, led = 0; i < len; i += 3, led++) {
    c = Adafruit_NeoPixel::Color(data[i], data[i + 1], data[i + 2]);
    strip.setPixelColor(led, c);
  }
  strip.show();
}

void setup()
{
  Serial.begin(1000000);
  tpm2Driver.registerRxData(CallbackRx);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop()
{
  tpm2Driver.update();
}

Glediator code

#define DATA_PORT          PORTD
#define DATA_DDR           DDRD						
#define DATA_PIN           3						
#define NUMBER_OF_PIXELS   600



//##############################################################################
//                                                                             #
// Variables                                                                   #
//                                                                             #
//##############################################################################

unsigned char display_buffer[NUMBER_OF_PIXELS * 3];
static unsigned char *ptr;
static unsigned int pos = 0;

volatile unsigned char go = 0;


//##############################################################################
//                                                                             #
// Setup                                                                       #
//                                                                             #
//##############################################################################

void setup()
{
  // Set data pin as output
  DATA_DDR |= (1 << DATA_PIN);
  
  // Initialize UART
  UCSR0A |= (1<<U2X0);                                
  UCSR0B |= (1<<RXEN0)  | (1<<TXEN0) | (1<<RXCIE0);   
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00)             ; 
  UBRR0H = 0;
  UBRR0L = 1; //Baud Rate 1 MBit (at F_CPU = 16MHz)
  
  ptr=display_buffer;
  
  //Enable global interrupts
  sei();
}


//##############################################################################
//                                                                             #
// Main loop                                                                   #
//                                                                             #
//##############################################################################

void loop()
{  	
  if (go==1) 
  {
    cli();
    ws2812_sendarray(display_buffer, NUMBER_OF_PIXELS * 3); 
    sei();
    go=0;
  }
}


//##############################################################################
//                                                                             #
// UART-Interrupt-Prozedur (called every time one byte is compeltely received) #
//                                                                             #
//##############################################################################

ISR(USART_RX_vect) 
{
  unsigned char b;
  b=UDR0;
  
  if (b == 1)  {pos=0; ptr=display_buffer; return;}    
  if (pos == (NUMBER_OF_PIXELS*3)) {} else {*ptr=b; ptr++; pos++;}  
  if (pos == ((NUMBER_OF_PIXELS*3)-1)) {go=1;}
}


//##############################################################################
//                                                                             #
// WS2812 output routine                                                       #
// Extracted from a ligh weight WS2812 lib by Tim (cpldcpu@gmail.com)          #
// Found on wwww.microcontroller.net                                           #
// Requires F_CPU = 16MHz                                                      #
//                                                                             #
//##############################################################################

void ws2812_sendarray(uint8_t *data,uint16_t datlen)
{
  uint8_t curbyte,ctr,masklo;
  uint8_t maskhi = _BV(DATA_PIN);
  masklo =~ maskhi & DATA_PORT;
  maskhi |= DATA_PORT;

  while (datlen--) 
  {
    curbyte = *data++;

    asm volatile
    (
      "		ldi %0,8	\n\t"		// 0
      "loop%=:out %2, %3	\n\t"		// 1
      "lsl	%1		\n\t"		// 2
      "dec	%0		\n\t"		// 3
      "		rjmp .+0	\n\t"		// 5
      "		brcs .+2	\n\t"		// 6l / 7h
      "		out %2,%4	\n\t"		// 7l / -
      "		rjmp .+0	\n\t"		// 9
      "		nop		\n\t"		// 10
      "		out %2,%4	\n\t"		// 11
      "		breq end%=	\n\t"		// 12      nt. 13 taken
      "		rjmp .+0	\n\t"		// 14
      "		rjmp .+0	\n\t"		// 16
      "		rjmp .+0	\n\t"		// 18
      "		rjmp loop%=	\n\t"		// 20
      "end%=:			\n\t" 
      :	"=&d" (ctr)
      :	"r" (curbyte), "I" (_SFR_IO_ADDR(DATA_PORT)), "r" (maskhi), "r" (masklo)
    );
  }

}

Dein Problem ist der falsche LED-Typ oder besser IC-Typ. WS2812B sind wegen des Protokolls in ihrer Datenrate beschränkt, weil Daten und Takt auf einer Leitung zusammen übertragen werden.

Ca. zehnmal schneller sind ICs vom Typ APA102 und vergleichbare mit Daten- und Taktleitung getrennt.

Das kann schon sein, aber ich habe mir damals 3 LED Bänder mit diesen Controllern bestellt und diese Testweise an das FastLED.h colorpalette Beispiel Programm angehängt was mehr als flüssig gelaufen ist. Deshalb verstehe ich nicht was der Flaschenhals bei der Geschichte sein sollte. Weil bei Glediator funktioniert als flüssig bis 300 LEDs und darüber nicht mehr und bei TPM2 funktioniert irgendwie gar nichts flüssig. Aber im Programm finde ich mit meinen Kenntnissen keinen Flaschenhals.

Ich wäre mir jetzt nicht sicher, ob die Ausgabe an 600 LEDs in einer Interrupt-Routine (TPM2 code) oder das globale Sperren aller Interrupts während der Ausgabe (Glediator code) wirklich glückliche Lösungen sind.

Das Protokoll der WS2812B ist zeitkritisch und darf daher nicht durch einen Interrupt unterbrochen werden.

Unterbrochen muss es meiner Meinung nach eh nichtwerden (WS2812B-Signal), weil wenn ich mir denke das so ein Testprogramm min. 25 FPS auf die Reihe bringt (laut Sketch sind es 100) und ein TPM2 Programm nicht, finde ich das schon schwach. Weil meine Denkweise für das Programm ist, dass es Daten über USB bekommt und dann an die LEDs übersetzt und dann sofort wieder auf USB-Daten wartet. Deshalb kommt es mir spanisch vor warum es in Glediator funkioniert und in TPM2 nicht.

Hallo

mal was zum lesen Link

hat zwar nicht mit Deiner Lib zu tun aber ich denke die Gründe sind die gleichen.

Heinz

Danke für die Antworten.
Ich sehe schon das der Arduino hier wohl seine Grenzen aufzeigt. Obwohl mir das nicht logisch vorkommt aber egal ich werde mir wohl ein leistungsstärkeres Board dafür holen müssen.
Danke an alle die hier auch ein paar Gedanken daran verloren haben.