• Hi, i'm trying to control 160 APA106 leds (LED Clock) with the Espruino Pico and the neopixel library.

    In general, controlling the leds work (as in the addressed ones are lit up) but the brightness (an a bit of color shifting) occurres intermittently and gradually worse further along the 'strip' towards the end.

    I first thought about hardware issues (because gradual issues tend to be signal/noise related), so i've replaced the power supply, added a 330 ohm resistor on the data line, added a large capacitor on the power rail, tried the af_opendrain state with pull up resistor, added a cheap transistor based buffer (which was too slow) and so then ordered a SN74HCT125N buffer (instead) to increase the data signal van 3.3 to 5v. Then i added 100nF decoupling capacitors on some leds to see if that made a difference (even if the APA106 datasheet mentions no external components are needed). But none of these measures fixes the issue.

    Having searched the internet, i found out that the APA106 has different timings than the more common WS2812B or others, where the neopixel library is mainly setup for.

    So that got me wondered and i bought a scope (good excuse to do so, haha). I've scoped the dataline and noticed that the signal looks quite clean and (apart from the amount of data) the same in the beginning and the end of the loop. So with the signal/data beeing fine, i measured the periods of the data and noticed that the short period is about 0.42μs and the long period is 0.85μs which is in spec for the WS2812B (and to be expected probably), but the APA106 requires a long period of 1.36μs. Even with a tolerance of .15μs the 0.85μs is too short. This probably results in some bit shifting and increase of the rgb values?

    A possible solution would be to change the neopixel source code and compile/flash a complete new firmware, but that is way out of my comfort zone. And this won't allow for easy firmare updates (which i'm doing since the first kickstarter).

    Perhaps it is an idea to add an additional property to the require("neopixel").write() with 3 timings or just a led type (like the NeoPixelBus Arduino lib, which has fixed this issue also)? Not sure if that is possible for compiled code. Otherwise a 'custom' APA106 function would be nice.

    Or is there something other i can do (apart from changing the hardware)?

  • That's an odd one, I'm surprised this came up. Although I seem to recall I may have experienced the odd flicker even with WS2811 - it could possibly be an interrupt thing.

    One thing you could try - before the neopixel library, the code we used for sending looked like:

    SPI1.setup({baud:3200000, mosi:B5});
    var arr = new Uint8Array(57*3);
    var pos = 0;
    function getPattern() {
      var c;
      for (var i=0;i<arr.length;i+=3) {
        c = 10+Math.sin((i+pos)*0.1324)+Math.sin((i+­pos)*0.1)+Math.sin(pos)*0.2;
        c = E.HSBtoRGB(c-(0|c),1,1);
        arr[i  ] = c;
        arr[i+1] = c>>8;
        arr[i+2] = c>>17; // blue too bright
    function onTimer() {
      SPI1.send4bit(arr, 0b0001, 0b0011); 
    setInterval(onTimer, 50);

    So I guess you could try SPI1.send4bit(arr, 0b0001, 0b0111); which should add 50% to the time for a '1' - and see if that helps

  • Thanks for the quick response!

    When using SPI2.send4bit(arr, 0b0001, 0b0011); (i'm using pin B15 as the data line) in stead of require('neopixel'), i' getting the same behaviour als with neopixel (so gradually worse along the line with varying degrees for every send command).

    When using SPI2.send4bit(arr, 0b0001, 0b0111); i get random leds lighting up (random color, intensity, address) so that seems to break it :( .

  • Just to check, is the firmware on your Pico definitely up to date?

    I know in the past there was a phase where the Pico/WiFi/etc had some issues with the occasional glitch caused by interrupts during the send process, but I just looked and interrupts do seem to be disabled now

    Personally, I would have thought that if the LEDs work and then only flicker some of the time, it may not the actual timing of 1s and 0s that is at fault. It's possible that there is some kind of intermittent timing issue in the data that is sent.

    Since you have a scope, I'm not sure if it would have enough sample memory but maybe you could set it to trigger on the waveform so it all gets read in (even if you only send to a handful of APA106), and then just send out data manually until you get the LEDs to display the wrong thing.

    When they're displaying the wrong thing, the scope should hopefully have shown the trace and you can see whether everything looks ok (in which case it really is 1/0 timing or electrical) or whether somehow the actual data being sent from Espruino is glitchy.

  • The firmware was on 2.16, so i've upgraded to 2.17 (no release formpost?) but that did not matter in this case.

    So i've changed the code, so the send command is done on BRN press (in stead of interval). Then i could single shot capture the full signal for 160 leds (at the input for the first LED) and record a sample for a 'right' and 'wrong' moment by pressing the BTN a couple of times while resetting the single shot in between.

    When inspecting the last few bits of the long data signal (see attached file, where i've photoshopped the two captures over each other), it was noticable that a few bits have shifted/flipped? Where exactly the first change occures, i have not checked (as it is a very long data stream). But if that matters, i could investigate/compare further/deeper (however i doubt that this means a lot because the issue starts randomly along the line after about 16 leds, mostly in blocks.

    The total length of the captured signal is the same length most of the time, so it's more like there are bits shifted as apposed to delays in the full data signal.

    Just to be clear, in order to compare the data signals, i set all values to 20 (arr.fill(20)) and console.logging the arr before the send command, i can confirm that the arr data is allways the same, but the leds change (are not equally lit) everty 1-5 send command.

    Please let me know if you would like to have more info (video, source code, scope data...).

    1 Attachment

    • apa106-signal-difference.png
  • Thanks! That's very interesting... I'm just trying here and it seemed to work fine on WS2811, but I do have what I think is a strip of APA106 here (at least they light up blue when power is applied) and that did flicker when using the neopixel library, when using firmware 2v00 all the way to latest (I didn't test earlier).

    On closer inspection I realised that there was a tiny spike in the data output line just before transmission started, and it was because require("neopixel").write was re-initialising the SPI peripheral each time before it sent any data (although the code I posted above with send4bit wouldn't have done that).

    At least for me, that was throwing off the APA106 (but not WS2811) every so often.

    So what I've done now is to remove that initialisation if the SPI device was already initialised, which should work but will just be a pain if you're trying require("neopixel").write on different pins.

    If you try the latest 'cutting edge' build then it might fix it for you?

  • Just to add: I'm also surprised about the different data being sent, and I can't really see how that can happen - are you sure it's not just that the scope is triggering on a different point in the signal?

    Ideally you could reduce the amount of data you send (even down to just one pixel) so you can get the whole thing in the scope, and then you could be 100% sure

  • TL;DR: It turns out to be an electrical issue after all.

    Perhaps the timings for this type of LED are not optimal and makes the LED more sensitive to interference or something. But more likely the seller cheaped out on me and did not sell APA106 LEDs but P9823 or some other clones that require external components, but i can't say for sure. In the end, soldering decoupling capacitors on all LEDS (not only a couple as i tried before) fixed the issue.

    Long story:
    I first tried the latest espruino_2v17.23_pico_1r3.bin, but that did not fix the issue. I had to add the SPI2 setup to make it work in the first place, so that is probably not a good change (for other users) and i would suggest to revert that?

    So then i started measuring again, and noticed that the signal mostly stayed the same. Then i remembered i had ordered a cheap logic analyzer in the past, but misplaced it somewhere. After finding that, i've hooked that up and started logging.

    When measuring this way (and decoding as WS2813, because decoding as 2812 did not work), i saw that the values in the start where always correct (except for the first data signal after powering up, but thats ok).

    So i hooked up the other chanels further along the string of LEDS. Then, after a few tries i noticed that the values changed sometimes (from 141414 which is 20 to 282828), which should not happen of course. This made me beleive that the LEDs where not functioning properly and messing up the data signal (as the signal itself looked clean on the scope).

    After that, i started adding (more) decoupling capacitors on the LEDs and slowly saw that the issue was going away. As the datasheet for APA106's states that no external components are needed, i was looking the wrong way..

    My apologies for wasting your time!

    1 Attachment

    • apa106-logic-analyzer.png
  • Glad you got it sorted!

    from 141414 which is 20 to 282828

    That's twice as much so I imagine either a bit of data got lost or an extra one was found. Could it be that there was a lot of voltage loss down the string of LEDs or something like that?

    It's a bit of a worry that someone would be selling a LED strip that just doesn't work reliably :(

    I seem to recall that some of these LED chips actually recreate the signal they get - so after the first LED the pulse lengths will get reset to the correct levels.

    I had to add the SPI2 setup to make it work in the first place

    That's odd - were you using SPI for something else in your project too? When I tested here it all seemed to work fine without needing to call setup separately.

  • Hi,

    It was most likely interference on the powerline, and fixed because of the decoupling caps on all LEDs.

    It's not a led strip, but through hole LEDs connected in a grid-style (large Word Clock). So the issue are the LEDs themselves (beeing other types and/or the specs on the datasheet are incorrect or based on single led applications without beeing chained ;) )

    True, they recreate the signal (i've read you can use one as a makeshift level shifter because of that), so that is probably also why the data changed (interference on the power line causing one or more bits to flip).

    I've hooked up B3 to a DCF77 receiver and use the DCF77 library, but i don't think that uses/needs SPI(1). On espruino_2v17 sending data worked without the SPI2 setup, but with espruino_2v17.23_pico_1r3 i needed to add the SPI2 setup to make it work. So i think that last change is not an improvement.

    Thanks again for your effords, i'm happy to have it working now. :)

  • It's not a led strip, but through hole LEDs

    Ahh - actually I have heard of that being a problem with them. I imagine you don't need a capacitor on each one, but it's probably not a surprise you may need some kind of smoothing.

    I'll look into the changes that were made - we definitely do need something in there to avoid that glitch as I noticed it causing problems on some devices here, but I bet we can do it in a better way.

    edit: I just pushed a change which should improve matters. If a new SPI peripheral is set up, or the state of the pin used for neopixels is changed, SPI will be automatically set up again - so I think that should fix your issues with the newer firmware while also stopping glitches

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Wrong timings for controlling APA106 LED's using the neopixel Library

Posted by Avatar for Eddie @Eddie