since there will be many centerpieces and i want them to be syncronized in whatever they are doing i was originally thinking of a RFM69 module running some kind of mesh network. i got some from my favorite chinese superstore, and played with them for roughly an hour and decided that would be kinda a pain in the a**. instead i turned to a slightly less energy efficient item the ESP8266.
In short it uses a bit more current, but take on the role of both processor and wireless tranceiver, plus python. its the path of least resistance for me. so i took the wireless "strip" i created several entries ago and hooked it up to some nodeMCU modules i had lying about.
i use the built in python binding for the apa102 and connect the CLKIN line to GPIO14 and the DATAIN line to GPIO 13.
technically i should use a level converter, but at the prototype stage it works okay. so ill leave it for future me to sort out.
and thats the hardware completed for this post.
ive decided to try using UDP broadcasts for this project, it will syncronize within the latency of the network, and that is negligible on the timescales im working with. ill have to build up a protocol layer on top on UDP but i dont need to worry about reliable communications since i can accept a certain amount of frame loss in the transmission.
for a test program ive decided to transmit a 3 byte datagram in RGB order. when a node receives the datagram it will set all leds to the transmitted color.
im currently running micropython, but i may switch to circuit python at some point if i run into any problems.
from machine import Pin from apa102 import APA102 import usocket port = 5500 clock = Pin(14,Pin.OUT) data = Pin(13,Pin.OUT) numPixels=2 apa = APA102(clock,data,numPixels) def setPixelRaw(index,r,g,b,val=31): apa[index]=(r,b,g,val) def setPixelStr(index,s): if len(s)<3: return val=31 r= s g= s b= s if len(s)>3: val = s setPixelRaw(index,r,g,b,val) setPixelRaw(0,255,255,255) setPixelRaw(1,255,128,64) apa.write() s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM) s.bind(('127.0.0.1',port)) while True: t=s.recvfrom(1024) setPixelStr(0,t) setPixelStr(1,t) apa.write()
that is it for now, in the future id like to be able to send different rgb values for different pixels. but seeing as how i only have two leds wired up at the moment this will do to test the wireless aspects.
The transmitter code currently runs on my laptop. on a full python2.7 interface. this is likely how the final version will run; a full python interface, not my laptop, maybe a Raspi or Beaglebone.
Using the full python interface simplifys the HSV to RGB conversion significantly, "import colorsys" does it all. <insert XKCD comic here>
the only special part of this code is the socket option SO_REUSEADDR for broadcasting to the local subnet.
import socket import binascii import colorsys import time udpIP = '10.0.0.255' udpPort = 5500 color = "7f3f1f" message = binascii.unhexlify(color) sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.sendto(message,(udpIP,udpPort)) while True: for i in range(256): (r,g,b) = colorsys.hsv_to_rgb(i/256.0,1,1) r=int(r*255) g=int(g*255) b=int(b*255) message = chr(int(r))+chr(int(g))+chr(int(b)) sock.sendto(message,(udpIP,udpPort)) time.sleep(.01)
now to focus on having more LEDs to play with...