mongoose-os-libs / neopixel

Other
2 stars 14 forks source link

Timing issue ? #1

Closed jeanmatthieud closed 5 years ago

jeanmatthieud commented 6 years ago

I'm using a WS2812b chip, with the GRB order, and an ESP8266.

On an Ardunio platform, with the Adafruit Library, everything works fine.

On the same device, with the MOS platform, it's impossible to have a real RED color. A yellow color is displayed instead.

I tried with the JS and C examples.

jeanmatthieud commented 6 years ago

In fact, the green is always on, even with: strip.clear(); strip.setPixel(0, 0, 0, 0); strip.show();

That's why the red is yellow and the blue is a lighter blue.

Maybe a timing issue as already seen on the FastLed lib: https://github.com/FastLED/FastLED/issues/104#issuecomment-64829622

tripflex commented 6 years ago

@jeanmatthieud are you using SPI on Arduino or bitbanging it like this lib does? Looks like this lib doesn't support SPI and does the standard bit banging (which is common for WS2812)

mamuesp commented 5 years ago

In fact, the timing was a little out of turn. I have fixed this problem and will soon publish a PR with possibilities to configure the timing via mos.yml. I mentioned the problem here. BTW I'm also working on a driver for the APA102 LED. @tripflex - SPI doesn't work with neopixels because they need a combination of PCM and PWM because they work clockless. They are only controlled by one wire and use different pulse widths to detect 0and 1. So a clock cycle within the given time (1.25us) is one bit, and starts with HIGH and drops to LOW, but with different durations. If it is shorter than half the cycles duration, it is considered HIGH and LOW if the drop occurs after half of the cycle duration. A LOW of more than 40 cycles is considered a "reset". This is all these devices may understand ... In contrast, the APA102, for example, can be controlled via SPI, but here one more connection is required (CLCK), and the data is transmitted with constant pulse width as pulse code. Therefore it is clear: for the Neopixel LEDs only bitbanging is possible, or SPI with some external hardware. SPI cannot be "bent" to produce a signal understandable for WS2812/Neopixel. P.S.: A good explanation might be found here (Adafruit Neopixel Überguide)

fjp commented 5 years ago

My problem is similar. In my case red seems always on even when using

strip.clear();
strip.setPixel(0, 0, 0, 0);
strip.show();

@mamuesp were you able to solve this issue?

@rojer could you please take the time to merge the pull requests?

mamuesp commented 5 years ago

@fjp - Yes, with the configurable timing settings I figured out the correct timing. The default didn't fit on every occasion. As I have ENOTIME, you may look at my fork: https://github.com/mamuesp/neopixel Anyway I'm planning to contorl the WS2812 over the RMT module, because for my purpose bitbanging is absolutely no option. That's why I use APA102 over SPI for the moment. Works like a charm.

fjp commented 5 years ago

