Blinkt get_pixel

I would like to be able to use get_pixel. I am using blinkt across zeromq with multiple systems (pi and x86 mint linux based). It would be nice to be able to read from one system what has been set by another on the blinkt device.

I notice that get_pixel appears in the blinkt.py on github, but it doesn’t appear to be present in the library.

p.s. where is the “Library” directory? So I can sudo python3 setup.py install (as per your docs)?
p.p.s It would also be nice to be able to write directly to the buffer without using show, but I can live without that (mostly, I think).

Thanx RichR

If you found blinkt.py then you’ve found the library directory ;)

Auto-update, as you suggest, is certainly possible but we usually favour updating individual pixels and then calling show. It’s more efficient in most cases, at the expense of a little more typing.

You could create your own set_pixel::

def set_pixel(x, r, g, b):
    blinkt.set_pixel(x, r, g, b)
    blinkt.show()

Thanks for a response, but maybe you didn’t see my first question?

It is GET not SET I have a need for, and cannot get it to work …

I already did the following (as long as it allows changes to individual
pixels it works ok - my test did work from different systems so far. ):

def ledClrAll():
for x in range(8):
blinkt.set_pixel(x, 0, 0, 0, 0.0)
blinkt.show()
return “done”

def ledSet(p,r,g,b,i):
blinkt.set_pixel(p, r, g, b, i)
blinkt.show()
return “done”

BUT :

def ledGet§:*
** blinkt.get_pixel§**
** return r, g, b, i*

the last one doesn’t seem to work, even though on Github I found a
routine that should work. But where does the library get installedon
the jessie system
?

Should the get_pixel routine work?

Scenario: I have three systems A, B, C.
B sets a pixel on Blinkt on A, and C wants to check the value of the
pixel on A and then maybe alter it… All this is using RPC via Zeromq
(which I have working reliably). Thus status can be communicated by
simple RPC calls across the network.

For this I would like to use get_pixel…

OK, I found it in :- /usr/lib/python3/dist-packages$ sudo nano blinkt.py

From Github, I added :

def get_pixel(x):
""“Get the RGB and brightness value of a specific pixel”""
r, g, b, brightness = pixels[x]
brightness /= 31.0
return r, g, b, round(brightness, 3)

my code now works as below:

def ledGet§:
return blinkt.get_pixel§

if name == “main”:
print(getTmp())
print(datim())
try:
while True:
for x in range(8):
ledSet(x, 64, 0, 0, 0.2)
print(ledGet(x))
sleep(0.1)
ledSet(x, 0, 0, 0, 0.0)
print(ledGet(x))
sleep(0.1)

Not sure if your code is not up to date, or get_pixel has been dropped,
or what happened?

The code in GitHub will almost always be slightly ahead of any releases via pip or apt, that’s just the way of things.

If you want the bleeding-edge you could have installed the GitHub version of the library as you mentioned. Something like:

git clone http://github.com/pimoroni/blinkt
cd library
sudo python setup.py install
sudo python3 setup.py install

I would like different python scripts to set individual pixels (although not at the same time), I understand that a blinkt.show() will rewrite all the leds so I wanted a routine to get the current values of the Leds, change the one I want and call Blinkt.show(). I had assumed that I ciould use Blinkt.get_pixel(x) to get the current value but it doesnt seem to do that. If I set a pixel with one script and call show ( using blinkt.set_clear_on_exit(False)), and run another script the value of the pixel always comes out as 0,0,0,0.266
If I set the pixel and then use get_pixel in the same script it seems to work but I’m guessing that get_pixel is not querying the blinkt itself ???

I did clone the lastest github library and installed it as per gadgetoids post above

Any ideas

I suspect it is a little more complicated than you hoped. I think you will need one program to keep hold of the blinkt as the control is buffered. I currently use a “reply” program that replies to message sent by zeromq e.g.:-
from zm_req import ZReqst
if name == “main”:
zp = ZReqst(“c.local:5555”)
led = 2
try:
while True:
print(“system c : isARM : {}”.format(zp.req(“is_ARM”)))
print(“system c : getTMP : {}”.format(zp.req(“getTmp”)))
zp.req(“ledSet”,led, 64, 0, 0, 0.2)
print(" system c : led {}: {}".format(led, zp.req(“ledGet”,led)))
etc
These can run on any system, so I can set/clear/query led’s from any pi (or other).
Currently looking at switching over to use some Rust-lang so possibly will change to use websockets rather than zmq.
You may need to use inter-process-communication(IPC). Or am I being too complex?

The answer above touches upon how you might start to solve this, but the crux of the problem is this:

  • You can’t read from the pixels on Blinkt! They are write-only hardware and have no support for reading.

The get_pixel method is only useful for reading back a value in the internal memory buffer of the library, so if your program exits and resumes again that value is lost.

Yes, Blinkt!'s pixels (APA102s to be precise) remember what colour they’re told to be, but unfortunately have no way to communicate that back to the host.

As @richrarobi suggests, you’ll need to create a service that runs constantly and acts as a gatekeeper for Blinkt!, keeping its memory buffer constantly initialised and refreshing the pixels periodically. That way you can always be sure of their state.

