Flashing LEDs problems with the Blinkt! HAT

Hello everyone,

I’m having a few problems with my Blinkt! HAT since yesterday. I’m using the provided C library and wanted to test how fast I could turn the HAT on or off, maxing out my Pi Zero at 50% CPU Usage while the LED-Strip first blinked slowly and then stopped at some point.

Since then, sometimes when I call show(), some LEDs don’t update correctly. This is way more likely for the ones further to the right (higher index). Sometimes they just turn off, sometimes they flash very brightly in a completely different color. If I call show() multiple times, it works 99% the second time. This is very annoying as it makes the LEDs flash at random if I update the strip continuously.

I guess that this isn’t normal behavior and that I broke it somehow by updating it too quickly? Or does this always happen? And is there any fix (other than my workaround of calling show() 5 times in a row)? Or do I just have to live with it or buy a new one?

Thanks in advance!

I can’t say 100% that its broken but it sure sounds like it. I’d try one of the python examples as a test.
blinkt/examples at master · pimoroni/blinkt (github.com)

CPU load maybe, that cycles the LED’s quickly. I have a Blinkt and haven’t seen the behavior your seeing.

Wow, to my surprise the examples do seem to work. I’m gonna test around a bit and will try to get some basic code to work with the c library. If that doesn’t work, then I guess the library is buggy? Maybe I need to insert delays after each write/send because the python code is slower as well, so that will make it more similar?

Edit: I tested the C library now and at first it seemed to work, but when I set the brightness to 1 I got the same problems again. The following is the code I tried:

#include <stdint.h>
#include "blinkt.h"
#include <stdbool.h>
#include <unistd.h>

int main() {
	start();
	while(true) {
		for(uint8_t i = 0; i < 8; ++i) {
			set_pixel_brightness(i, rand() % 2);
		}
		for(uint8_t i = 0; i < 8; ++i) {
			set_pixel(i, 255, 255, 0);
		}
		show();
		usleep(1000 * 500);
		for(uint8_t i = 0; i < 8; ++i) {
			set_pixel(i, 255, 0, 255);
		}
		show();
		usleep(1000 * 500);
		for(uint8_t i = 0; i < 8; ++i) {
			set_pixel(i, 0, 255, 255);
		}
		show();
		usleep(1000 * 500);

	}

}

This really pronounced the bug and only about 50% of the leds are now on, switching after each loop.

For reference, this is the python code I tried:

#!/usr/bin/env python

import time

import blinkt
import random

blinkt.set_clear_on_exit()

step = 0

while True:
    if random.random() <= 0.5:
        blinkt.set_brightness(0)
    else:
        blinkt.set_brightness(0.1)
    
    blinkt.set_all(255, 255, 0)
    blinkt.show()
    time.sleep(0.5)
    blinkt.set_all(255, 0, 255)
    blinkt.show()
    time.sleep(0.5)
    blinkt.set_all(0, 255, 255)
    blinkt.show()
    time.sleep(0.5)

Which actually does seem to work.

Here is a picture I took while running the C Code:

Does the C Code work for you? Or is my Blinkt! really broken?

I have never used C with my Blinkt. I only use C when I have to, like with my Arduinos. I’m not knocking C, its just that I have zero skills with it.
I can likely try your C code latter on today though. I’ll go get my Blinkt out of storage and hook it up to a spare Pi. What IDE are you using?

Hey, first, thank you for trying to help me😄. I mainly use C/C++ because I just like using it more, there’s not really a good reason. And it’s nice to know that your Pi doesn’t have to do a lot and you can easily still update it without it being slower than it already is while updating. And it’s easier to use C/C++ with Buildroot, which I originally used on the Pi.

I just typed the Code in vim, so any text editor should do.

First, you need the bcm2835 driver, because that’s what the Pimoroni library uses internally. Here’s a short tutorial on installing it which I used: Install BCM2835 Library in Raspberry Pi - TechWorked

The gist is:

cd ~
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.58.tar.gz                
tar xvfz bcm2835-1.58.tar.gz             
cd bcm2835-1.58                       
./configure
make
sudo make install

When that’s done, you need to clone the GitHub repo from Pimoroni (GitHub - pimoroni/blinkt: Python Library for Blinkt; 8 APA102 LEDs for your Raspberry Pi) and go to the folder library_c/lib. There you create a file there named test.c which contains the above-mentioned C-Code. You can compile the whole thing with

gcc test.c blinkt.c -o demo -lbcm2835

