Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
That shredded plastic can’t possibly be a Good Thing; the endcap contained plenty of loose shreds.
Perhaps I’m overly critical, but I think the only way these fixtures could have a UL approval certificate was that somebody else didn’t notice their certificate went missing. Most likely, of course, the fixtures sent for approval looked lovely and bore no relation to the junk actually sold to Lowe’s / Home Depot.
The least horrible way to get events from the keypad turned out to be a simple non-blocking poll from Python’s select library, then sucking the event input queue dry; the main loop now does what might be grandiosely overstated as cooperative multitasking. Well, hey, it reads lines from mplayer’s output pipe and processes keypad events and doesn’t stall (for very long) and that’s multi enough for me.
It extracts the stream title from the ICY Info line, but I still haven’t bothered with a display. It may well turn out that this thing doesn’t need a display. The stream title will be enclosed in single quotes, but it may also contain non-escaped and non-paired single quotes (a.k.a. apostrophes): the obvious parsing strategy doesn’t work. I expect titles can contain non-escaped semicolons, too, which will kill the algorithm I’m using stone cold dead. Some try - except armor may be appropriate.
This code does not tolerate a crappy WiFi connection very well at all. I eventually replaced a long-antenna WiFi adapter with an actual Ethernet cable and all the mysterious problems at the far end of the house Went Away. Soooo this code won’t tolerate random network stream dropouts very well, either; we’ll see how poorly that plays out in practice.
The hackery to monitor / kill / restart / clean up after mplayer and its pipes come directly from seeing what failed, then whacking that mole in the least intrusive manner possible. While it would be better to wrap a nice abstract model around what mplayer is (assumed to be) doing, it’s not at all clear to me that I can build a sufficiently durable model to be worth the effort. Basically, trying to automate a program designed to be human-interactive is always a recipe for disaster.
The option for the Backspace / Del key lets you do remote debugging by editing the code to just bail out of the loop instead of shut down. Unedited, it’s a power switch: the Pi turns off all the peripherals and shuts itself down. The key_hold conditional means you must press-and-hold that button to kill the power, but don’t run this on your desktop PC, OK?
Autostarting the program requires one line in /etc/rc.local:
sudo -u pi python /home/pi/Streamer.py &
AFAICT, using cron with an @REBOOT line has timing issues with the network being available, but I can’t point to any solid evidence that hacking rc.localwaits until the network is up, either. So far, so good.
I make no apologies for any of the streams; I needed streams behind all the buttons and picked stuff from Xiph’s listing. The AAC+ streams from the Public Domain Project give mplayer a bad bellyache; I think its codecs can’t handle the “+” part of AAC+.
All in all, not bad for a bit over a hundred lines of code, methinks…
More fiddling will happen, but we need some continuous experience for that; let the music roll!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
It stopped changing colors and began blinking high-intensity bursts of the RGB LEDs. Which was interesting, I’ll grant you, but didn’t produce the desired, ah, mood.
It’s been plugged into a Kill-a-Watt meter that reports it ran for 415 hours and used 150 W·h of energy, for an average 360 mW dissipation. I think the actual power falls well below the meter’s lower limit, so I doubt the accuracy, but it’s a whole bunch less than a nightlight and much more interesting.
Now, to break that epoxy bond without breaking the bulb …
The getter flash covers the entire top of the tube; shining an LED down through the evacuation tip won’t work and even a laser doesn’t do much. That saves me the trouble of trying to create a cap that doesn’t wreck the tube’s good looks.
I originally planned to use white / natural PETG for the socket, but the more I see of those things, the more I think black is the new white. The sockets should vanish into the background, to let the tubes (and their reflections) carry the show.
The (yet to be designed) base must vanish under the platter edge, too, which puts a real crimp on its overall height. I’m not sure how to fit an Arduino Pro Mini and an FTDI board beside the existing socket; perhaps this calls for a unified socket-base design held on by those screws, rather than a separate socket inside a base enclosure.
Even though I know the tubes are inert and cool, I still hesitate before removing them from their sockets with the Neopixels running: you simply do not unplug a hot, powered device!
Stipulated: garish labels that don’t fit the keys well at all.
I need more than one stream for testing; the only one that matters is Classical.
The keypad uses the same 2.4 GHz ISM band as the Raspberry Pi’s Wifi radio, which means holding a key down (which should never happen) puts a dent in mplayer’s cache fill level. Even absent that interference, the WiFi link seems more than a little iffy, probably because it’s at the far end of the house and upstairs from the router.
Other WiFi devices report that 2.4 GHz RF has trouble punching through the intervening fifty feet of hardwood floor (on the diagonal, the joists amount to a lot of wood) and multiple sets of doubled wallboard sheets; the RPi probably needs a better radio with an actual antenna. I did move the WiFi control channel away from the default used by the (relatively distant) neighbors, which seemed to improve its disposition.
USB WiFi dongle (in power hog mode) on a short extension cable for better reception
As much hardware doc as you need:
RPi Streaming Player – first lashup
The green plug leads off to a set of decent-quality PC speakers with far more bass drive than seems absolutely necessary in this context. The usual eBay vendor bungled an order for the adapter between the RCA line-out jacks and the 3.5 mm plug that will avoid driving the speakers from the UCA202’s headphone monitor output; I doubt that will make any audible difference. If you need an adapter with XLR female to 1/4 inch mono, let me know…
The keypad labels provide all the UI documentation there is:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The Media dictionary relates keycodes with the command line parameters required to fire mplayer at the streaming stations. With that running, the Controls dictionary turns keycodes into mplayer keyboard controls.
There’s no display: you have no idea what’s going on. I must start the program manually through an ssh session and can watch mplayer‘s console output.
Poking the Halt button forcibly halts the RPi, after which you squeeze the Reset button to reboot the thing. There’s no indication that it’s running, other than sound coming out of the speakers, and no way to tell it fell of the rails other than through the ssh session.
The loop blocks on events, so it can’t also extract stream titles from the (not yet implemented) mplayer stdout pipe / file and paste them on the (missing) display; that’s gotta go.
There’s a lot not to like about all that, of course, but it’s in the tradition of getting something working to discover how it fails and, in this case, how it sounds, which is even more important.