Moving upwards from the Uno

Hello. This is my first post, I hope it's in the correct section.

I've built a simple Uno + WS2812B + Adalight set-up using 104 LEDs and FastLED 3.1 library. However I've never been happy with the FPS (12 or so). I've decided to upgrade but I'm unsure which one to go for.

I've read that the Teensy 3.x boards are not restricted by baud rates, meaning I should see an increase in the Adalight FPS. On the other hand, I'd rather stick with Arduino products as I'm now used to the high build quality and helpful website. Especially from a beginner's point of view.

Does anyone have an opinion on this? I have searched but it seems the Due and new, more powerful boards are still limited by baud rates. Is this correct?

Thank you for reading.

Piers

Hi,
Have you tried emailing Adafruit?
Send an example video of your project using their products.
You never know what you may find.
Without looking at your sketch it is hard to tell.

Tom... :slight_smile:

In the end, you will be limited by the transfer rate into the WS2812B:
"When the refresh rate is 30fps, cascade number are not less than1024 points."
"Send data at speeds of 800Kbps."

Teensy has connections with Arduino IDE so it can be coded for similar to the 8-bit 328/1284/2560 processors.

Sorry, I forgot to include the current sketch used.

I should also add that I've been using a baud of 1000000 without any errors.

Here it is:

#include "FastLED.h"

#define NUM_LEDS 104 // Max LED count
#define LED_PIN 6 // arduino output pin
#define GROUND_PIN 10
#define BRIGHTNESS 255 // maximum brightness
// #define SPEED 115200 // virtual serial port speed, must be the same in boblight_config 
#define SPEED 1000000 // appears to work, used for over a month without FPS drop

CRGB leds[NUM_LEDS];
uint8_t * ledsRaw = (uint8_t *)leds;

// A 'magic word' (along with LED count & checksum) precedes each block
// of LED data; this assists the microcontroller in syncing up with the
// host-side software and properly issuing the latch (host I/O is
// likely buffered, making usleep() unreliable for latch).  You may see
// an initial glitchy frame or two until the two come into alignment.
// The magic word can be whatever sequence you like, but each character
// should be unique, and frequent pixel values like 0 and 255 are
// avoided -- fewer false positives.  The host software will need to
// generate a compatible header: immediately following the magic word
// are three bytes: a 16-bit count of the number of LEDs (high byte
// first) followed by a simple checksum value (high byte XOR low byte
// XOR 0x55).  LED data follows, 3 bytes per LED, in order R, G, B,
// where 0 = off and 255 = max brightness.

static const uint8_t magic[] = {
  'A','d','a'};
#define MAGICSIZE  sizeof(magic)
#define HEADERSIZE (MAGICSIZE + 3)

#define MODE_HEADER 0
#define MODE_DATA   2

// If no serial data is received for a while, the LEDs are shut off
// automatically.  This avoids the annoying "stuck pixel" look when
// quitting LED display programs on the host computer.
static const unsigned long serialTimeout = 150000; // 150 seconds

void setup()
{
  pinMode(GROUND_PIN, OUTPUT); 
  digitalWrite(GROUND_PIN, LOW);
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);

  // Dirty trick: the circular buffer for serial data is 256 bytes,
  // and the "in" and "out" indices are unsigned 8-bit types -- this
  // much simplifies the cases where in/out need to "wrap around" the
  // beginning/end of the buffer.  Otherwise there'd be a ton of bit-
  // masking and/or conditional code every time one of these indices
  // needs to change, slowing things down tremendously.
  uint8_t
    buffer[256],
  indexIn       = 0,
  indexOut      = 0,
  mode          = MODE_HEADER,
  hi, lo, chk, i, spiFlag;
  int16_t
    bytesBuffered = 0,
  hold          = 0,
  c;
  int32_t
    bytesRemaining;
  unsigned long
    startTime,
  lastByteTime,
  lastAckTime,
  t;
  int32_t outPos = 0;

  Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!

  Serial.print("Ada\n"); // Send ACK string to host

    startTime    = micros();
  lastByteTime = lastAckTime = millis();

  // loop() is avoided as even that small bit of function overhead
  // has a measurable impact on this code's overall throughput.

  for(;;) {

    // Implementation is a simple finite-state machine.
    // Regardless of mode, check for serial input each time:
    t = millis();
    if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) {
      buffer[indexIn++] = c;
      bytesBuffered++;
      lastByteTime = lastAckTime = t; // Reset timeout counters
    } 
    else {
      // No data received.  If this persists, send an ACK packet
      // to host once every second to alert it to our presence.
      if((t - lastAckTime) > 1000) {
        Serial.print("Ada\n"); // Send ACK string to host
        lastAckTime = t; // Reset counter
      }
      // If no data received for an extended time, turn off all LEDs.
      if((t - lastByteTime) > serialTimeout) {
        memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
        FastLED.show();
        lastByteTime = t; // Reset counter
      }
    }

    switch(mode) {

    case MODE_HEADER:

      // In header-seeking mode.  Is there enough data to check?
      if(bytesBuffered >= HEADERSIZE) {
        // Indeed.  Check for a 'magic word' match.
        for(i=0; (i<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
        if(i == MAGICSIZE) {
          // Magic word matches.  Now how about the checksum?
          hi  = buffer[indexOut++];
          lo  = buffer[indexOut++];
          chk = buffer[indexOut++];
          if(chk == (hi ^ lo ^ 0x55)) {
            // Checksum looks valid.  Get 16-bit LED count, add 1
            // (# LEDs is always > 0) and multiply by 3 for R,G,B.
            bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L);
            bytesBuffered -= 3;
            outPos = 0;
            memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB));
            mode           = MODE_DATA; // Proceed to latch wait mode
          } 
          else {
            // Checksum didn't match; search resumes after magic word.
            indexOut  -= 3; // Rewind
          }
        } // else no header match.  Resume at first mismatched byte.
        bytesBuffered -= i;
      }
      break;

    case MODE_DATA:

      if(bytesRemaining > 0) {
        if(bytesBuffered > 0) {
          if (outPos < sizeof(leds))
            ledsRaw[outPos++] = buffer[indexOut++];   // Issue next byte
          bytesBuffered--;
          bytesRemaining--;
        }
        // If serial buffer is threatening to underrun, start
        // introducing progressively longer pauses to allow more
        // data to arrive (up to a point).
      } 
      else {
        // End of data -- issue latch:
        startTime  = micros();
        mode       = MODE_HEADER; // Begin next header search
        FastLED.show();
       /// This part drains the buffer and stops flicker, not included with standard file
       while(Serial.available()>0){ Serial.read(); }
      }
    } // end switch
  } // end for(;;)
}

void loop()
{
  // Not used.  See note in setup() function.
}