OPC Client Apps

Hello world! Launch the Processing (2.2.1) IDE and load the first of our example programs: OPCstrandtest.

At the top of the code are these two lines:

OPC opc       = new OPC(this, "", 7890);
int numPixels = 256; // Set this to actual strand length

The first line holds the address of your OPC server device. We previously configured that in the Arduino code. The format here is just a little different though…instead of four comma-delimited values (192, 168, 0, 60), here it’s a string with period separators "". Edit the numbers to match the Arduino sketch.

Next line is the number of LEDs in your DotStar chain. This might be 64 for an 8x8 matrix, or 60 (or 144, etc.) for one meter of DotStar strip.

When you run this code (the top-left icon in the Processing window), after just a moment’s delay you should see the message “Connected to OPC server” and get a “chaser” down the DotStar chain that cycles between red, green and blue for each pass. Press the ESC key to stop the program.

If the colors appear in the wrong order (not red, green, blue), you’ll need to edit the Arduino sketch to match your particular DotStar hardware. This is explained near the bottom of the “Software” page.

If it runs slowly or stutters, especially with long LED runs, you may need to reduce the frame rate. Inside the setup() function you’ll see a call to frameRate(). It takes a single argument, the number of frames per second. The default (if not specified) is 60 frames per second…that’s usually fine with small projects, but with lots of LEDs you may need to dial it back, to perhaps 30 frames per second.

If you don’t see the “Connected” message and don’t get any LEDs: either the Server sketch on the Arduino can’t connect to the wireless network, or the address at the top of the Processing sketch is incorrect.

Do not continue until you have the led “chaser” working, and it’s cycling from red to green to blue.

Animation Without Programming

Now load the second example: OPCpianoRoll. Make similar edits to the IP address and LED chain length at the top of the code. When run, this will prompt you for an image file. A moving cross-section (one horizontal line) of this image is then “played” on the LED chain.

What this basically enables you to do is use your favorite image editor (Photoshop or most anything else) to create animation sequences. Create a new image whose pixel width is equal to the number of LEDs in the chain, and the height is the animation length in seconds times the number of frames per second (which can be controlled with the slider at the bottom of the window). For example: 60 DotStar LEDs, with a 15-second animation at 30 frames/second (the default) = 60 pixels wide x 450 pixels high (15 x 30). Make the background black, then try using the pencil or airbrush tools to paint some colorful lines. Save the result as a lossless 24-bit image (like PNG or TIFF…do not use GIF or JPEG, they’ll degrade with each successive edit)…then run the OPCpianoRoll sketch and select this file when prompted.

The topology (a straight line) won’t necessarily match the physical layout of your LEDs, but once you understand the “mapping” between the two different spaces it’s pretty easy to use.

Here’s an image equivalent to the RGB chaser code along a 144 pixel strip. Right click and “Save Image” to save this to your computer for use with the OPCpianoRoll sketch:

Video Playback

Last example is “OPCvideo.” This works best with LED matrices. Edit the IP address at the top of the code to point to the OPC server, then edit the values of “arrayWidth” and “arrayHeight” to match the LED matrix (assumed to be a “zigzag” layout…if not, there’s an opportunity to change that a little further down in the setup() function). When run, you’ll be prompted to select a movie file (e.g. .MOV, .MP4, .AVI) which then plays on the LED matrix, hot damn.

Video decoding and playback is unfortunately not always reliable in Processing…it can be incredibly persnickety about codecs, plug-in libraries, 32-bit vs 64-bit and other things. If a certain video file doesn’t work, your only recourse may be to try other videos using different codecs, or sometimes a different version of Processing…or you may just have to skip this one and try the other demos (and start writing some of your own).

Some of the dimmer LEDs flicker!

