Some of the more complex demos are written in Processing, a cross-platform multimedia programming environment for Windows, Mac and Linux. If you’re not already using Processing…
When you unpack and install Processing, you’ll notice it looks very similar to the Arduino IDE, and it’s easy to get the two confused if they’re both running. Unlike the Arduino IDE, which is specifically for microcontrollers, Processing is for writing code for your regular computer.
Let’s open one of the example projects. Let’s say grid32x16z_wavefronts…
Download from Processing.org
When you unpack and install Processing, you’ll notice it looks very similar to the Arduino IDE, and it’s easy to get the two confused if they’re both running. Unlike the Arduino IDE, which is specifically for microcontrollers, Processing is for writing code for your regular computer.
Let’s open one of the example projects. Let’s say grid32x16z_wavefronts…
You’ll see this sketch has a second tab called “OPC.” Every Processing sketch for Fadecandy requires this code for communicating with fcserver; you’ll want to copy it into any new Fadecandy sketches you write.
As written, this demo sketch won’t work with our LED curtain. It’s designed for several 8x8 NeoPixel matrices. But we can rework it quite easily.
Look for this block of code in the setup() function:
As written, this demo sketch won’t work with our LED curtain. It’s designed for several 8x8 NeoPixel matrices. But we can rework it quite easily.
Look for this block of code in the setup() function:
size(640, 320, P3D); colorMode(HSB, 100); texture = loadImage("ring.png"); opc = new OPC(this, "127.0.0.1", 7890); opc.ledGrid8x8(0 * 64, width * 1/8, height * 1/4, height/16, 0, true); opc.ledGrid8x8(1 * 64, width * 3/8, height * 1/4, height/16, 0, true); opc.ledGrid8x8(2 * 64, width * 5/8, height * 1/4, height/16, 0, true); opc.ledGrid8x8(3 * 64, width * 7/8, height * 1/4, height/16, 0, true); opc.ledGrid8x8(4 * 64, width * 1/8, height * 3/4, height/16, 0, true); opc.ledGrid8x8(5 * 64, width * 3/8, height * 3/4, height/16, 0, true); opc.ledGrid8x8(6 * 64, width * 5/8, height * 3/4, height/16, 0, true); opc.ledGrid8x8(7 * 64, width * 7/8, height * 3/4, height/16, 0, true);
Change the size() call to match the aspect ratio of our curtain (24 columns wide, 60 rows tall). We’ll scale it up by a factor of 10 so the window is easier to see:
size(240, 600, P3D);
Change the OPC() call to contact the Raspberry Pi across the network:
opc = new OPC(this, "curtain.local", 7890);
And all the ledGrid8x8() calls are replaced with 24 vertical ledStrip() calls. We’ll use a loop for brevity:
for(int i=0; i<24; i++) { opc.ledStrip(i * 60, 60, i * width / 24.0 + width / 48.0, height * 0.5, width / 24.0, PI * 0.5, false); }
The parameters to opc.ledStrip() are:
Before running this sketch, close the browser window running the ganzfeld test; the two programs will interfere.
When you move the mouse over the wavefronts window, you’ll get some colorful ripples that follow the cursor. The animation should be mirrored on the LED curtain.
- The index of the first pixel in the strip. Because of the map we set up in fcserver.json, and the length of the strips, this is equal to the column number (i, ranging from 0 to 23) times the strip length (60 pixels).
- Strip length, 60 pixels.
- In window coordinates, the centerpoint of the strip on the X (horizontal) axis. For our curtain, this is equal to the column number (0 to 23) multiplied by 1/24 of the total window width in pixels (the variable 'width' in Processing). The additional half column (+0.5) is to center the full set of columns in the window, so they’re not pressed up along the left edge.
- Centerpoint of the strip on the Y (vertical) axis. Our vertical strips will always be centered along that direction, hence height * 0.5.
- Spacing between LEDs, in pixel units. With 24 columns, this is width / 24.0.
- Angle of the strip, in radians. For vertical strips with the first pixel at the top, this is PI * 0.5(90 degrees).
-
false = don’t reverse the order of the LEDs.
Before running this sketch, close the browser window running the ganzfeld test; the two programs will interfere.
When you move the mouse over the wavefronts window, you’ll get some colorful ripples that follow the cursor. The animation should be mirrored on the LED curtain.
No response from the LEDs, or some sections aren’t lighting!
Use the same troubleshooting process as for the web example above.
It’s flickering madly!
Close the browser window running the ganzfeld test; the two programs will interfere.
The brilliance of the Fadecandy OPC code is that it’s easily incorporated into existing Processing sketches. There’s already tons of visual effects code out there.
Here’s a Processing sketch for playing video. Select a movie file (AVI, MOV, etc.) and it’ll crop and scale a 24x60 vertical box from the center. Remember to copy the contents of the OPC tab from another Fadecandy sketch to use this.
Here’s a Processing sketch for playing video. Select a movie file (AVI, MOV, etc.) and it’ll crop and scale a 24x60 vertical box from the center. Remember to copy the contents of the OPC tab from another Fadecandy sketch to use this.
// Processing 2.X movie example for // Adafruit NeoPixel/Fadecandy LED curtain import processing.video.*; OPC opc; Movie movie; PGraphics g; // Offscreen buffer for scaling DisposeHandler dh; int xres = 24, yres = 60, scale = 10, mx, mw; void setup() { size(xres * scale, yres * scale, P2D); g = createGraphics(xres, yres, P2D); opc = new OPC(this, "curtain.local", 7890); dh = new DisposeHandler(this); for(int x=0; x<xres; x++) { opc.ledStrip(x * yres, 60, (x + 0.5) * scale, height * 0.5, scale, PI / 2.0, false); } selectInput("Select a file to process:", "fileSelected"); } void fileSelected(File selection) { if(selection == null) exit(); movie = new Movie(this, selection.getAbsolutePath()); movie.loop(); mw = (int)((float)yres * ((float)movie.width / (float)movie.height)); mx = (xres - mw) / 2; } void movieEvent(Movie m) { m.read(); } void draw() { if(movie == null) { background(0); } else { g.beginDraw(); g.image(movie, mx, 0, mw, g.height); // movie->buf scale/crop g.endDraw(); image(g, 0, 0, width, height); // buf->window scale } } public class DisposeHandler { // LEDs off when exiting DisposeHandler(PApplet pa) { pa.registerMethod("dispose", this); } public void dispose() { for(int i=0; i < xres * yres; i++) opc.setPixel(i, 0); opc.writePixels(); } }
The DisposeHandler section takes care of turning off the matrix when the program exits. You may want to copy this into your own Fadecandy sketches.
Curating videos, selecting material that looks good on the vertical curtain can be time-consuming; not everything frames well in this format. The stargate segment in 2001: a Space Odyssey looks great though.
Curating videos, selecting material that looks good on the vertical curtain can be time-consuming; not everything frames well in this format. The stargate segment in 2001: a Space Odyssey looks great though.
For Power Users…
You can write Fadecandy applications in almost any language…anything that provides access to TCP sockets…you just need to follow the Open Pixel Control protocol, as detailed in the Fadecandy documentation. Or you can pick apart the OPC code in Processing.
Python and C both perform quite well on the Raspberry Pi. An expert programmer could make this a self-contained system, not reliant on a networked computer to drive the animation.
Text editor powered by tinymce.