Capturing and Repeating a WS2812B Signal (Project Feasibility)

Hello!

First, I should say I am completely new to this type of electronics. I am exploring the use of a ATmega328P to solve a problem I am currently scratching my head over. I feel I am maybe on the right track here, but would like to know if it really would be feasible to use an Arduino Uno, Nano or Pro Mini for my ends in this case.

My question is this:

Using timer1 capture event interrupts, am I able to first detect and count the rising edges of a WS2812B LED data signal, and then after a certain amount of bits have been counted, pass the remainder of the signal through to an output pin of the Arduino, before resetting and beginning the process again after each Treset?

So, for example, after each Treset, a 72 bit W2812B data signal reaches the timer pin. After the first 24 bits have been counted, the remaining 48 bits would be passed through (or perhaps even bypass the '328 externally) to an output.

Sorry if this is muddled, or I am not thinking about this correctly, or even if I haven't supplied enough info, but I really don't know what I'm doing here! Any help at all would be greatly appreciated.

WS2812B latest manufacturer's datasheet: http://www.world-semi.com/DownLoadFile/108

thank you for your time.

This seems a classic XY problem. You have a solution to a problem and you want help with the solution, but we don't know the problem. So it is harder to help.

Sounds tricky and certainly would involve the timer peripherals as you suggest.

But why, tell us. It looks like you want to duplicate an existing strip’s response to its signaling, but cut out the first of three pixels in your example. Assuming RGB.

If so, it would be easier just to

a) tap into the data line downstream where you want the secondary duplicate to begin or

b) use an extra pixel to absorb the one you aren’t interested in seeing, wrap it in something opaque…

Either method would apply for skipping the first N pixels.

But it can’t be that simple, so I say again tell us what you really up to there scratching your head!

a7

Ah I see, let me try again.

The IC chip on a WS2812B RGB LED module uses the first 24 bits of source signal it receives to inform the brightness of each LED (Red, Green and Blue) in that cycle, it then deducts this from the original signal and passes the rest through to the next WS2812B module and then resets after each Treset (sustained low voltage) and the cycle begins again.

Not paying any attention to the lighting of any LEDs, only the operation on the source signal, I would like to know if it is possible achieve almost exactly the same thing the integrated WS2812B does using an ATmega328P, only rather than deduct 24 bits of data from the source signal at a time, deduct many multiples of 24 bits of data in each cycle.

Is that a better way of putting it?

Thank you for taking the time.

alto777:
Sounds tricky and certainly would involve the timer peripherals as you suggest.

But why, tell us. It looks like you want to duplicate an existing strip’s response to its signaling, but cut out the first of three pixels in your example. Assuming RGB.

If so, it would be easier just to

a) tap into the data line downstream where you want the secondary duplicate to begin or

b) use an extra pixel to absorb the one you aren’t interested in seeing, wrap it in something opaque…

Either method would apply for skipping the first N pixels.

But it can’t be that simple, so I say again tell us what you really up to there scratching your head!

a7

Ok, so the data signal itself cannot be edited because before the signal reaches the arduino, there is a split to another set of LEDs which require the full signal.

The three LEDs example is just that; ignore it!

In reality I would like to remove 16 LEDs worth of data at a time before sending the signal off to yet another set of LEDs. I already have a crude solution to my problem; cram a 16 LED strip into a project box and run the signal through it lol, obviously this is fairly bulky and runs dangerously hot.

I am looking for a more elegant solution which would ideally fit snuggly in the back of a computer case and not burn anything to the ground!

Still a bit muddy. It's tired and I am getting late…

Hand draw a diagram as best you can of all your strips and what you are trying to do, including the way your crude solution would solve your problem.

Not sure what flunks the "tap into the data downstream" idea. Maybe you are throwing away 16 pixels worth of data that you never need/want to have pixels for?

And I don't think it's a particularly crude solution, haha. Sometimes you must go with what works. I am surprised to think it would generate dangerous heat, wait I guess 5 watts if they are all always full on could add up in a small enclosure, sure. It would take some volume, though, true.

a7

Just forget everything you think you know and start from scratch. There isn't any combination or arrangement of NeoPixels that you can't control using standard connections and software methodology.

The way to "deduct" LED signals from a chain, is to not send them out in the first place. If you can't change that, just paint the LEDs you don't want to see black, and hide them. They're considerably smaller and cheaper than a Nano.

16 LEDs worth of data is 16 x 3 x 8 bits of data, yes?
Maybe a cooler (less heat) way to do that would be to use a bunch of WS2811 with No LEDs attached. You can buy those as a string and remove the LEDs.

Or send them 0-0-0 so the chip is powered, but the LED is not lit up.

Do you have control over the source of the signal for the LEDs? Do both sets of LEDs need to be synchronized so that they receive the signal at exactly the same time, or can they be driven alternately?

