Closed MustBeArt closed 3 years ago
Thanks to @abraxas3d for working with me to find this issue.
If the strip is of type NEO_GRBW, the maximum length is even shorter, and matching your math perfectly: 24 LEDs work, but (with the delay(1) workaround in place) LED#25 (n=24 starting from 0) of a 30-pixel strip shows a red offset when the brightness is low. It seems like one bit is forced to 1 due to the timing issue. I confirm that disabling the interrupts also works for me, but agree that interrupts should never be disabled that long.
Thanks @MustBeArt for the documentation, I had the same problem in my code but I already manage to solve it
When researching NeoPixels for the ESP32 I came across a library for FreeRTOS that uses the IR engine to generate the pulses and uses interrupts to keep the pipe full. I think for the ESP32 this would be a better solution than the normal method for driving the LEDs since the pulses and timing are handled by the hardware and it also would be fine for interrupts.
See https://github.com/marcmerlin/Neopixel-IR/blob/master/esp32_ws2812.cpp
Using the RMT is addressed here. Waiting on driver support from upstream.
No idea if this is the same issue, but my NeoPixel code that works perfectly using AdafruitIO on a Feather Huzzah does not work properly on the FeatherESP32. I can flash the exact same code to both and the ESP32 board always sets the first pixel green and flickers no matter what color I set it to after that. It's been incredibly frustrating trying to figure out why...
Hi @scott-linenberger I have exactly the same issue with Artnet on Feather HUZZAH ESP32, actually looking to fix It without any luck so far
@Heljick --> I couldn't fix the issue either. The NeoPixels seem to work fine so long as I don't make an AdafruitIO connection. So, it would seem that when I'm using WiFi and the NeoPixels, the first pixel flicker is there. I tried different level shifters, tried a ton of code to reset and clear things...Wound up having to return my ESP32s and just use the updated Huzzah Feather (which is working absolutely fine).
Thanks @scott-linenberger for the feedback, can you give me the link to your Feather ? I am in France adn it's very annoying for me, not sure I can't return mine :/ I saw people had issue and solved It using an other library than Adafruit one but can't remember where and if It was exactly for that issue. Will post a review if I can found it but for what I remember this was a delay issue and just having delay(2) solved there problem (maybe was for ESP8266)
Found the thread https://github.com/Makuna/NeoPixelBus/issues/152
@Heljick This is the other Feather I used that works fine with AdafruitIO and NeoPixels Huzzah Feather I also tried a different library: FastLED and had the exact same issue, as soon as I introduced a WiFi connection...flickering lights..
OK thanks I assume It's better to stay on ESP8266 indeed even if it's three times slower :/ Shame was very happy so far.
heya @me-no-dev do you have any recommendations?
@ladyada issue comes from the fact that we are running on top of freertos so the scheduler switches task every tick (1ms). In the beginning Arduino was the only task running on Core1, but that was later changed in IDF so some tasks run without core affinity, thus interrupting the loop task on Core1. The only long time solution is to use either RMT or I2S in combination with DMA so the transmission is not interrupted. Bitbanging time critical protocols that transmit longer than the tick period is kinda impossible on ESP32.
@ladyada I can help with a custom driver based on one of the above protocols. Let me know :)
@me-no-dev we've got no indepth experience with the RMT/DMA framework on ESP32 so a pull req from y'all would be super appreciated by everyone it seems :)
Will do :) I have a feather-wing with neopixels here. Just one question... AFAIK there are two different signal standards and colour orders right? Like RGB and BGR and two different timing schemes. Could you point me to the proper info on those? Or I can get all that info from the lib and your website?
the color order is swapped in software, the timing scheme is identical. the library passes a uint8_t array, and the number of bytes to write to the HAL. the is800khz flag is always true (almost nobody has 400khz pixels anymore) https://github.com/adafruit/Adafruit_NeoPixel/blob/master/esp8266.c#L24
Unfortunately I based my WS2812B hardware application on ESP32 before doing thorough checking (in my prototype I used a strip of 30 LEDs while the final project, for which I already printed PCBs, uses 120 LEDs). As you can imagine, there are glitches all over the place after LED #32.
As expected, using delay() doesn't help in my case of 120 LEDs.
What I find odd though, is that even if I use the portDISABLE_INTERRUPTS() "workaround" the problem does not disappear completely. In theory, even though disabling interrupts introduces so many other problems, it should totally fix the glitches in the LEDs. In practice, in my case, the glitches are reduced 90% but not completely disappear.
Anyway, that's my 2 cents on the issue. Since I have a custom PCBA with ESP32 and 120 WS2812B sitting there, I can help with any debugging you guys may need.
I have success with using I2S, but the IDF I2S driver will not do. The way that DMA is implemented causes issues. So... I use my own I2S driver and all is fine. At least for 340 pixels (DMA accepts up to 4096 bytes at once). Now I need to write the I2S driver so it can go into Arduino's HAL and will PR the changes here. Maybe 8266 can go the same direction and use I2S as well?
sure, weve used SPI to DMA befroe, on the samd21. as long as you have pin flexibility i don’t think people care too much how it happens. :)
Same issue, ESP32 feather + NeoPixel FeatherWing == glitches even on strandtest unless you use delay(1);strip.show()
, and the delay(1)
trick doesn't seem to work at all once you turn WiFi on. Looking forward to @me-no-dev's PR! But in the meantime you might want to include a note on the NeoPixel FeatherWing product page re: ESP32 (in)compatibility? I bought my ESP32 feather + featherwing just a few weeks ago, I would have gotten the Huzzah if I had a had any clue there was a problem.
EDIT: I just tried https://github.com/Makuna/NeoPixelBus with total success, even with WiFi and Serial. Had to install from git, though, due to https://github.com/Makuna/NeoPixelBus/pull/212 on Linux. I can confirm that's a good workaround until the Adafruit library gets hardware support on ESP32.
@cscott added a note to the product page. @me-no-dev any updates or code we can test?
@ladyada sorry I have been quite busy with a whole lot of things. I have a form of the driver running through I2S and one of my colleagues wrote a driver and example with RMT (in PR already), so you will have all the options quite soon. I have tested with up to 48 leds (that is all I have) and everything seems good.
@cscott Makuna uses an early version of my I2S driver, but will also switch to the main one once finished. Afterall using a half-ass driver is not an option for Adafruit :)
Is there any update on this? What is the current problem?
Is a workaround available?
Hey everyone. I made my own workaround a while ago, and have been meaning to make a pull request. I don't think I will get around to it soon, so I am just posting my implementation here that gets around it. I am using RMT, like @me-no-dev suggested. Feel free to use/abuse my code how you like. https://github.com/jordan9001/ColorWaves/blob/master/Hardware/EspControl/WS2812_ESP_RMT.cpp
Looks like https://github.com/Makuna/NeoPixelBus has made a new release since my post above, so you no longer have to build it from git. That should be a reasonable workaround for most folks, I think.
neat - if someone is feeling especially kind, a PR would be greatfully appreciated! if not, we'll try to get to it next time we do a sweep thru this library
@cscott its' good to cyber-see you - ahh i remember that killer mystery hunt puzzle with the pic micro and the mirror-ball. would be neat to rebuild it! (it was assigned to me but i never solved it :)
I can confirm that the Adafruit library is not working right on (my) ESP32 but NeoPixelBus is. Thank you!
@ladyada Are you hunting this year? Gnireenigne Lab was arguably too hard a puzzle given that it required decompilation of PIC flash contents (I was a novice writer!) but I was quite pleased/proud of http://web.mit.edu/puzzle/www/2012/puzzles/ben_bitdiddle/investigators_report/ ...
Sorry for drifting off topic...
@cscott nah, im terrible at that stuff - and not local :) anyways, just wanted to 👋
Hi all my lib works cross platform using the SPI MOSI pin https://github.com/leonyuhanov/SK6812viaSPI/tree/master/ESP32 feel free to integrate
Hi All, As well, I found a workaround to keep interface and WS2812FX class functionality Fell free to see https://github.com/Yurik72/ESPHomeController/wiki/WS2812-driver-to-remove-flickering
I have written a WS2812B driver loosely based upon https://github.com/MartyMacGyver/ESP32-Digital-RGB-LED-Drivers
Instead of ending transmission, I keep the RMT in constant transmit (i.e. I never fill RMT entries with 0). I have tested my code on these https://www.aliexpress.com/item/DC5V-WS2812B-1m-4m-5m-30-60-74-96-144-pixels-leds-m-Smart-led-pixel/32832420003.html?spm=a2g0s.9042311.0.0.319e4c4dX1ZIpO (upto 150 pixels in a strand).
To get it to work though, I had to increase the stretch of duration1 on the last pixel to 3 TRS (i.e. 150us vs the datasheet's 50us). Using TRS values lower than 3TRS resulted in the strand not being reset and therefore cascading forever.
I don't have a scope to measure what is actually happening on the data line, but as I still get high refresh rates, my hypothesis is that the actual time of duration1 is lower than described by the datasheet when duration0 is much smaller than duration1.
The ESP32 library has what looks to be some official RMT tools built-in. They even provide an example. They work just fine for driving WS2812B pixels. I have it working with a flexible 8x32 display with no problems (which is amazing after fighting all sorts of weird flashing and flickering when driving the pin, even with interrupts disabled). With the RMT code, all artifacts have been completely silenced (though, I found I could somewhat reduce them by strapping a couple 220pf capacitors across data and ground).
Anyway, to get this working, I monkey-patched Adafruit_NeoPixel.cpp
to use the RMT peripheral. You can find my code here:
That code is horrible, but only because I'm rushing by monkey-patching rather than making a careful fix. It ignores standard defines and hardcodes things in a way I would never do for a library I'm actually distributing. I hate to share my code in it's current state, but by sharing it I'm hoping to remind myself to come back next week and fix it.
I based my code off of the example that is on the official espressif repo. That code can be found here:
I hope to make a PR next week AFTER I finish giving a talk at The Perl Conference which features the device I need this for. I will have time after that, but definitely not before because I don't even have slides yet.
I think I'm experiencing this same bug on an ESP32 board I made. I'm using the Neo7Segment library which relies on the Adafruit_NeoPixel library. Here is what I am seeing:
Video of Neo7Segment demo -> https://imgur.com/5zKBg4n Same board running FastLED demo -> https://imgur.com/jAo15dh
Hi, any news about this issue? experiencing the same problem with esp32
Fixed year ago https://github.com/Yurik72/ESPHomeController/wiki/WS2812-driver-to-remove-flickering
On Sun, Mar 8, 2020 at 2:49 PM ramarro123 notifications@github.com wrote:
Hi, any news about this issue? experiencing the same problem with esp32
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adafruit/Adafruit_NeoPixel/issues/139?email_source=notifications&email_token=AKDREXOG5FBJPDDTYYCAMI3RGOH55A5CNFSM4DLP5P7KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEOEVFUI#issuecomment-596202193, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKDREXIS4YNUXSYFBFBJBBDRGOH55ANCNFSM4DLP5P7A .
did you submit a patch for this project? are you promoting your project saying that you managed to fix in a different library? was your fix backported here?
i don't see how linking a different library can help :) i am aware that fastled, neopixelbus, and now this other library probably, support rmt on esp32 ... but i am asking about adafruit_neoload not about other_library
Anyway, to get this working, I monkey-patched
Adafruit_NeoPixel.cpp
to use the RMT peripheral. You can find my code here:That code is horrible, but only because I'm rushing by monkey-patching rather than making a careful fix. It ignores standard defines and hardcodes things in a way I would never do for a library I'm actually distributing. I hate to share my code in it's current state, but by sharing it I'm hoping to remind myself to come back next week and fix it.
@zostay
Apologies for digging up an old post, but I had a similar issue with NeoPixels and ESP32. I made my own NeoPattern library but am not skilled enough to convert it to the likes of NeoPixelBus so when I came across your post and RMT version I thought I'd give it a try, however, it doesn't seem to work. When using your .h and .cpp the neopixels do absolutely nothing. Is there something special I need to add or change? I was hoping it'd just work by dropping it in (I've included your .h and .cpp locally in the project folder)
`
`
There's no error, the neopixel strip just does nothing. If I upload basic NeoPixel test, everything works albeit glitchy with the odd artifact, so it's definitely something related to swapping the libs and NOT a hardware/wiring/power issue
MTIA
Yeah what ever happened with this? I do not think a PR was ever made for RMT on esp32, are people just using other libraries now?
I‘m also interested in getting this to work. Question: Did someone tried to use Neomatrix with Neopixels library instead of this one? The demos work but I see this issue everywhere in a 50x20 matrix By the way is funny this 1 ms tick is displayed as a "diamond" I've the feeling there is more than this. Using the port* disable interrupts still shows some so I guess not a real solution.
portDISABLE_INTERRUPTS();
matrix->show();
portENABLE_INTERRUPTS();
Does this issue sound like the same problem ?
Some people say that if you move your pixel rendering to second core it helps. So far I tried NeoPixel library and other Library called NeoPixelBus and FastLED, all of them suffer from flickering on ESP32 when you use Wifi. The only think that left is running on separate core which I'm going to do next.
NeoPixelBus supports Matrix, here the reply of Michael in the gitter channel: Matrix is supported, check out the wiki, including not only a single panel layout but also mosaics of those panels. There are samples for it. But it is just a coordinate translation object.
So the killer solution would be to fork Neomatrix from Adafruit and make it work with Neopixel Bus. This library is simply not for ESP32. You cannot avoid this 1ms ticks and is really annoying to use like it is right now. Need to find the time to see if this idea can be done, keep tuned
Thanks @BatsIhor for the hint that moving to the second core helps! Doing that removed all the flickering for me, I still had to disable interrupts though. But at least it works now.
This is my code:
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define PIN 2
TaskHandle_t Task1;
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, 2, 1, PIN,
NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS + NEO_TILE_PROGRESSIVE +
NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_TILE_PROGRESSIVE,
NEO_GRB + NEO_KHZ800);
const uint16_t colors[] = {
matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255)
};
void Task1code();
int x = matrix.width();
int pass = 0;
String scroll_text = "This is a test !!!";
void setup() {
Serial.begin(115200);
matrix.begin();
matrix.setTextWrap(false);
matrix.setBrightness(40);
matrix.setTextColor(colors[0]);
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, &Task1, 0);
delay(500);
}
void Task1code( void * pvParameters ) {
for (;;) {
matrix.fillScreen(0);
matrix.setCursor(x, 0);
matrix.print(scroll_text.c_str());
if (--x < (int)(-6 * scroll_text.length())) {
x = matrix.width();
if (++pass >= 3) pass = 0;
matrix.setTextColor(colors[pass]);
}
portDISABLE_INTERRUPTS();
matrix.show();
portENABLE_INTERRUPTS();
delay(100);
}
}
void loop() {
delay(10);
}
released as 1.7.0
On the ESP32, an extra delay of about 5 microseconds is inserted into the signal output every millisecond. This is far outside the Neopixel timing tolerance of 150 ns, so it leads to incorrect values in some of the pixels.
The data for up to 33 RGB pixels can be transmitted in less than one millisecond (1.25 uS per bit X 24 bits per pixel X 33 pixels = 990 uS). In the common case where the show() method call immediately follows a delay() function call, the problem is not encountered unless the strand has at least 34 RGB pixels. However, if the code keeps time some other way (such as by calling millis() repeatedly) the extra delay may occur with random alignment to the signal. In that case, the signal may be corrupted with even a single pixel strand.
The extra delay may also be avoided by disabling interrupts during the call to the show() method. In the ESP32 Arduino environment, this cannot be done in the usual way, by calling noInterrupts() -- that function is defined to be nothing in Arduino.h. It can, however, be accomplished by invoking the macro portDISABLE_INTERRUPTS() defined by FreeRTOS in the file portmacro.h, since the Arduino code in the ESP32 is actually running on top of FreeRTOS. The macro portENABLE_INTERRUPTS() re-enables interrupts. Of course, if this method is used, any other time-critical operations will suffer interference, probably including millisecond timekeeping.
Method to Reproduce
The best way is to observe the output signal on a logic analyzer. Use any sketch that talks to pixels, and set the number of pixels to at least 34. In each burst of activity on the signal line representing a single strand update, you should see at least one pulse (high or low) of between 5 and 6 uS, and those pulses should occur every millisecond thereafter (when the millisecond coincides with signal activity).
If no logic analyzer is available, you can see the problem with just a strand of pixels. If a strand of more than 33 pixels is available, simply hook it up and try to run any of the example sketches. Flaky pixels will be visible.
If no long strand of pixels is available, the following sketch will illustrate the problem with whatever length strand you do have. Because the strand is short, the extra pulse will only occur some fraction of the time, so you may have to watch for a while to see flaky pixels. (This is how I originally discovered the problem. I use this method of timekeeping when I need to process more than one time-critical device.)
Workarounds
If your sketch is written so that every call to the show() method always follows immediately after a call to delay(), you can use up to 33 pixels in a strand without a problem. (Note: delay(0) doesn't work, it has to be at least delay(1).) The provided example sketches work this way.
If your sketch keeps time some other way, you can add a delay(1) call immediately before each call to the show() method, and use up to 33 pixels in a strand without a problem.
If you must have strands of 34 or more pixels, your only choice is to disable interrupts as described above and suffer the consequences.
Suggested Solution
The problem is pretty fundamental. The only way to prevent the extra delay appears to be to disable interrupts, and disabling interrupts for more than a millisecond (much more for long strands) is hardly a good answer.
See http://www.insentricity.com/a.cl/268/controlling-ws2812-rgb-leds-from-the-esp32 for an alternative driver design that should avoid this difficulty, if it can be ported to the Arduino environment.