I'm trying to do an ARGB controller without libraries, needed a code that i could completely control to keep implementing functions and could sync perfectly with another time sensitive functions too.
The problem is that high-level code have µs lags and i would need ns precision to output data to those WS2812B. That's beyond my current skills right now
ok, no more chitchat
This ̶c̶r̶a̶p̶ code is my current point with this, that's just the logic for me to follow and i'm working to otimize it to work faster and precisely.
I tried to implement direct port manipulation and a "delay" with timer1, but i think that's not nearly enough. Still need to implement a better way to check what bit to send, for an if will not work, i know.
//Send data in buffer (takes 225us for 4320b (3ch 60Leds))
for(byte aRGB_aux=0; aRGB_aux==1079; aRGB_aux++){
//Send bit 0
if(aRGB_DataBuffer[aRGB_aux]==0){
PORTD = PORTD | B00010000;
TCNT1=0;
while(TCNT1<=3){}
//delay(.4us @ 0)
PORTD = PORTD & B11101111;
TCNT1=0;
while(TCNT1<=10){}
//delay(.85us @ 1)
}
It will be tough to implement the WS2812 in C. You're looking at pulse widths that are only about 2 instruction cycles long; every implementation I've seen resorts to inline assembly language. (you can look at many of the existing drivers - they're open source.)
In general, each bit is 1.25uS long (20 cycles at 16MHz.) For a zero, you send less than 1/3 of that high, and for a one you spend 2/3 of that high, leaving you the final 1/3 of the time to get the next bit ready.
Does not the entire data stream for the strip more or less have to be delivered continuously, with small periods, leaving no time or opportunity for doing anything else?
There are smart LEDs that use data and clock lines, they might be easier to use if you need to interleave processor activity.
But this sounds like an XY problem. Would the OP care to explain the circumstnces that give rise to the need to look into this?
It absolutely does, for the WS2812B. Other chips, like the SK6812, have much more relaxed timing, as do many WS2812B clones and variants that are incorrectly sold as WS2812B (since they believe people are too dumb to keep track of other part numbers, apparently). So it's easy to do testing and reach the wrong conclusions unless you have verified parts.
I know this because I did extensive testing with the PIC and oscilloscope. The PIC happens to lack certain "tricky" instruction sequences that are possible on the AVR, that make it possible to index LEDS while their data streams are written out. But I found that the SK6812, while using the same data format, has a more relaxed inter-value interval, which makes it work. With the relaxed values, it's relatively easy to bit bang on almost any processor. But not using the actual WS2812. Also the data sheet for the WS2812B is a tricky one, the numbers are presented in such a way as to fuel arguments about what it says...
Many variants are sold as WS2812B because that's what people search for, but they don't have the same IC embedded.
The protocol is described in the WS2812B Datasheet. After RESET (at least 50us of data line LOW), each pixel consumes the the first 24 bits (1.25 us/bit) it sees. Any additional bits are ignored and passed down the line. Each pixel displays the new color after some (unspecified) delay once it gets its 24 bits.
Your math is more or less correct. Pixel #299 would change color ~8970 us (1.25 * 24 * 299) after Pixel #0 changes.
Yeah, would be tough or even impossible to get something below µs with C, at least with 16MHz. But i was looking at Pololu library and that can make WS2812 work even on 8MHz CPUs, so "should" be possible to implement something as amateur at assembly.
I'm looking into existing libraries too, already reversed engineered basic thing like BMP085 and DHT libraries, but those WS2812 are way harder to read.
Absolutely, i'm expecting that for 6~11ms/s the CPU will be sending data and nothing else. But in the remaining time the signal would be in reset state to implement anything else, as the rest of my coding is all timing friendly, that would not be a problem. I would have at least 999.980µs to do everything else i need, this if i don't leave a static color that i wouldn't need to refresh the data
I already have 5M of these WS2812 strips without use, buying another set of strips, even being easier to use defies the purpose.
I want to further upgrade my code to be able to receive ARGB or RGB data from a PC motherboard and send data to another ARGB or RGB controller while controlling a set of WS2812B strips, being able to "easily" read a VGA signal and doing some effect with the ARGB strip...It's all about being able to control how the driver works and how it will sync with other functions. Those timing friendly libraries that i found have some limitations cause it interrupts the program even when i don't need it to, and it's going to be a little harder to implement effects
I've had great success with PJRC's DMA WS2812B implementation. I can do audio-responsive LED displays with real-time processing on the 16-bit / sample, 2-channel stereo audio running at 44.1 Ksamples / second.
The Adafruit_NeoPixel library has very good comments about how they implemented the protocol, and exactly how many instruction cycles it takes for each bit. The actual code is in-line assembly, because of the necessity to very strictly control the timing, but they comment each line of assembly showing what it does and how many instruction cycles it takes to execute. Hard to understand, but I did go though it a couple of years ago to add an option for a 20MHz clock rate.
There is a maximum time the level can stay low (TxL) before a reset is triggered and any loaded data is latched and displayed on the LED.
which isn’t what I was looking for but seems to say the same thing I thought I knew.
The 24*300 data bits are clocked out without any markings of where pixels begin and end. Only the reset pulse between strip.show calls is not a 1 or 0.
Each neopixel accepts its 24 bits of RGB data, reshapes and firms up the data and sends the rest data down the line.
When the reset pulse is recognized, the latched data is transferred and at that time the pixel shows the new color.
So in my example, the last pixel changes 8 milliseconds after the start of transmission, but so do all the pixels in the strip, as it is at that time that they see the reset condition on the data line.
Modulo a slight delay in each pixel’s reshaping circuit.
So I infer they change very nearly simultaneously and that the change ripples quite fast from beginning to end in order.
Since it could work this way and would arguably be better if it did, I hope that it does.
I am not too lazy to do experiment… just not sufficient motivation yet.
Your analysis of turn-on timing down the string would be valid assuming the assertion that the reset period triggers color change rather than an individual pixel consuming its 24 bits. Please post the results if you verify it experimentally. The datasheet is silent on that subject. Not surprising as it supplies minimal details and what it has is written in Chinglish.
That’s an interesting find regarding the timing being more relaxed than commonly assumed. Regardless, I’ll probably stick to driving these strings via DMA from a PJRC Teensy. Especially since it can hook into FastLED and take advantage of all the color manipulation that library supplies. And, as the name implies, it’s very fast and efficient.
It is possible to drive the WS2812B with just PWM from timer1 of Arduino running at 16 MHz. As long as your OVF ISR to load the next byte into the RGB array doesn't exceed 50usec, you should be fine.