This is normal and by design. DotStar LEDs have a finite number of discrete brightness levels, and our eyes perceive disproportionally large steps toward the low end of the brightness range. Borrowing an idea from Fadecandy, our code uses temporal dithering to approximate in-between brightness levels that would otherwise be too dim or too bright…it quickly alternates between the two. It’s less noticeable at a distance and/or with some diffusion over the LEDs, like paper or white acrylic.

Creating New OPC Clients in Processing

Notice that all of the example sketches have a second tab called “OPC.” This is an Open Pixel Control library for Processing, written by Micah Scott (Fadecandy’s creator). To create a new OPC sketch, or adapt an existing Processing sketch to add OPC output, make a new tab called “OPC” and then copy-and-paste that code from any of the existing OPC examples.

Processing is way too deep to summarize here. Entire books have been written on the subject. If you’d like to get started writing new sketches of your own, look through the Examples they include, or skim the Reference and Tutorials pages on the Processing web site.

The OPC library allows you to create an “overlay” atop the screen output of any existing Processing sketch, redirecting specific pixels to an OPC server. Several functions allow you to position lines or grids (even circles) of LED pixel locations within the Processing output window. After this one-time setup, your sketch just draws animation as it would normally…no per-frame processing is required…and the LED pixels follow suit. So you can write animation code first (no hardware required), then worry about the LED placement later.

What’s exciting about this is that you’re not constrained to pixel grids. Your art can take whatever shape you feel it needs…this isn’t necessarily dictated by the physical hardware.

Here’s an example using one of our 255-pixel DotStar LED discs:

And the corresponding source code. Notice the “circumference” array, which lists the number of pixels in each concentric ring around the DotStar disc, and the calls to opc.ledRing() which overlay these points atop the program’s display window. The draw() function then handles the animation…it doesn’t have to think about networking or data packets at all, it just happens.

// OPC example scrolls text on a 255-pixel DotStar disc

OPC opc = new OPC(this, "", 7890);
PFont f;

void setup() {
  size(400, 400);

  int circumference[] = { 12*4, 11*4, 10*4, 8*4, 7*4, 6*4, 5*4, 3*4, 6, 1 };
  int i = 0;
  for(int j=0; j<10; j++) {
    opc.ledRing(i, circumference[j], width/2, height/2, width/20*(9-j), 0);
    i += circumference[j];

printArray(PFont.list()); // Show available fonts, if you need to change:
  f = createFont("HelveticaNeue-BoldItalic", 450);
  colorMode(HSB, 100, 100, 100);

int hue = 0, x = -1800;

void draw() {
  fill(hue, 100, 50);
  text("Adafruit", x, 360);
  x -= 12;
  if(x < -1800) x = width;
  if(hue >= 100) hue = 0;

Not Done Yet

Things get really interesting when you realize it’s possible to create arrays of OPC objects, each one pointed to a different remote OPC device…

OPC opc[] = {
  new OPC(this, "", 7890),
  new OPC(this, "", 7890),
  new OPC(this, "", 7890)

void setup() {
  size(400, 400, P3D);
  opc[0].ledGrid8x8(0, 100, 200, 10, 0, true);
  opc[1].ledGrid8x8(0, 200, 200, 10, 0, true);
  opc[2].ledGrid8x8(0, 300, 200, 10, 0, true);

…once set up, the remainder is “automagic.” The animation is synchronized across all the OPC devices on the wireless network, which are free to move around (within range of the WiFi router). This could make for some very potent and interesting performance art. Also, it’s “self-healing”…if a device loses its connection, animation continues across the others, and the missing device will pick up at the right spot once a network connection is reestablished.

Python Too…and More to Come!

The Open Pixel Control protocol itself is fairly straightforward, and most any programming language with network support could conceivably be used to write clients.

The canonical OPC code repository on Github includes some examples written in Python.

Google around, you may find libraries for other languages as well. Or read the OPC stream specification (incredibly simple!) and implement your own.

Last updated on 2016-02-01 at 06.03.44 PM Published on 2016-02-01 at 05.10.02 PM