November 7th, 2017

Vladimir Iakolev: Soundlights with ESP8266 and NeoPixel Strip

Programing, Python, by admin.

About a year ago I made soundlights with Raspberry Pi.
But RPI is a bit of an overkill for this simple task and it’s quite big,
doesn’t have WiFi out of the box and practically can’t be used without a power adapter.

So I decided to port soundlights to ESP8266. The main idea was to reuse as
much as possible from the previous implementation, so the parts with patched
audio visualizer and colors generation are the same. In a few words,
I’ve patched cava to print numbers
instead of showing pretty bars in a terminal. And I’ve generated colors
with a code found on Quora.

And in current implementation I decided to make it very simple to use,
the only requirement is to have a machine with cava and ESP8266
on the same WiFi network. So I chose UDP broadcasting as a way to send data to ESP8266. And because there’s just 60 LEDs and color of
a LED is three values from 0 to 255, colors for all strip is just
180 bytes. So it fits in one UDP packet.

Let’s start with the part with cava:

import sys
import socket
import array COLORS_COUNT = 256
COLORS_OFFSET = 50 def get_spaced_colors(n): max_value = 16581375 interval = int(max_value / n) colors = [hex(i)[2:].zfill(6) for i in range(0, max_value, interval)] return [(int(color[:2], 16), int(color[2:4], 16), int(color[4:6], 16)) for color in colors] def send(colors): line = array.array('B', colors).tostring() sock.sendto(line, ('', 42424)) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) colors = get_spaced_colors(COLORS_COUNT) while True: try: nums = map(int, sys.stdin.readline()[:-1].split()) led_colors = [c for num in nums for c in colors[num]] send(led_colors) except Exception as e: print(e)

It can be used like:

unbuffer ./cava -p soundlights/cava_config | python cava/soundlights/esp/

And it just reads numbers from cava output, generates colors, transforms them to bytes
and broadcasts them at 42424 port.

The ESP8266 part is even simpler:

import socket
import machine
import neopixel np = neopixel.NeoPixel(machine.Pin(5), 60)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 42424)) while True: line, _ = sock.recvfrom(180) if len(line) < 180: continue for i in range(60): np[i] = (line[i * 3], line[i * 3 + 1], line[i * 3 + 2]) np.write()

It just receives broadcasts from 42424 port and changes colors of LEDs.

At the end, this version has less code and just works.
It’s even some sort of IoT and with some effort can become a wearable device.


Back Top

Leave a Reply