README.md

BlinkyTape Orb

The code in this repository makes a BlinkyTape controller board
act like an ambientdevices Ambient Orb and allows controlling it from Ruby over
USB. Controlling the Orb from other languages should be simple—it only requires
sending a few ASCII characters over the serial interface.

Ambient Orbs are great for displaying background information such as stocks,
the weather, or whether or not the master branch of your repository is
passing tests.

Custom Firmware for BlinkyTape controller board

A BlinkyTape has multiple individually-addressable LEDs connected to it. It can
recieve commands over the serial interface. The default firmware expects 3
bytes per pixel (values for red, green, and blue), followed by a 255 byte to
display everything. This protocol is required for compatibility with BlinkyTape
software such as PatternPaint.

On the other hand, the Ambient Orb accepts a color and animation, encoded as
ASCII. After recieving a command, the Orb continues to animate (pulse) on its
own. Like on the BlinkyTape, the button is used to cycle through several
brightness levels.

The arduino directory in this repository contains custom firmware for the
BlinkyTape that makes it act more like an Ambient Orb. There are some
differences:

Serial Protocol

The custom firmware accepts a single ASCII character per command. Color and
pulse speed commands encode both attributes in a single character. In
brightness commands, a single character corresponds to a single brightness.

Color and Pulse Speed

The two lowest bits encode the pulse speed:

00 - No pulsing

01 - Slow pulsing

10 - Medium pulsing

11 - Fast pulsing

The next three bits encode the color:

000 - Red

001 - Orange

010 - Yellow

011 - Green

100 - Blue

101 - Purple

To make the protocol easier to type by hand in a serial monitor, commands are
"shifted up" by 65 (ASCII "A"). For example, green and medium pulsing would be
encoded as 01110 (14), but this is sent as 79 (65+4), which is "O".

This encoding can be done easily in Ruby:

('A'.ord + (color *4) + pulse).chr

In other words, "A" is red with no pulsing, followed by "B" for slow pulsing,
"C" for medium pulsing, and "D" for fast pulsing. "E" is orange with no
pulsing, "F" is orange with slow pulsing, etc.

Brightness

There are three settings encoded in two bits:

00 - Dim

01 - Medium

10 - Bright

These are "shifted up" by 60 (ASCII "<"). So "<" is dim, "=" is medium, and ">"
is bright. The Ruby one-liner for encoding is:

('<'.ord + brightness).chr

Hardware Setup

I stuck the BlinkyTape controller board
on the plastic base of the Orb with a small styrofoam riser (poor man's 3D
printer) and some double-sided tape. The adafruit NeoPixel 12-LED ring
easily fits on the plastic base and in the hole in the bottom of the glass part
of the orb. The ring rests on slightly higher styrofoam risers, above the
controller board. I got the JST connector version of the controller board,
snipped off the connector, and soldered the wires directly to the NeoPixel
ring. The glass orb simply rests on the plastic base since there isn't anything
for the base to screw into anymore. (The wires kind of help keep the base
attached to the glass.) I considered getting a NeoPixel 7-LED jewel to sit in
the center of the ring, but the 12 LEDs are plenty bright even in daylight.

adafruit makes NeoPixel LEDs in a variety of form factors. I built another
"Orb" using the 8-LED strip that has
no enclosure—it is just attached to the underside of my monitor and lights up
the monitor stand. The setup is relatively cheap, easy to assemble, and small
enough to install just about anywhere.