Pan tilt hat - ws2812 ring not working


16 led ring works fine on arduino, but only sets 3 or 4 pixels when running on pantilthat. (and even then it is random colours not the ones you have selected)

I see other complaints about this elsewhere here, so looks like it has not been solved.

any progress on this?


Is this the 12 or 24 pixel ring? Have you tried it directly on the Pi with the Unicorn HAT library- it should, in theory, work.

I’m not convinced there’s anything wrong with the PanTilt HAT. And I’d hope there isn’t, since the code to drive the WS2812s is baked into the firmware and thus is impossible to change.


guess it could be that your hat does not support the older 2812 led’s as opposed to newer faster 2812b leds?

only way to test that is with a 2812b strip I guess


I’ve opened an issue on github for this problem.
I’ve tried everything I can think of to get a strip of 8 standard RGB ws2812b LEDs to work as a pan tilt light. But unfortunately it just doesn’t want to play. I just see a few LEDs flickering apparently random colours, although I’m pretty well convinced it seems to be sending too much data and the LEDs are just getting confused. I’m doing a set all to 255 red, everything else 0, and it seems to flicker certain LEDs from red to green to blue, which makes me think that the LEDs can’t interpret the data properly. Or maybe they are resetting all the time? Other people have suggested that RGBW strips do work, which might suggest that RGB LEDs won’t work if the hat only ever sends RGBW data, regardless of the config settings.
I haven’t got a scope to look at what’s being sent on the light data pin. Is there a way to analyze it using the pi itself, maybe connect the data pin through a logic level converter to a gpio pin?


like he said, (but kind of denied) burnt unchangeable code to a set of pan-tilt hats… just rgbw works now…

Stuff messing around with it! though i’d appreciate just a new board with corrected firmware…


Do either of you have a Unicorn HAT or Unicorn pHAT? Both of these work for me.

@skypi when using your LED ring with Arduino are you using NEO_KHZ400 or NEO_KHZ800 speed?

The Pan Tilt HAT is, indeed, fixed to one speed. In fact the whole NeoPixel update routine looks like this:

                    static uint8_t pixel, j;
                    for(pixel = REG_WS2812; pixel < NUM_ELEMENTS+REG_WS2812; pixel++){
                        for(j = 0b10000000; j != 0; j>>=1){
                            if(_i2c_slave_get_regs(pixel) & j){
                                WS2812_LAT = 1; 
                                WS2812_LAT = 1; 
                                WS2812_LAT = 0;
                            } else {
                                WS2812_LAT = 1;
                                WS2812_LAT = 0;

Could you link me to the LED ring you’re using and I’ll see what I can do.

@skypi I had to take some liberties with your latest post- I appreciate your frustration, but please avoid swearing.


All of our Pan Tilt HATs are actually tested on a jig with a 24 pixel NeoPixel ring installed. However I tried a 12 pixel ring I found in a box, and it just wouldn’t work.

It appears like APA102s, not all WS2812s are created equal. And certain brands/variants are more forgiving of deviation from the protocol.

It’s really finickity to get an accurate representation of the protocol on an 8bit PIC at 16Mhz - but there’s a fair amount of leeway

I’ve hooked up my oscilloscope, unrolled the loop (which I shared above) and made some very minor timing tweaks to the off bits.

It now seems to work with my test 12 pixel NeoPixel ring, while still working with the RGBW sticks and the 24 pixel ring on the test jig.

It is really close to the limit though. Assuming a definite logic HIGH level of 0.7*VCC, the HIGH pulse for a 0 bit is now just scraping 250us, which is the lower limit of acceptable timing.

At this point, I wouldn’t be surprised if the clock accuracy on the PIC itself caused some bits to be misidentified.

I could push this as a new firmware for all Pan Tilt HAT boards from this point- but since there’s clearly a fair deal of variance in WS2812 LEDs I can’t make any guarantee that it will work with all possible variants. Even boards we’ve tested and list on the product page could change their part supplier and suddenly not work.

This is one of those things that’s just complicated- a PIC15F1503 is ill-suited to driving WS2812s. I added it in as a bonus feature to avoid the pain and inconvenience of using the Pi itself to drive LEDs. It will never be perfect.

@skypi - you could tap a wire off BCM18 (marked as PWM on the Pan Tilt HAT) and try your luck running the NeoPixels using the rpi-ws281x library. (just run the Unicorn HAT library to test, and then go from there)


OK thanks for the testing, it’s just a cheap chinese ws2812 (probably not a 2812b) ring, I’m using the pololu library on arduino so not sure what speed that is driving the led rings at. I am not that bothered about it, I was guessing you had tested it with the modern stuff you sell.

I have got to stop cursing!


I ordered and received (from Pimoroni Deutschland) a nice Adafruit GRBW stick, which is the one featured in the build tutorial. It works! (When you correctly update the library to the latest version!)

My ws2812b neopixel strip (also Chinese no name) does not work.
Those ‘neopixels’ DO however work on the following:
BBC micro:bit
Codebug (a PIC18F25K50!)
Adafruit Trinket M0 with circuit python (1)

I’m calling it done because, to be honest, fiddling around with camera extension cables and the led problem have literally taken the shine off the whole thing.

(1) My neopixels didn’t work with circuit python 2.0.0 out of the box, because Adafruit built a bug-like feature into the default demo, which I finally found and my strip sprang into life!