@mamuesp thanks for the reply. I replaced this neopixel lib with yours in my mos.yml followed by mos build and mos flash but nothing changed, red is still always on :( I am using the WS2812B on the D1 mini rgb shield.

Do I have to change something else to get the correct timing?

fjp commented 5 years ago

@mamuesp I tried with the example-neopixel-c, replaced the neopixel lib with yours and it works 👍

In my other app I am using the http-server lib. In the app's main function I switch the led off but the red channel stays on... Don't know why though.

fjp commented 5 years ago

Ok there is something "wrong" with the http-server lib. Everytime I include it in the mos.yml the led keeps switching to red even when I do not include headers or use any of its functions. Is the http-server lib writing to pin 4?

The colors are correct when I don't use the http-server lib:

# List of libraries used by this app, in order of initialisation
libs:
    - origin: https://github.com/mongoose-os-libs/boards
    - origin: https://github.com/mamuesp/neopixel
    - origin: https://github.com/mongoose-os-libs/rpc-service-config
    - origin: https://github.com/mongoose-os-libs/rpc-service-fs
    - origin: https://github.com/mongoose-os-libs/rpc-uart
    #- origin: https://github.com/mongoose-os-libs/http-server

Any ideas why this is happening?

mamuesp commented 5 years ago

@fjp - As bitbanging is blocking everything and time consuming (so e.g. the interrupt handling will be stopped for a moment), there might be side effects so the data transmission won't work accurately. In my opinion this solution will only work as (almost) a standalone function with no other timers, events or interrupts interfering with the process. That's why I switched to APA102, there the data transfer might be handled via SPI in the background.

galilov commented 5 years ago

I fixed the issue for WS2812b which I noticed on ESP8266. Please find the fixed version at https://github.com/galilov/neopixel It works well without any issues.

Usage:

libs:
  - origin: https://github.com/mongoose-os-libs/boards
  - origin: https://github.com/mongoose-os-libs/ca-bundle
# other libs
  - origin: https://github.com/galilov/neopixel  # link to github
    version: 2.15.ag  # used version

It is a very simple fix:

void mgos_neopixel_show(struct mgos_neopixel *np) {
  mgos_gpio_write(np->pin, 0);
  mgos_usleep(100);
#if MGOS_ENABLE_BITBANG
  mgos_bitbang_write_bits(np->pin, MGOS_DELAY_100NSEC, 3, 8, 8, 3, np->data,
                          np->num_pixels * NUM_CHANNELS);
#endif
  mgos_gpio_write(np->pin, 0);
  mgos_usleep(100);
  mgos_gpio_write(np->pin, 1);
}

I changed timing according to ws2812b doc which was not really necessary and changed the initial usleep from 60 to 100 uS which fixed the issues for 100%. And the trailing pause was also prolonged from 60 to 100 uS.

rojer commented 5 years ago

please submit a PR

rojer commented 5 years ago

https://github.com/mongoose-os-libs/neopixel/pull/5 merged, i'll consider this fixed, please reopen if not.

TheCrypt0 commented 4 years ago

I had issues with timings too, I'll add my discoveries here since the latest commits didn't work for me. I hope to save someone else's time.

I've recently got a WS2812B strip and since I've been looking to try Mongoose OS for a while so I thought why not give it a try with those LEDs.

Unfortunately, I couldn't make it work no matter what I tried. Sometimes, when I connected and disconnected the data line, I would get some random flashes of the correct color, meaning that something was passing though but not what I was hoping for.

I immediately thought of a faulty board, changed it with another one but without any luck. I then flashed WLED and (to my surprise) the LEDs light up without any issue, even displaying fast animations.

Long story short, I found this article which explained the protocol in details. Particularly, this the following paragraph was a game changer:

Another possible issue comes with a change from 2017. New WS2812B LEDs started to appear, requiring 300us reset times instead of the 50us we discussed earlier. The concepts presented here will still apply with this time change, but if you're going to construct your own interface on a very low level, consider yourself warned.

I changed the reset delays from 100uS to 300uS, recompiled and it worked! There were some minor glitches but this was a big step forward.

After playing around with the timings I got a reliable data transmission with the following code (borrowed from @galilov's library with some values changed).

void mgos_neopixel_show(struct mgos_neopixel *np) {
#if MGOS_ENABLE_BITBANG
  uint8_t data = 0;
  mgos_bitbang_write_bits(np->pin, MGOS_DELAY_USEC, -1, 30, -1, 30, &data, 1);
  mgos_bitbang_write_bits(np->pin, MGOS_DELAY_100NSEC, 3, 9, 9, 6, np->data,
                          np->num_pixels * NUM_CHANNELS);
  mgos_bitbang_write_bits(np->pin, MGOS_DELAY_USEC, -1, 30, -1, 30, &data, 1);
  mgos_bitbang_write_bits(np->pin, MGOS_DELAY_USEC, 30, -1, 30, -1, &data, 1);
#endif
}

It looks like there are multiple versions of WS2812B LEDs with very different timing requirements. It would be very useful to have a compiler flag to choose what timings to use.

Cheers, Crypto

sushantr5 commented 4 years ago

I have built custom PCB using ESP 32 and 4 WS2812B-B Pixels.

The Neo Pixels just works fine with ESPHome firmware. But when I try with Mongoose firmware, first pixel does not respond correctly. Second pixel becomes first pixel and so on. But real physical first pixel ( zeroth Index ) does not work.

Please help me in this as I am stuck here.

I again tried with FastLED arduino, all pixels work fine.