Now you execute ./demo which should in theory make all the LEDs flash simultaneously in different colors at random. You can try the Python code I posted above to see what should happen when you run ./demo.

Thanks for the info. Might be a day or two before I get too it though. I have a bunch of errands to run today.

So, I’ve been experimenting around a bit more and it gets weirder and weirder…

First, I noticed that I made a mistake in the C code and that it behaves exactly as it should after I fixed it. Then I tried a bit more stuff and noticed that actually everything works in C except for my original code. My original code connects to mqtt and received commands from the broker on what to do. If I run that, I get problems.

Then I thought that might be because of interference between wifi and spi, because the commands are sent over wifi. But after I attached an ethernet usb dongle and disabled wifi it still didn’t work. I tried the mqtt example from pimoroni and that does work, though it’s much slower than my code because it’s python, so I thought that’s maybe the reason. But even after I added some delays here and there I still had the same problems.

Now I’m trying to use a different MQTT library instead of my handwritten one, though it’s hard to imagine that that’s the problem… Maybe it really is due to some sort of interference, I have a Pi 4 in use that I could probably borrow and test if the code works there. If you (or anyone else) has any other ideas, please tell me.

I’ll post here once I find a solution in case someone from the future finds this post on Google because they have the same problem.

TLDR: You don’t need to test my C example anymore, the code I posted is broken and the fixed one works. I’m now experimenting around a bit to find a solution.

Okay, so I tested this on the Pi4, and it actually works perfectly! I can run it over mqtt at insanely high speeds, the fastest I tried is changing all LEDs at 1000Hz (at which point you can’t really seem them blinking anymore). At 100Hz, I only have like 10% CPU usage and everything works as well. So my Blinkt! isn’t broken but there does seem to be some sort of interference between the Pi Zero’s SPI and the Blinkt!. I’ll try to look around a bit more to try and fix this, but to be honest I don’t really know where to start :/

So, I got it working! As it turns it, my Pi Zero W seems to be (at least a bit) broken. I plugged the SD card in another Pi Zero W and my previous problem now happens only 1% of the time when the Blinkt! updates (instead of like 20%). I don’t know in what way or why my other one is broken, maybe it’s just an older firmware, but as everything (mostly) works now, I’m considering this done. I can probably get this to work completely if I just switch to a Pi 3A and I’m actually considering doing that.

I’m leaving this topic open in case anyone has a any idea on how to fix this problem completely for the Pi Zero W.

Thank you @alphanumeric for your help!

You did all the work lol. I do appreciate the feedback on what you did etc though. It really helps if somebody else has a similar issue.

I have a bunch of 3A+'s in use here. I have camera setups running Motion Eye OS. Two have the Pimoroni Pan Tilt Hats on them. A Pi Zero just wasn’t up to the task. I went with a 3A+ because all I use is the WIFI once they are all setup, and I can do my setup with just the one USB port. They run headless so smaller is better, and they use less power. The big thing for me is its a nice cost saving over a 3B, and only slightly less performance. IMHO its a great value especially for headless setups.

Yeah, the 3A+ does seem like a really nice Pi, I ordered one a few days ago for a LED matrix project. I’m quite excited to see what it’s like. I’m pretty sure that they should work with the Blinkt! without any modifications as well.

And I finally fixed the Pi Zero problem completely!

I noticed that it got worse and worse again with the new Pi Zero, and at some point it was all just a giant unicorn-colored mess. So I started looking around the driver a bit again and I remembered that the Python driver is a bit slower, you can actually see it turning one LED on after another, but not in the C version.
So after some experimenting I modified write_byte to the following:

inline static void write_byte(uint8_t byte){
	int n;
	for(n = 0; n < 8; n++){
		bcm2835_gpio_write(MOSI, (byte & (1 << (7-n))) > 0);
		bcm2835_gpio_write(SCLK, HIGH);
		usleep(1); // This line is new (you also need to include unistd.h)
		bcm2835_gpio_write(SCLK, LOW);
	}
}

And now it works! It has now the same behavior as the python driver and you can even see it turning the LEDs on with a slight delay. Sadly this does decrease the maximum refresh by quite a bit down to about 33 FPS, but that’s still perfectly usable and way faster than the Python version.

I’m pretty sure that although usleep(1) should only sleep 1 microsecond, it sleeps like 500µs because the Pi Zero’s CPU isn’t that good at timing stuff. You could probably get higher refresh rates if you have some stupid loop there that takes exactly as long as required for the Blinkt! to notice the HIGH and LOW.

1 Like