Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Driving WS2812B Leds with ESP32, palette is not continuous after addressing more than 63 leds #35

Open
McMathewson opened this issue Feb 6, 2023 · 1 comment

Comments

@McMathewson
Copy link

#include <FastLED.h>
#define NUM_LEDS1 64
#define LED_PIN1 22
CRGB leds1[NUM_LEDS1];
uint8_t paletteIndex = 0;

DEFINE_GRADIENT_PALETTE(redLight){
0, 255, 0, 0,
//102, 0, 0, 0,
127, 0, 0, 0,
//153, 0, 0, 0,
255, 0, 0, 0
};

CRGBPalette16 redLightPalette = redLight;

void setup() {
FastLED.addLeds<WS2812B, LED_PIN1, GRB>(leds1, NUM_LEDS1);
FastLED.setBrightness(255);
FastLED.clear(true);
}
void loop(){
fill_palette(leds1, NUM_LEDS1, paletteIndex, 255 / NUM_LEDS1, redLightPalette, 255, LINEARBLEND);

EVERY_N_MILLISECONDS_I(speedTimer, 1) {
paletteIndex++;
}
speedTimer.setPeriod(20); //use purpleVal for GPS
FastLED.show();
}

Im relatively new to coding on the ESP32 and I cant find anybody else with this specific issue but when I address more than 63 leds on my strip I have a sort of delay between the start and end of the strip. I have only had issues when using the fill_palette function.

I have a circular strip of WS2812B leds which total to 99 leds which id like to run a continuous moving palette on for a project.

In the arduino board manager im using version 2.0.6 eps32 board by Espressif Systems and version 3.5.0 of the FastLed library.

Let me know if this is the wrong place to post this issue or any other issue.

@robertlipe
Copy link

robertlipe commented May 3, 2024

I'm not involved in this project, but I tinker more than a little with ESP32 and WS2812's. An answer after a year from someone that's talking out of their hat might not be so helpful, but I'm what you've got. :-)

I think you're in the wrong place and are not actually using this project. I can see how it happened as there are a few projects with similar names.

IDF is Espressif's own SDK, optimized for ESP32. There is a project https://github.com/espressif/arduino-esp32 that sits atop of ESP-IDF and adds a smear of Arduino paint atop of ESP-IDF (more or less) that lets some/most of the packages written for the Arduino ecosystem run on ESP32. There's also the confusion that "Arduino" was the name of a family of 8-bit boards fron 2005 or so. So "Arduino" can refer to either a specific family of boards/MCUs, but increasingly it refers to software written for those boards that is now available for other boards/MCUs/SOCs of completely unrelated hardware. Oh, and there's an IDE that was originally written for those boards that uses a package manager to pull in all those libraries that's called...Arduino.

This software been known under other names, long ago, but there is a project named "FastLED" that targets all kinds of MCUs, with original focus on the AVR that was used on the Arduino boards. That project is https://github.com/FastLED/FastLED. It's a very successful and well-known package and lots of blinky light projects use the simple API that it presents.

THIS project looks like it takes the FastLED API, throws out all that silly 8-bit nonsense, and focuses on making a really good version specifically for the ESP32's and using Espressif's own SDK, ESP-IDF. If you're not building code with 'idf.py' (and/or one of the GUIs that does that for you) and/or the README.md doesn't match what's in the code for this project (https://github.com/bbulkow/FastLED-idf?tab=readme-ov-file) or your directory isn't named "FastLED-idf" or you don't have a THREADING.md, I don't think you're actually using this code.

Your code looks very arduino-y: setup() and loop() are Arduino. The version numbers also point to Arduino usage. An ESP-IDF project borrows a lot of conventions from FreeRTOS, notably that the entry point is app_main(). It's not apples to apples, but code using THIS project would look more like https://github.com/bbulkow/FastLED-idf/blob/master/main/main.cpp (That code is from this project, so that's not exactly a concidence.) ESP-IDF code tends to not use busy loops (like "loop") that spin-wait (bad for a processor in general, but torture on a multi-core device, especially one that's trying to do networking) and testing things like EVERY_N_SECONDS and instead using things like esp_timer_start_periodic() and xTaskCreate family to only do work when there's work to do.

I think you're using the Arduino SDK (probably via https://github.com/espressif/arduino-esp32) and are using the original, cross-platform FastLED, https://github.com/FastLED/FastLED, perhaps repackaged in a slightly different form, and not this project, https://github.com/bbulkow/FastLED-idf, which is optimized specfically for the ESP32 hardware and the operating system and SDK that it uses, ESP-IDF. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html

Looking at your code, I don't see a problem offhand. It looks like you're doing more work in loop than you have to. If the timer doesn't change and you don't bump paletteIndex, is there a reason to re-fill the pallette on every loop iteration (possibly while it's being drawn fastled.show() doesn't wait for the bits to be clocked out. You may thus be changing leds1[] while it's being drawn, depending on the hardware configuration. Also, there's no need to keep redrawing the strip if it hasn't changed; the WS2812's will remember their settings until the next show() starts clocking out a bit pattern. My starting point for triage would be to make

void loop(){
  fill_palette(leds1, NUM_LEDS1, paletteIndex, 255 / NUM_LEDS1, redLightPalette, 255, LINEARBLEND);

  EVERY_N_MILLISECONDS_I(speedTimer, 1) {
  paletteIndex++;
  }
  
  speedTimer.setPeriod(20); //use purpleVal for GPS
  FastLED.show();
}

into something more like

setup() {
  ... whatever you have now +
  fill_palette(leds1, NUM_LEDS1, paletteIndex, 255 / NUM_LEDS1, redLightPalette, 255, LINEARBLEND); // so it's initialized the first time
  speedTimer.setPeriod(20); //use purpleVal for GPS (don't keep reprogramming a timer on every loop iteration) 
}


void loop(){
  EVERY_N_MILLISECONDS_I(speedTimer, 1) {
    fill_palette(leds1, NUM_LEDS1, paletteIndex, 255 / NUM_LEDS1, redLightPalette, 255, LINEARBLEND);

    paletteIndex++;
    FastLED.show();
  }
}

loop() might, if you're lucky, run thousands of times per second. There's no reason to keep recomputing the pallete or reprogramming the timer, or scheduling draws at hundreds to thousands of times per second.

I don't know that any of this is related to your actual problem. It's just where I'd start.

This seems like a lot of words (esp from a random dude that's never even used THIS code) for "wrong number. who dis?" but hopefully it's helpful. If you still need a follow-up, providing a buildable test case and posting in reddit's r/fastled
seems to be the best way to reach qualified devs on that project if it's indeed what you're using.

P.S. to keep fancy code styling in Github issues, mark the block as code if you're using the browser editor or use markdown styling and wrap the block with opening and closing triple backticks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants