Skip to content

RMT + Neopixel + WiFi = Flickering #8161

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

Closed
scoates opened this issue Jan 11, 2022 · 16 comments
Closed

RMT + Neopixel + WiFi = Flickering #8161

scoates opened this issue Jan 11, 2022 · 16 comments

Comments

@scoates
Copy link
Contributor

scoates commented Jan 11, 2022

This is related to #8158 + #7985.

I am experiencing neopixel "flicker"/noise only when Wifi is on.

Some background on my setup (same as what I described in #7985):

  • a 16x16 RGB panel (256 LEDs)
  • connected directly to my LOLIN D32 Pro board on GND, USB (+5V), 25
  • I'm using the firmware that @jimno built and shared in esp32/machine_bitstream.c: Replace with RMT-based driver. #7985
  • no capacitors or level shifters (maybe this would help, but this setup seems to work fine in FastLED, so I'm doubtful)
  • I've powered it both through USB on my computer, and by unplugging the USB connection and putting +5V over the panel's connection, which feeds back into the "USB" pin as +5V
  • works fine with FastLED from what I can tell
  • the current amount of flickering (which is signalled with RMT, on this firmware, I assume), is much less than what I experienced in esp32/machine_bitstream.c: Replace with RMT-based driver. #7985
  • it seems to happen only in the "later" part of the panel—I haven't seen any flickering in the first 4 or 5 rows of 16 pixels
  • I've tried this on different ESP32 boards (a second LOLIN D32 Pro, and a different WROOM board); same results
  • I tried a different LED panel that appears to be the same hardware, and the same problem
  • I've taken a short video. It's a bit hard to see, but definitely visible. The 0 pixel is on the right and the 255 pixel is on the left.

Here's the code I'm using (with various timings; all similarly flickery, but only with wifi turned on and connected to a local WLAN in boot.py):

import machine
import neopixel


np = neopixel.NeoPixel(
    machine.Pin(CONFIG["DATA_PIN"]),
    CONFIG["NUM_PINS"],
    # timing=(350, 800, 800, 350),  # , timing=(400, 850, 800, 450)
)
while True:
    print("doing a round.")
    for p in range(CONFIG["NUM_PINS"]):
        np.fill((0, 0, 0))
        np[p] = (64, 0, 0)
        np.write()

in #7985, @odi6331 suggested:

I changed them on my setup to a timing=(350,800,800,350) and all the flickering was gone since then.

I tried this timing on my setup, and it worked fine with wifi off, but when I turned it on, the flickering came back.

@dpgeorge
Copy link
Member

Thanks for the details.

works fine with FastLED from what I can tell

Do you have WiFi enabled and connected to the local WLAN when you test FastLED?

@scoates
Copy link
Contributor Author

scoates commented Jan 12, 2022

Hi. That's a good question. I couldn't recall for sure, so I loaded this onto my exact same hardware setup:

#include <FastLED.h>
#include <WiFi.h>
#include "wificonfig.h"

#define NUM_LEDS 256
#define LED_PIN 25
#define BRIGHTNESS 30

CRGB leds[NUM_LEDS];

void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, WiFiPassword);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println("Connected.");
  Serial.println(WiFi.localIP());
}

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);

  Serial.begin(115200);
  initWiFi();
}

void loop() {
  for (int n=0; n<=NUM_LEDS; n++) {
    FastLED.clear(true);
    leds[n].red = 255;
    FastLED.show();
  }
}

The serial monitor shows a LAN IP address, and no flickering/noise.

Edit: to explicitly answer your question: yes, local WLAN connected when testing with FastLED, and there's no "noise".

@scoates
Copy link
Contributor Author

scoates commented Jan 12, 2022

I also observed that when I do get flicker/noise on the Python side, it seems it's always around the pixel that's supposed to be lighting up—never at the other end of the matrix. This sounds like a localized timing error of some sort (but I don't know), and not general noise like I was seeing in the bit-banging implementation (referenced in #7985).

@dpgeorge
Copy link
Member

For further info can you please provide:

  • IDF version used
  • link to FastLED source code used (eg on github)
  • FastLED options used, eg FASTLED_ESP32_I2S

@dpgeorge
Copy link
Member

I can reproduce at least one glitching issue with the following set up:

  • an 8-neopixel strip
  • connected to WiFi
  • turn on all 8 pixels to one colour
  • construct a neopixel object with just 4 pixels, and in an infinite loop turn on first 4 pixels a different colour to the last 4
  • ping the device rapidly
  • eventually some of the last 4 pixels change colour (even though it's not supposed to be sending data to them)

If I revert to using the bit-banging implementation of machine.bitstream() then the glitching goes away and it works without any issues.

@scoates
Copy link
Contributor Author

scoates commented Jan 12, 2022

I was keeping up until now. (-:

I'm using platformio to manage that build+upload. It's PlatformIO Core, version 5.2.3 if that helps. It's really the code listed above, a simple wificonfig.h (+ nix shell + pipenv + python 3.8.9), and platformio.ini:

[env:lolin_d32_pro]
platform = espressif32
board = lolin_d32_pro
monitor_port = /dev/tty.usbserial-1440
monitor_speed = 115200
framework = arduino
lib_deps = fastled/FastLED@^3.4.0

The bit-banging strategy wasn't working for my panel; this is described in #7985 where @jimmo fixed it (for not-Wifi).

@wimaha
Copy link

wimaha commented Jan 12, 2022

I have the same problem.
In my setup i also use a level shifter and a 1000uF capacitor. So I'm sure the hardware should be fine.

I found this post: https://www.esp32.com/viewtopic.php?f=2&t=3980&start=10
Maybe we have the same problem? In this post the problem was solved by pinning the rtm to another core.

Is it possible to pin the rtm code to another core as wifi?

@dpgeorge
Copy link
Member

I found this post: https://www.esp32.com/viewtopic.php?f=2&t=3980&start=10 Maybe we have the same problem? In this post the problem was solved by pinning the rtm to another core.

Is it possible to pin the rtm code to another core as wifi?

That post is very interesting, it describes exactly the symptoms I'm seeing.

I tried pinning MicroPython to core 1 and it fixed the glitching with WiFi enabled for me (see related #7258).

I also tried calling rmt_driver_install() from core 1 and that also fixed things. I think this would be a good solution until #7258 is merged. Will make a PR.

@dpgeorge
Copy link
Member

I can reproduce glitches using just plain esp32.RMT. Here is the code:

import esp32, machine

# The channel resolution is 50ns (1/(source_freq/clock_div)).
r = esp32.RMT(0, pin=machine.Pin(14), clock_div=4)

def np_data(pixel):
    np_bits = ((8, 17), (16, 9)) # 400ns, 850ns, 800ns, 450ns
    data = ()
    for bit in range(24):
        data += np_bits[(pixel >> bit) & 1]
    return data

r.write_pulses(np_data(0x00_08_00) * 8, 1)
out4 = np_data(0x00_00_08) * 4
while 1:
    r.write_pulses(out4, 1)

Connect a neopixel strip with at least 8 pixel (although 6 would work) to Pin(14). Run without WiFi connected and it'll show solid green on the first 4, and solid red on the last 4 pixels. Turning WiFi on and running the code, eventually pixels 5 and 6 turn blue and pixel 7 turns off (it's always this glitch). The glitch happens faster if the device is ping'd.

dpgeorge added a commit to dpgeorge/micropython that referenced this issue Jan 13, 2022
MicroPython currently runs on core 0 of the esp32.  Calling
rmt_driver_install will mean that the RMT interrupt handler is also
serviced on core 0.  This can lead to glitches in the RMT output if
WiFi is enabled (for esp32.RMT and machine.bitstream).

This patch calls rmt_driver_install on core 1, ensuring that the RMT
interrupt handler is serviced on core 1.  This prevents glitches.

Fixes issue micropython#8161.

Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge
Copy link
Member

See #8170 for a fix.

@wimaha
Copy link

wimaha commented Jan 13, 2022

Thanks @dpgeorge! I tried your fix and for now it's working.

@dpgeorge
Copy link
Member

I tried your fix and for now it's working.

Great, thanks for confirming.

dpgeorge added a commit to dpgeorge/micropython that referenced this issue Jan 14, 2022
MicroPython currently runs on core 0 of the esp32.  Calling
rmt_driver_install will mean that the RMT interrupt handler is also
serviced on core 0.  This can lead to glitches in the RMT output if
WiFi is enabled (for esp32.RMT and machine.bitstream).

This patch calls rmt_driver_install on core 1, ensuring that the RMT
interrupt handler is serviced on core 1.  This prevents glitches.

Fixes issue micropython#8161.

Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge
Copy link
Member

Fixed by e754c2e

@scoates
Copy link
Contributor Author

scoates commented Jan 15, 2022

Great news! I built current master + flashed it, and it works for me, now, too.

Thanks, @dpgeorge.

@dpgeorge
Copy link
Member

Awesome! Thanks for confirming.

leifbirger pushed a commit to leifbirger/micropython that referenced this issue Jun 14, 2023
MicroPython currently runs on core 0 of the esp32.  Calling
rmt_driver_install will mean that the RMT interrupt handler is also
serviced on core 0.  This can lead to glitches in the RMT output if
WiFi is enabled (for esp32.RMT and machine.bitstream).

This patch calls rmt_driver_install on core 1, ensuring that the RMT
interrupt handler is serviced on core 1.  This prevents glitches.

Fixes issue micropython#8161.

Signed-off-by: Damien George <damien@micropython.org>
tannewt added a commit to tannewt/circuitpython that referenced this issue Jul 18, 2023
usb host: add keyboard map control in usb workflow
@Walkline80
Copy link

Is there any possible to fix flickering on single core MCU?

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

No branches or pull requests

4 participants