Note: It’s not good practise to simply set Blinkt! to a colour and then exit. It’s possible, but there’s no guarantee Blinkt! will stay that colour since the LEDs have a nasty habit of interpreting random environmental noise as signal and displaying the result of their own accord. In your service you should constantly refresh Blinkt! to the colour(s) you want. Your refresh rate being a tradeoff of responsiveness vs CPU usage- 15/30/60fps are good values.

This thread has a really quick and dirty example of Blinkt! being controlled from another process, it illustrates a point but is probably not something you should ever do :D Accessing blinkt from 2 different processes

This may excessively muddy the waters, but is the way I think I will be going (so that I can also run programs written in Rust)…see:


The above link gives a way to use websockets (in python)… The “server” would control the blinkt, and have “exposed” functions to set and query the blinkt buffer (like the add example). (I currently do this across systems with zmq, but am planning to move towards websockets)
p.s. You need to remove the “sanic” bits if not in a web server …
this might be a better example…

1 Like

I put my code on github if it is any help to anyone…

p.s. running this program (twice) from an I5 linux system uses about 15% cpu on a pi3…

#!/usr/bin/python3
from time import sleep
from zm_prox import ZProxy

if __name__ == "__main__":
    zpc = ZProxy("c.local:5555")
    try:
        while True:
            for led in range(7):
                zpc.ledSet(led, 64, 0, 0, 0.2)
                sleep(0.05)

            for led in range(7):
                zpc.ledSet(led, 0, 64, 0, 0.2)
                sleep(0.05)

            for led in range(7):
                zpc.ledSet(led, 0, 0, 64, 0.2)
                sleep(0.05)
 
    except KeyboardInterrupt:
        print("Stopping!")
        sleep(1)
        for led in range(7):
            zpc.ledSet(led, 0, 0, 0, 0.0)
        sleep(2)

Thanks for all the help in the end I used a simple sockets based script

import blinkt
import socket

blinkt.set_clear_on_exit(False)
blinkt.set_brightness(0.1)
blinkt.set_pixel(7, 0, 0, 255)
blinkt.show()

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('0.0.0.0', 8089))
serversocket.listen(5) # become a server socket, maximum 5 connections

while True:
	connection, address = serversocket.accept()
	buf = connection.recv(64).decode('utf-8')
	data = buf.split(',') #split string into a list
	cmd=data[0].upper()
	if cmd=="SET" :
		blinkt.set_pixel(int(data[1]),int(data[2]),int(data[3]),int(data[4]))
		blinkt.show()
		print(cmd)
	elif cmd=="CLEAR":
		blinkt.clear()
		blinkt.show()
		print(cmd)
	elif cmd=="SHOW":
		blinkt.show()
		print(cmd)
	else:
		print('Unknown command')

and then communication from the other raspberry pi just use

import socket
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('192.168.2.197', 8089))
clientsocket.send(b'set, 0,255,34,0')

simple if inelegant :-)

1 Like

^ ooooh! I wouldn’t call this inelegant. It’s a really good example of what we’re talking about. In fact I’ll mark it as the solution for now since it pretty cleanly demonstrates how multiple processes can share a Blinkt!

Sure it’s not a 100% perfect implementation of a threaded socket server and all that nonsense, but we can bash the rough edges off and make a good example for inclusion in the Blinkt! GitHub repository, I’m sure.

its definitely not perfect the client I’m using in Lua (openluup runing on another rpi) needs the socket closing and reasserting otherwise it just sends the same string again something like this is needed

local socket = require("socket")
local host, port = "192.168.2.197", 8089


local tcp = assert(socket.tcp())
tcp:connect(host, port);
tcp:send("set,4,0,32,32");
tcp:close()

local tcp = assert(socket.tcp())
tcp:connect(host, port);
tcp:send("set,4,0,0,0");
tcp:close()

Umm wondering if there is some sort of flush command if the send is used in the same routine …

Also needs some work to set up the server as a daemon - currently I’m using some of the leds to indicate whats happening in my home automation

I just run my python based server script (ZM_reply_m.py) on startup (using an autostart script driven by cron) so it is available all the time from any of my systems.
Because ZeroMQ supports many different programming languages (including LUA) I preferred to let that do the low level work.
I have a Displayotron pi2 showing temperature, Humidity and Baro from a second remote pi2 with a SenseHat, using a BLINKT on a third pi for status LED’s. Any of the three pi systems (and my PC systems) can run routines on the others (so My Linux PC can query the sense hat, etc). Distributed Computing…

While I was considering converting my server routine to Rust there seems little point, as Python is plenty fast enough for this job. I will use Rust for repetitive processing, though.

Since when does anything have to have a point? :D :D :D

I really should look into rust, but I fear I’m too much of a programming cowboy.

Created a port of Blinkt library in go(lang).
This is still being tested and is currently a program with functions (not a package as such yet) (And there aren’t many comments, I will add some sensible ones) - I tend to read the code.


and

RichR
p.s. I tried Rust, It was a little too finnicky for me, go seems to suit my style, more anyway.

I have now turned the blinkt library into a package on github. See the example also there.
It is almost identical in operation to the Python, but note that the brightness (Luminance) goes from int 0 to 31 (not float 0.0 to 1.0) (Also a value of less than 5 seems adequate)
I would appreciate any comments/bugs/etc…