If you are really intent on doing it like you describe, then use something like an attiny25, after Treset count the falling edges until you reach the correct multiple of 24, then output a signal to an external logic gate (such as a HIGH to an AND gate) that gates the LED signal through to your LED strip. You may be able to do it entirely with just the attiny25, but the timing is fairly critical and may require some assembly language to make sure it is within specs.

I am still unclear, (as mud), what the OP is trying to do.

major_major:
Ah I see, let me try again.

The IC chip on a WS2812B RGB LED module uses the first 24 bits of source signal it receives to inform the brightness of each LED (Red, Green and Blue) in that cycle, it then deducts this from the original signal and passes the rest through to the next WS2812B module and then resets after each Treset (sustained low voltage) and the cycle begins again.

Not paying any attention to the lighting of any LEDs, only the operation on the source signal, I would like to know if it is possible achieve almost exactly the same thing the integrated WS2812B does using an ATmega328P, only rather than deduct 24 bits of data from the source signal at a time, deduct many multiples of 24 bits of data in each cycle.

Is that a better way of putting it?

Thank you for taking the time.

As an experiment, I'd probably run the WS signal to a tri-state buffer (e.g. a 74xxx125 or 126). The input to the buffer would also be fed to the input capture pin of the Arduino. The output enable of the buffer would be tied to another Arduino GPIO.

At it's most basic, I think you'd want to interrupt on both edges, a high-low pulse representing a single bit.

On the falling edge, tick a counter. When the counter reaches you desired value and data is low, set the GPIO to disable the buffer. Count however many more pulses you want to "block" and then set the GPIO to enable the data path again.

A pulse for a '0' bit for a WS LED is just 400nS so your ISR would have to be very, very speedy, perhaps even written in assembler. You'd have to experiment to see how fast a full ISR could execute (including overhead like processor latency, the register pushes and pulls that are a "hidden" part of an ISR.

You might also do the same thing with polling -- if that's all the Arduino would be doing -- since you're only looking for complete pulses and aren't really interested in their width. The reset pulse is the only one you'd need to consider differently.

It sounds like you have two strips. One of 16 + some more LEDs, the other just some more LEDs. The two strips should be lighting up the same, except for the first 16 LEDs.

To do this, you could simply split the data signal after the first 16 LEDs. So both remaining bunches of LEDs get the same signal.

If I misunderstand something, do post a drawing of what you try to achieve.

Another option, if you are programming the board the drives the LED strips. Flip both strips over lengthwise and drive the signal from the opposite end. That way you can just let the extra bits fall out the end of the shorter strip.

Hello everyone,

So to help clarify this problem of mine, and add a little much needed context, I have taken Alto777's advice and created a diagram. Hopefully this clears up all the mud sloshing around this post!

You can find the diagram here, I'm having trouble attaching it directly to the post...

Imgur

1. The signal source. This comes from a proprietary commercial program which can only edit the signal superficially (change how many LEDs of data is supplied, and which colour the LEDs should be). The interface is a hub for distributing the signal between many RGB devices. I should mention, it is intended for RGB devices that enthusiasts use to customise their PCs.

2. The grey box with hatching represents a port on the hub. Each port has 5V supply voltage, ground, data in, and data out. In my diagram, only the path of the data is depicted, although there will always be a 5V line and a ground with it. The red line with hatching represents a connector to my module. You may notice another connector over at the RGB device near [3]. It is worth noting now that I can only modify, and am only interested in modifying, anything that comes between these two "connectors", as everything outside of them is impossible to modify or is subjective to my aims.

3. Commercial RGB device (Case fan, LED strip, GPU block etc). A few important things: this device, no matter what it is, will never have the means of returning a data signal, and it must receive the signal exactly as it passed through the port.

