A Nifty Tool For Counting Neopixels

Picture it. You’ve got a big roll of NeoPixels, but you have no idea how many are actually on the tape. Or you need to count how many WS2812B LEDs are in a display to properly plan your animations. Fear not, for [Gustavo Laureano] has built the perfect tool for counting the addressable LEDs.

The tool is based on a Raspberry Pi Pico, so it’s easy to replicate at home. The LED strip is simply connected to the microcontroller via a set of jumper wires going to the 5V and GND pins, while one of the Pico’s ADC pins is then connected to the strip’s GND pin after the jumper. A further GPIO pin is used to send data to the strip.

Essentially, this uses the jumper wire as a rudimentary current shunt. The code steps through the string of LEDs, turning each one on and then off in turn, comparing the value read by the ADC pin at each state. When the Pico detects no difference in current draw between the on and off states, that suggests it’s trying to turn on an LED beyond the end of the string, and thus the count is concluded.

You don’t need to understand any of that to put this device to good use, however. You can easily whip it up on a breadboard with a Pi Pico and parts you have lying around in the shop. Video after the break.

25 thoughts on “A Nifty Tool For Counting Neopixels

  1. Fun little project but it is quite slow. Apart from the actual time it takes to do the measurement, the most logical improvement would be to start with an initial guess (Maybe just “50” or the last measured length) and then do a successive approximation. This would make it quite quick on any reasonable display size. i.e. a million leds would at most take 20 iterations.

    Although having a LED test (RGB separately?) for each LED may also be a nice extra. This may benefit from a better shunt, but that’s also only a small change.

    Anyone else got more Idea’s to add some feature creep?

    1. Surely that scanning process was slowed down for demonstration purposes only 😳

      For an approximation method, what about a binary search? Set LED 2^N to be the only one on, scanning up the N till no LED is actually illuminated. Then the strip of LEDs is then known to be between the final 2^N and 2^(N-1). Then binary search between those two numbers.

      🤔 If each LED drew a constant current at a particular brightness, and the ADC current sensing was precise enough, couldn’t the mcu light up 1 or more LEDs, measure the current per LED, then just assume there’s 2000x LEDs and send the data to light them all up to see if there’s 2000 x Current-of-One that is consumed? If it knows there’s less, it could calculate how many did light up. And even if it it wasn’t certain of the exact amount, then it could probe where the approximate end of the LED string is.

      Another option could be akin to Compressed Sensing. Set an upper limit for how many LEDs to probe for. Then have a “clever” pattern of LEDs sent to all existing and non-existing LEDs. Do this a few times while measuring how much current is drawn with each pattern. Then do some math to see how long the string of LEDs would have to be to get the particular current values per pattern, since the “clever” patterns would be truncated in reality, and any variations in LEDs being on/off after that point wouldn’t be counted in the current consumption.

      I think the fastest/simplest solution would be if you could access the Data Out at the end of the string. Have the mcu clock in data continuously on the Data In, and measure how many clock cycles it takes for the data to come out the other end. Not great if you have a rolled up spool that you don’t want to unwind, though.

    2. @paulvdh said: “Fun little project but it is quite slow… Anyone else got more Idea’s to add some feature creep?”

      Start by using a faster programming language, like the C/C++ compiler. The sluggish MicroPython Interpreter has no business anywhere near a microcontroller like the Cortex M0.

      1. Hadn’t even noticed it was running uPython, but scrolled through the video until I saw some blinkenlights and timed roughly. Looking at the sourcecode at the begin of the video I see no obvious delays. I was expecting some delay due to to maybe something like a lot of averaging / filtering for the ADC measurement over a wire shunt. (Maybe just a few adc ticks?)

        RP2040 should have plenty of uhmpf to do it snappy even with that load on it’s back. Shifting WS2812 data has to be relatively quickly, that is inherent in the protocol, so at least it can do that. So now I am a bit confused. I either missed something or this uPython is truly awfully slow. Is it some kind of fluke, or add it to the list of reasons to dislike Python?

        1. My guess is that it is typical snobbery elitish. I am a C++ guy. But I use uPython quite often for a quick experiment like this. It is perfect for the task of getting a setup to run quick and easy. 90% of the time, performance is not really a factor for these style of projects.

          I also found it stable, unlike earlier lua attempts on microcontrollers. My cristmas lights ran on uPython and ran the whole season without a hitch.

          1. I was interested so just poking around a bit I suspect the slowdown is in the Neopixel library. If it would run at full speed I don’t know that the LEDs’ current would have time to settle.

    3. What about detecting burnt out LEDs? Have it also test a few LEDs past the one that doesn’t turn on to see if it’s the end of the string, or just a dead LED.

      (I know many of the cheap strips will kill anything past the dead LED, but some won’t.)

    4. One way of thinking about it is to consider the led strip as a giant wirewound potentiometer where the wiper is at an unknown position . A few years ago I decided to bring the old fairground GIANT BUZZWIRE game up to date using an Led strip instead of copper wire. Warning ! this has almost zero relevance to the problem at hand! Using a search coil in the wand the position along the strip can be detected by picking up the small Dout pulse radiated from each led when in close proximity “touched!”. With a travelling/tracking led pattern , the position can be determined to a resolution of a led pitch.

  2. If you have access to both ends of the strip, you could have an input that listens for data clocked out the end of the chain. Then you only need to send data one time as long as you try and send enough.

    1. My first thought too. But sometimes I have a string/array without an end connector, or it is buried and I’m too lazy to dig it out and put a probe on… the current sense hack is pretty clever but I agree with the above comments a binary search would be faster

  3. (First, let me state that it’s a neat project, with an interesting solution. By no means am I questioning why it was made/done, but more questioning promoting this as an actual solution to an actual problem.)

    Is this actually a problem for some people? I’ve personally worked with well over 50,000 LEDs in various projects over the years, and I’ve always just used a tape measure and some basic arithmetic, which takes seconds. 5050 strips typically only come in 3 different “densities” at 30, 60, and 144/meter. Strings are 50/segment.Just seems easier (and *much* cheaper!) to keep it analog.

    Perhaps one could use it for non-standard setups where there are hard to measure segments on a pre-made fixture, but I still feel like that’s got to be a very tiny amount, if any. Anyway, still a neat learning project!

    1. Your approach is obvious for determining the static default, i.e. the “expected” count.
      Runtime detection can still be useful for, well, runtime detection of errors that might occur after deployment of a system. LEDs could “burn out”, or connectors or even traces on those flex-strips could crack or break, esp. if there’s some kind of movement involved.

    1. How about pointing a camera at a random arrangement of neopixles. You iterate through them and record their position. Then display an image on them no matter how they are arranged.
      It could be good for putting flat images on 3D objects or soft moving surfaces.

  4. it’s just a shift register, what about a “walking ones” pattern. the output of the pixel does have a data_out, so load say 1000 zeros, and then shift a 1 and count the cycles.

    typically format is like R,G,B [ 8,8,8 ] or so, so 24 bits pixel, shift [ 1000000,0000000,00000000 ]

    Am I missing something?

    This sounds like an overly complex and error prone way.

    1. Except it’s usually inconvenient / expensive / “impossible” (due to some kind of product-/situation-specific constraint) to route back the output from the far-end of the strips, if they are connected “single-ended”. The strip(s) can easily end several meters away from the controller end; unless of-course they are arranged in some more-or-less loop back-like geometry.

      The ‘cost’ would include at the very least a return-wire as long as the strip; probably some mech. fastening things/adhesive to route & hold it; and probably some buffer(s) / driver(s), possibly several as signal repeaters.

      In case it’s already forming more or less a loop back close to the controller, then yes – looking at the D_out is an obvious solution, *but*…
      … even then, also sampling the LED current can still tell you if various LEDs along the string might have burned out, even if the digital shift-register logic still works.

      Or in fact, help pin-point the *actual point* of (the 1st) broken-connection, if there is one.
      In some cases it might be much more useful to know “there’s a break between N and N+1” than just “Meh, didn’t work, sorry. Bring out your DMM and go probing…”

      In fact, given enough resolution in the current-sampling, you could probably detect *two* things:
      a.) the 1st breaking point for digital shift-register data, by simply checking which LEDs can be enabled & disabled,
      b.) the number of LEDs that actually see any VDD at all. A broken connection affecting VDD/VSS might differ from a breaking point of Data or Clk(if applicable). But assuming that even unlit LEDs will probably contribute (linearly) to a combined “idle-current” when all LEDs are OFF, but powered, and knowing a typical idle-current of a single node, the VDD breaking point can also be estimated.

      And in case ‘b’ above; even if the resolution is too coarse or quiescent current of each node is too small to be resolved individually, (or if the idle-current can vary too much), it can still be helpful to guestimate how many “groups of N” LEDs that have connection to VDD & VSS, +/- a few.

      1. if you can’t measure the d_out, simply send 24’b0, and then walk a one, have a light sensor at the end of the strip, simple, and doesn’t need to make fancy current measurements. these things have finite drive limits, current limits, etc that limit the practical length of the strips.

        this again, sounds like a solution looking for a problem.

        he has a coil of pixels, we know the distance between leds, the diameter of the coil, it’s simple math, I can do it with probably the same accuracy, maybe better.

        1. He has a coil of pixels, not entirely basic.

          There’s the internal diameter, external, thickness of the strip, start and end points relative to each other, how tight is it wound? Did a machine do it or has it been loosely rewound by hand?

        2. > “have a light sensor at the end of the strip, simple”
          Though I fail to see how that solution would be better or cheaper than loopbacking D_out.
          If you have a light sensor at the far end, you’d need to bring back that signal instead to the controller’s end.
          If you have a geometry that means that the controller board at the near end indeed has a line-of-sight to all LEDs – or at least, the final one(s) – it makes more sense. In that case, of course use a local light detector (if it can be afforded in the BoM) to look at the far end.

          If you can’t trust a line-of-sight, you could also add a MCU with BT/Wifi/any-RF transceiver at the far end, and a receiver at the local side. When the remote MCU detects D_out toggling, it phones home a “Success!” message :-)

          Guess it could happen, if it’s a project with basically *no* BoM/cost limitations. The current measurement approach would be significantly cheaper and easier

          Probably most pragmatic solution is to just have a guy manually verify that all LEDs light up after assembly: running a test pattern in the production-test mode of the FW. If you can trust that no burn-out or breakage can “ever” occur during product life time – or just don’t care if it does

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.