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

ESP8266 delay/milliseconds makes LED strip buggy #945

Open
Theagainmen opened this issue Dec 29, 2019 · 7 comments
Open

ESP8266 delay/milliseconds makes LED strip buggy #945

Theagainmen opened this issue Dec 29, 2019 · 7 comments

Comments

@Theagainmen
Copy link

@Theagainmen Theagainmen commented Dec 29, 2019

My setup

  • ESP8266 powered by USB, common ground with LED strip
  • 120 WS2812B LED's powered by a 5V 10A power supply
  • D5 (GPIO14) as data pin

The issue

Currently I'm working on a project that uses the ESP8266 as a websocket and webserver, I want to run the LED's at a certain FPS using the EVERY_N_MILLISECONDS( 1000 / FPS ) { } function.

I first ran all my tests without this function and everything worked as expected. Then I started to add this function (I'd prefer a non-blocking function so the websocket can still receive data) and I noticed that the LED strip started to bug out. I started debugging the websocket by adding a non-blocking delay, a blocking delay but it didn't help. I started playing around with the code more and I figured out that it was the FastLED itself (or maybe a combination with the WebSocket?). Whenever I don't have any waiting function and always call my FastLED function in the void loop() it'll work just fine. But whenever there's a delay (doesn't matter whether it's blocking or non-blocking) the LED strip starts to bug out.

For example (not full code, left out WiFi setup and Webserver/websocket parts for readability, this code works as expected):

// LED strip settings
#define DATA_PIN    14
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    120
#define MILLI_AMPS  10000

void loop() {
  int frameTime = 1000 / framerate;
  server.handleClient();
  webSocket.loop();
  juggle();
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}

This code runs as expected, the lights show up, no issues at all, I do receive the websocket data but I simply don't use it yet.

Now if I use this code:

void loop() {
  int frameTime = 1000 / framerate;
  server.handleClient();
  webSocket.loop();
  EVERY_N_MILLISECONDS( frameTime ) {
    juggle();
    //Pattern(1);
  }
}

I noticed that it doesn't work anymore, same for when I run my own pattern, it will work correctly without the delay, but if I use a delay it doesn't work anymore.

What happens

Juggle shows 8x dots that go back and forward while they leave a nice faded tail, whenever they cross it combines the colors.
With the 2nd code snippet it does somehow the same but there's a black dot in between the trails and each trail is almost as twice as long. I guess there's a FastLED clock running somewhere in the background that is used in those functions. I hoped FastLED.delay() would solve it, but it didn't.

If the issue is unclear I'll try to record a video.

I hope anyone could help me out here or try the juggle animation themselves with the EVERY_N_MILLISECONDS( framerate) { } to see if they have the same issue.

@jasoncoon

This comment has been minimized.

Copy link
Member

@jasoncoon jasoncoon commented Dec 31, 2019

Thank you for the thorough issue report. I don't see a call to FastLED.show(). Did you just omit it from your example code?

Tried using a constant value in the EVERY_N_MILLISECONDS call?

#define framerate 60
#define frametime 1000 / framerate
...
EVERY_N_MILLISECONDS ( frametime) { 
...

On the ESP8266, I normally just use delay(1000 / framerate). The call to delay yields to the ESP8266 core for processing wifi, etc.

@tihoangyeudau

This comment has been minimized.

Copy link

@tihoangyeudau tihoangyeudau commented Dec 31, 2019

Just change fastled.delay() to delay(). The code will work.

@Theagainmen

This comment has been minimized.

Copy link
Author

@Theagainmen Theagainmen commented Dec 31, 2019

I don't see a call to FastLED.show(). Did you just omit it from your example code?

My bad.. yes I left it out the example code.

Tried using a constant value in the EVERY_N_MILLISECONDS call?

Yes that's indeed one of the things I tried!

Just change fastled.delay() to delay(). The code will work.

I already tried that, but sadly with no result.

I decided to make a video with all these cases to hopefully make my issue more clear, basically all the cases where I just try any form of delay it won't work anymore.

The video (click) consists out of 4 cases with the following codes (I sometimes press the reset button in the video so you can see the start of the juggle animation):

Case 1: no delay

This case works as expected, and how it should work.

void loop() {
  server.handleClient();
  webSocket.loop();
  juggle();
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 25);
  byte dothue = 0;
  for ( int i = 0; i < 8; i++) {
    leds[beatsin16(i + 7, 0, NUM_LEDS - 1 )] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
  FastLED.show();
}

Case 2: delay(60)

Here you see where my issue comes in, it seems to stretch out 2x it's usual size and skip 1/2 LED's on it's tail.

void loop() {
  server.handleClient();
  webSocket.loop();
  juggle();
  delay(60);
}

Case 3: FastLED.delay(60)

Same as case 2
In this case FastLED.show() was removed from the Juggle() loop since FastLED.delay should call FastLED.show itself, I tested however both cases. Both cases gave the same result.

void loop() {
  server.handleClient();
  webSocket.loop();
  juggle();
  FastLED.delay(60);
}

Case 4: EVERY_N_MILLISECONDS(60)

Same as case 2 and 3.

void loop() {
  server.handleClient();
  webSocket.loop();
  EVERY_N_MILLISECONDS( 60 ) {
     juggle();
  }
}

I also made a case 5 where I only tried

void loop() {
  EVERY_N_MILLISECONDS( 60 ) {
     juggle();
  }
}

to see if the issue was maybe related to the webserver/websocket, it gave the same result however.

@roches1969

This comment has been minimized.

Copy link

@roches1969 roches1969 commented Jan 1, 2020

Try to put a "yield();" after the delay.
Also had problems with delay and delayus on a ESP8266 and the yield() after the delay made it function again.

@Theagainmen

This comment has been minimized.

Copy link
Author

@Theagainmen Theagainmen commented Jan 2, 2020

Tried

void loop() {
  server.handleClient();
  webSocket.loop();
  juggle();
  delay(60);
  yield();
}

but still same issue.

@d-a-v

This comment has been minimized.

Copy link

@d-a-v d-a-v commented Jan 2, 2020

delay() in main loop should be avoided on esp8266/arduino.
EVERY_N_MILLISECONDS is the right thing to do (similar to the BlinkPolledTimeout example in the arduino IDE).

Did you try this:
edit yes you tried it. It is anyway the good way to handle your delay and let other services work flawlessly.

void loop() {
  server.handleClient();
  webSocket.loop();
  EVERY_N_MILLISECONDS( 60 ) {
     juggle();
  }
}
@Theagainmen

This comment has been minimized.

Copy link
Author

@Theagainmen Theagainmen commented Jan 3, 2020

I think I found the bug..

void loop() {
  server.handleClient();
  webSocket.loop();
  EVERY_N_MILLISECONDS( 60 ) {
     juggle();
  }
  FastLED.show();
}

If I call FastLED.show() in the void loop() all the time and only delay the LED assignment (juggle) it seems to work as expected.. this took me way too long to figure out :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.