4. This is the heart of my problem (I'll discuss the overarching goal of the project later). It shows my current solution of cramming 16 WS2812B into a 4cm x 2cm x 1cm project box, just so each IC can deduct its 24 bits of data from the signal. I don't even require them to illuminate, although they do, and use power and create excessive heat! I am searching for a solution which will deduct all 16x24 bits from the data signal, fit in roughly the space of a Pro Mini, and not use silly amounts of power.

5. The data out (or in? Perspective.) will continue back into the hub and onto the next port where it becomes the source signal for this same process. Herein lies the ultimate aim of my project. If this process is repeated for 6 RGB devices, those 6 devices will be supplied their own unique 16 LED signal, or rather 16 x 24bit sections of the original signal issued by the source software. This means every RGB LED on each of the user's devices could be controlled individually using the software, allowing the user to maximise customisation. This is in contrast to a regular splitter hub, which only splits the same source signal to each device, making all devices display the exact same lighting effects.

Oh, and you might be wondering "Why 16 LEDs?" Well, it is a significant figure, but I can't give it away here; as you may have guessed, this is a commercial venture! Besides, it is of no relevance to the specific question I am asking, it could be any number.

On this subject of commercialism, and not to ride roughshod on the integrity of the good name of the Arduino Forum, I know this really isn't the place foir this, but I am a complete beginner here, whatever solution I do land on, it will take me a very long time to learn how to implement it. If someone would like to take a more active role in developing a solution with me, I am open to discussing the possibility of hiring them for the gig.

Hopefully I'm being understood a bit better now. And thank you to the other responses too, I'm investigating those suggestions too!

Thanks,

Graham

  1. This is the heart of my problem (I'll discuss the overarching goal of the project later). It shows my current solution of cramming 16 WS2812B into a 4cm x 2cm x 1cm project box, just so each IC can deduct its 24 bits of data from the signal. I don't even require them to illuminate, although they do, and use power and create excessive heat!

This was solved in reply #7.

OP's diagram:

aarg,

I did consider that solution, but it will not work. The LEDs (or rather their IC controllers) on WS2811 strips are just too sparse. The strip of WS2812Bs that is stuffed in that tiny box just now is 144 LEDs per meter! They only just about fit, there's no way I could fit a strip with lower LED density in there. The box they are in is as large as is feasible for its purpose.

I do have a roll of just the WS2811 IC controller chips by themselves. I considered making a little stack of sixteen and just connecting Din to Dout through the stack, but soldering that would be a nightmare.

The perfect solution for this approach would be a high density presoldered strip of only WS2811 ICs, although I highly doubt such a thing exists... Maybe a cursory search of Ali Express might turn something up lol

Here's what is frustrating me though: How does a '328 have such a hard time imitating a task the much smaller and I presume slower LED IC can do with ease?

Thank you for your time. And thank you david_2018 for publishing my diagram to the thread.

Why would you use them on a strip? If you are making a commercial product, you could place 16 WS2811 on a small custom circuit board. For prototyping you could use these:
https://www.aliexpress.com/item/32886944385.html

How does a '328 have such a hard time imitating a task the much smaller and I presume slower LED IC can do with ease?

Because the 328 is a general purpose MCU that has to do most things in software, and the WS28xx are special purpose IC's with dedicated circuits that use fixed logic arrays to process digital information. They don't have to be smart because they only do one simple thing, but do it well. The main problem in emulation is that the WS28xx protocol timing is fast, and data must be sent almost continously, there isn't enough time to easily calculate memory indices to the buffer and so on. It's hard to do even in pure assembly language.

Now add the requirement that it decode at the same time as encoding, and the answer is, "no way". You might be able to do it with another processor, for example STM32x, because it is much faster and has more sophisticated timer options than the AVR.

aarg,

After I wrote that last comment, having joked about checking Ali Express in case they have something, I took a punt and found that exact board you have recommended.

I actually think this is the solution. I presume the Dout pad, is just the flip side of Din (Only Din is marked on the PCB). If that is the case I think we may have a winner here.

And thanks for that explanation. That makes sense.

Again thank you for taking the time out of your day to help me.

major_major:
Here's what is frustrating me though: How does a '328 have such a hard time imitating a task the much smaller and I presume slower LED IC can do with ease?

That's simple. Dedicated IC vs general purpose microcontroller. That WS2812B is designed to do one thing and one thing only, so the whole "coding" is done in hardware. There are MP3 modules (DF Player Mini) that can decode and play back stereo music that cost less than an Arduino, which can't even handle low quality sound.

Now for your original question my suggestion (and it will fit easily in your case) is to take an ATtiny, connect the data signal to one of its inputs, and read it. Separately connect it to a 74LVC1G126 non-inverting, tri-state buffer. Keep the buffer disabled, look for a start frame (the first LED), and start counting - the moment the counter has received the appropriate number of bits sent enable the buffer output and now you can let the data pass through.

That will still not solve your problem as the data now will say "Hi, this frame is for LED #17!" as it is expected that by the time it has passed through 16 LEDs this has changed to "Hi, this frame is for LED #1!" and the 17th LED will notice it's for them, and use it to set its colour.

So indeed not only should the MCU read the signal, it has to change it accordingly, pretending there are 16 LEDs in the chain before it. The change part is probably pretty straightforward, the reading part not so much as it's a 800 kHz signal, so even at 20 MHz that's just 22 clock cycles per bit. Within that time you have to detect high/low time and based on that deduce whether it's a 1 or 0, and write it to memory. Based on these old threads, it may be possible if you write your code super optimised in assembler language.

To do something useful with it, you would separately have to write it out again! That takes even more clock cycles... The threads I linked to suggest the ESP8266. At 160 MHz that would stand a chance, but the chip's precision timing ability is not good. A teensy is another candidate, the 4.1 runs at 600 MHz. I have no experience with those boards yet.