WS2812b Success on the ESP-12

This one has been long in the making. I’ve had a fair bit of success with the little ESP-12 and it is now my favourite despite the 2mm centres.

Why, because it HAS everything – lots of port bits, A/D convertor etc. why on EARTH we all went off and used the little ESP-01 I can no longer understand especially as the ESP-12 is the same price!

Ok, so getting ports on and off was no big deal and even reading them was simple – but getting the timings right for the WE2812b LEDs has been a pain.

I eventually found a blog (all of this is referred to in the comments section of a blog a couple of days ago in here) which detailed how to use the WS2812b. Then I found a guy saying it was no good – and offering his slight modification – and I tested it and.. lo and behold – on GPIO0 it works.

But could I HELL get it to work on other ports – as I was stumbling around in the dark as to how to use the PORTS – the problem is timings – the WS2812b need VERY short pulses and they are not very forgiving if you don’t get the timings right. There are LOADS of ways to turn ports on and off on the ESP8266 but they all take differing times and if the port operation is part of your (very tight) timing – then any change will stop this from working.

Here is the original code that worked – on GPIO2 - this is just the bit for individual pulses and is commented out

So you see, that statement WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 ); is an integral part of the loop timing. Can’t go messing with it… but here’s the thing – this UTTERLY MEANINGLESS gook is actually incredibly simple…

Taking the first one it is this..

(*((volatile uint32_t *)(0x60000300 + (0+(0))))) = (uint32_t)(1)

and narrowing that down it is simply..

*(0x60000300)=1

Ok, so this made NO sense to me AT ALL…. until I hit THIS link thanks to one of you kind people.

It turns out that there are two magical locations on the chip – which I’m now using to turn things on and off. They are 0x6000304 to turn things on and 0x6000308 to turn things off – go ahead and define pretty names for them. This is weird. If you fire a 32 bit number at these locations – the first one will turn on any port who’ bit is HIGH while ignoring the rest. The second address does the same to turn them back off.

So if you consider binary 1 to be GPIO0, 2 to be GPIO1 etc etc this makes sense.

These two lines will turn the port 12 (GPIO12) on then off VERY, VERY quickly.

Weird, yes, FAST, certainly. Now you might say well that’s all good for one port but what happens if I want to use another port – well as long as you don’t want to handle them at the same time, it turns out you can use a STATIC variable and it appears to work just as well!!!

So – enough bull – here’s some code. I do not claim ownership – little bits are mine, little bits are from other people etc… well done to all I would say.

Now why do I have REDA and RED - well I don’t want these lights instantly changing colour – that’s boring – I want it to happen in the background – so – make yourself a 50ms timer callback and dump this inside.

/// rgb to fade from any colour to any other colour for any number of LEDS for any given period (rgbdelay)

if ((red!=reda)||(green!=greena)||(blue!=bluea)) { uint8_t myBuffer[3]; if (reda<red) reda+=((red-reda)/(rgbdelay*20))+1; if (greena<green) greena+=((green-greena)/(rgbdelay*20))+1; if (bluea<blue) bluea+=((blue-bluea)/(rgbdelay*20))+1; if (reda>red) reda-=((reda-red)/(rgbdelay*20))+1; if (greena>green) greena-=((greena-green)/(rgbdelay*20))+1; if (bluea>blue) bluea-=((bluea-blue)/(rgbdelay*20))+1;

I’ve only allocated 3 bytes for the RDB buffer as I’m not interested in individual colours – just changing them at once – and I repeat the whole thing by rgbnum – the number of LEDS and rgbdelay the time you want this to take to change from one colour to the next. It will do a nice job and smoothly without any horror colour changes – basically for each colour if the desired colour does not match the actual colour, adjust it by 10%.

oh and you’ll need this table… I found that on the web too. It’s simple enough – note that increasing values have little effect at first, getting more and more relevant as you get higher up. That’s because the difference in brilliance between 10 and 20 is large, the difference between 240 and 250 is almost zilch – to our eyes anyway.

So this is non-lossy –as the colours fade down, colour accuracy goes down but as you fade them back up it returns.

Oh, you also need to ensure that the output you use is actually an output!!!! So why are you waiting – moodlighting – SAD LIGHTS --- I’ve not tested more than 30 LEDS so do some tests before going wild.

Another thing to note – avoid the callback fading starting while the WIFI is setting up… I found using this immediately at startup caused issues – once you have connections it’s fine.

When I first played with this a month ago the compiler flags got in the way, no optimisation it was too slow, optimisation on it was irregular. I can only say that I have made NO changes to the basic setup - and it is working. I'm not yet an expert on the compiler optimisation so you'll have to play it by ear.

pretty much does the same thing, just uses a different way of writing to the register. this works well but some colours are a little off. I havent looked at that too much yet though. should just be a matter of tweaking some timings.
I also have an issue with the first LED being white regardless of what I send

I think Peter has cracked it and will let us know the solution when he gets some time. ( always on holiday by the sound of it! 🙂 NOT.
In the meantime the solution I have is that of getting rid of the first 32 bit stream, and adding an led count to the number sent out.
In the same way as controlling the output level, the port setting ( Input / Output) can be set.
For the first 32 bit out I make the Pin used an input, so the same routines are followed, but whatever it is causing the issue gets sorted, then from that point out it's set as an output.

In the while repetition loop I do an 'if else' on the repetition value so that the first output block gets the call WRITE_PERI_REG (PERIPHS_GPIO_BASEADDR + 20, 0x4000); [that's the PIN_DIR_INPUT reg and in my case pin14 0x4000). This sets it as input. (Pulldown required).
Then all other blocks get ....WRITE_PERI_REG (PERIPHS_GPIO_BASEADDR + 16, 0x4000); that's the PIN_DIR_OUTPUT reg.
Again only "1" bits written have any effect. Might help in order to play with the strips, whilst waiting for the real solution.
I do have an issue with 14 as an output due to there being quite a heavy pullup somewhere which I can't get rid of as yet. Always more to find out!

Not to do with the WS2812s, but I think most of the people who hang out here will be interested to know that Martin Harizanov has published his latest ESP work on GitHub. His build has httpd, mqtt, ntp, ds18b20 and dht22 all rolled in, with web-based configuration for just about everything. So if you boot the ESP with his code and then connect on port 80 with a browser you can, among other things, change the IP address and reboot the ESP to have the change take effect. There's also a very nice scheduler page for setting up daily times during a whole week for heating and cooling on/off points. This is really worth a look-see.

First, thank you very much for helping a devout Assembly programmer, and VB 6.0 programmer (don't laugh it still works great for my stuff) actually understand what you have done with C. Your coding methods and comments are very clear.

Regarding the WS2812b propensity to have the first set of RGB pixels rather flaky I have some in depth experience with that issue even with PERFECT timing.

I, like many, use these devices for large Christmas displays synchronized to music and send images to them in rapid succession.

The manufacturers of the various Christmas Display controllers for these lighting displays give the ability to null out the first set of RGB pixels as they fight this problem but not because of the controller timing but because of the waveform presented to the WS2812b strips, which YES does alter that once perfect timing.

Even with a controller producing perfect timing, usually the cables from the controller to the WS2812b add inductance/capacitance to the data line causing the rise and fall times to be rather soft and not nice and crisp.

However, the output circuitry of every node in the RGB string of WS1212b will recondition the data signal such that even with soft edges or some ringing from the controller --> 1st Pixel the next RGB pixels will receive nice clean rise/fall edges. This signal conditioning continues with every subsequent RGB set of pixels regardless of the number of RGB pixels.

In one of my MegaTrees with 16 strings and over 6,500 pixels, I had to null the first set of pixels in every string simply because of my cable lengths.

Great stuff you have created and I will be using the ESP8266's and WS2812bs for lighting similar to what you have created as mood lighting for my Pipe Organ console lights.

I would never have a go at a VB programmer - used it for many years myself. As for cables I did wonder about that and I have kept the cable from the ESP to the LEDs short, maybe 0.5metres. But then as the unit itself is WIFI there is nothing to stop you doing that.

That is a good point about the first LED and I will do some tests with longer cables - it should be trivial to do a check for the first pixel (a flag) and zero out the RGB component.... but up to now with the current software I'd not seen any issues.

Hi all,
I just found this blog, while searching and lookng for experiences, to take control over my first try of a 10x ws2812 LED stripe with an esp8266 nodemcu.
I found lots of ressources. But frankly speaking it very seldom to find something to just download and let go. Its very hard to search and tinker a running project together. Or to let an as "runnable" advertised code really run. Also in this blog, the c-code is distributed in serveral posts, with important pieces missing-. No chance for me to get a conistent pice.
I also found CNLohrs examples but they did not compile under my just set up eclipse-mars environment. Even that i followed all instructions very carefully.
The only trivial thing, which worked from first try for me was http://www.instructables.com/member/sabas1080/
Even that I cant read spanish, the offered arduino skech ran in seconds.
Can someone provide a complete code of this blog?
Is there a library using DMA for ESP8266 for ws2812?
Or better a load-and-go example for the ESP8266 Arduino IDE? Or even better for Eclipse-Mars?
Sorry for my unhappyness from my first tries.

Comments are closed.

Welcome to the Blog

Hi - I'm Pete and this is my technology blog. It is BIG. It is also the home of "ESP-GO". "The Script", Node-Red-Contrib-Bigtimer and many other useful toys. Use the search box below or check out the archives and other links below - be sure to SHARE what you like using the social media buttons and please subscribe to my YouTube channel http://www.youtube.com/PeterScargill

Please register or log in - the top menu changes a lot when you are part of the party... and once in, don't forget to tick the box so you will get email follow-ups to comments.

If you want to buy me a coffee or help fuel my gadget habit, use the Paypal donate link below.

Disclaimer: Because I have no idea of your level of technical skill or the requirements of your country laws in terms of electricity supply etc., I accept no responsibility for any damage caused through following advice in these pages. When dealing with mains voltages you should satisfy yourself that whatever you are doing is safe and if unsure, seek advice from someone who is sure.

Notice: I'm always happy to offer advice on stuff I've written - and indeed take advice. If I can help in any way just let me know but PLEASE don't ask me how to program in C/PASCAL/NODE/etc. There are many resources out there - if you want to program and can't - there's always Google.

Search for:

Email Newsletter

Enter a name and your real email address if you would like to receive occasional summary emails - sorry but invalid-looking or automated names and email addresses will be removed to help protect others.

Links

EE Times | Electronic Engineering TimesEE Times connects the global electronics community through news, analysis, education, and peer-to-peer discussion around technology, business, products and design