Forgotten Plots

09 Nov 2020

I’ve been having a little bit of “plotters block” recently, but I finally started making some new plots today. While doing that I remembered a series of plots I’d forgotten to add to the gallery. These plots are built around the addition of geometric boolean operations to SwiftGraphics.

Visit 43660c91…

There are also some fun time lapses of some of the plots.

Placeholder Art

28 Sep 2020

Last week I was listening to the latest episode of Make Do and near the end the conversation turned to generic art from a department store.

The mass-produced prints from IKEA, Target, etc. remind me of bringing store-bought baked goods to a party versus making a cake. Both fulfill the function of being a dessert, but they aren’t equal. There’s an intentionality to baking a cake or finding a unique print for your wall that the store-bought version doesn’t have.

When you bake a cake or hang “real” art you’re asking other people to ask you about it. Not just in the sense of fishing for compliments (though who doesn’t want people to say you have great taste?), but about the journey you went through for it to be here, now. How you baked the cake, or finally bought a piece by an artist you admired, or how you stumbled upon the piece at a local farmers’ market.

A generic photo of pebbles or the Golden Gate Bridge is there to be, effectively, a placeholder in your room. It fills space in an aesthetically pleasing way, but doesn’t prompt a conversation. Someone might say they like it, but the only conversation to be had is “thanks, I picked it up at Safeway on my way here.”

Sonoff L1 & Home Assistant

10 Aug 2020

Recently I bought a bunch of new Sonoff IoT devices, among them was the Sonoff L1: a WiFi connected LED strip. Like all of the other Sonoff equipment I figured it would be supported by ESPHome for easy integration with Home Assistant. As it happens, this wasn’t the case. The whole project ended up being far more complicated than I expected.

Flashing the Controller

The L1 doesn’t expose any headers, so you’ll need to solder wires to the UART pads. Luckily this only requires a few minutes of soldering and you’re good to go.

Flashing the ESP8285 proves a little more difficult as there’s no exposed GPIO0 pin. The Tasmota guide has a good illustration showing which pin on the chip itself needs to be shorted to ground. While this seems like it might be tricky, you get the hang of it.

Once the ESP is booted into programming mode it’s an easy matter to flash ESPHome which provides OTA updates for future changes.

The Software

I’d initially followed some guides for a similar LED controller which used PWM to controll the RGB channels, however, the L1 uses a Nuvoton N76E003 to drive the LEDs. The ESP comunicates over serial to the Nuvoton. Some clever people over on the Home Assitant forums managed to figure out how the board works. Everything from serial protocols to commands.

After several rounds of “I don’t know enough to make this work” I eventually started looking at the Tasmota implementation along with the ESPHome custom light docs and began coding up a custom component. Eventually I managed a basic, but working, implementation which parsed Home Assistant’s input and passed it along to the LED strip.

I would like to figure out how to support some of the other modes in the UI. The music sync mode has parameters for both sensitivity and speed. There are also severl “DIY” modes which allow the user to specify colors for the controller to cycle through.

Putting It All Together

I’ve uploaded the custom component and an example config on GitHub. All you need to do is download the sonoff_l1.h into your ESPHome directory and update led_strip_1.yaml with the specifics of your installation and you should be off to the races.

There are some limitations, at time of writing. While Home Assistant can send changes to the L1, the remote won’t push changes back to Home Assistant. Additionally not all of the L1 modes are fully supported yet.


28 Jul 2020

It’s been a couple of months since I initially began working on SwiftGraphics and it’s already grown quite a bit, and most of that growth has come along with the requisite growing pains. With very few exceptions, every time I’ve started a new generative piece I’ve found a part of the code-base that was fundamentally broken in some way. The good news is that this forced me to actually write tests for more of the code.

One of the largest changes I made was to the ray tracing system. The original version required each ray to have a termination point on a boudning box, along with a separate RayTracer protocol which allowed an object to modify a ray. The upated version unified a couple of protocols, allowing any Shape that can calculate intersections to handle1 rays.

With the new ray tracer in place the first real feature to come from the update was recursive ray tracing. Simply, this meant that a ray could interact with objects multiple times. For instance, two mirrors reflecting rays back and forth.

Another piece of low-hanging fruit I’ve been after for a while was Perlin noise. Much like everything else, there were a few false starts, but eventually I implemented the p5.js version of Perlin noise. Naturally the thing to do was to use the generator to create plots of Perlin noise as a linear sequence.

Finally, as was linked to at the top of the post, I’ve open-sourced SwiftGraphics. This comes with all of the changes mentioned above, along with actual documentation and an example app. The library is mostly built for my needs, but I’d love to get feedback to make it more useful for everyone.

  1. In most cases this simply means the primitive shape returns an empty array, which has the effect of casting a shadow. [return]

Capturebot 2020.2

28 Jun 2020


Last week I released the first update to Capturebot, version 2020.2, with a slew of new features and bug fixes. The update is mostly centered around making working with mappings easier.

The biggest change is a shift away from a single window to a document model, which means mappings can now be saved and shared. For a digital tech this is a perfect way to keep different mappings for each client. On the studio side mappings can be easily distributed to workstations for freelance techs on location. Mappings can also be locked to prevent editing.

There are a number of updates related to importing images. Folders of images can now be opened (along with their subfolders) and files can be dropped onto the images view. There’s also support for opening audio and video content; anything that Exiftool can write to is supported.

Another major feature is a new, free, write-only mode. After the trial expires Capturebot will still be able to open mappings and write metadata, however none of the mappins can be changed.

The final big update is the addition of a small shotlist view. This brings Capturebot full-circle back to its origins as a shotlist tracking application. The plan is to enhance the shotlist over time and make it a larger part of the application.

You can check out all of the changes and download a trial over at the website.

Generative Art in Swift

23 May 2020

For the past few days I’ve been working on my own Processing-like graphics library built in Swift. I got tired of working in JavaScript, and for lack of a better option, decided that writing my own library would be the way to go.

I didn’t want to simply port Processing into Swift, someone’s already done that. Instead I wanted to make a Swifty-er version that was more protocol and object oriented. Today I got it to a state where it’s functional and I’m happy with how it’s implemented.

One of the main reasons for wanting to build my own library was to make a nicer ray tracing system. I’d made a simple version in P5.js, but the idea of adding more features using JavaScript was… unappealing. After the basics (circles, rectangles) I wanted to add Fresnel lenses.

I tried several methods to figure out the angles. Initially I wanted to use vectors, but bailed on it (because I hadn’t implemented all of the vector math required for the operations) and decided that I should be able to use Pythagorean’s theorem to make a triangle from the line and calculate the angles. This initially worked, but ended up with far too many edge cases, everything from which way the line sloped, to horizontal and vertical lines.

Eventually I went back to the vector math. I knew that it was something that was possible, easy even, because of an example demonstrating non-orthogonal reflection from P5.js. After adding some more vector math operations I was able to reliable determine the angle perpendicular to the Fresnel lens line. This also gave the lens a single direction; it acts as a Fresnel from one side, and a collimating mirror from the other.

Processing & Generative Art

01 Apr 2020

I follow a number of people on Twitter who make generative art, and it’s something I’ve been wanting to try myself for a while. With everything going on I finally made the time to sit down and really play with a tool called Processing.

One of my favorite generative artists, Anders Hoff of Inconvergent, does some amazing work with plotters. My favorite piece of his is 706dbb4. I love the way the intersecting lines form a sphere, and the lines that break out of the confines of the circle are almost solar flares.

I wanted to attempt to generate a piece inspired by this print, and wanted to create something that could be drawn on a pen plotter.

I started off by connecting random vertices on the edge of a circle to one another, creating a random web of lines. Eventually I added a limit to the angles in which the vertices could be, which adds a more abstract character. After adding randomization to all of the parameters, I just kept rendering new images.

With some advice from Andrew Rodgers on Twitter to play with more advanced math functions like sine, cosine, exponents, etc. This came right as I was playing with using Bezier paths instead of straight lines. I created another set of vertices and modified their positions:

anchorPoint = pointOnCircle(center, center, circleRadius + 100, tan(r))
anchor1X = random(0, canvasSize)
anchor1Y = anchorPoint[1]

ancho2X = anchorPoint[1]
anchor2Y = pow(log(anchorPoint[0]), 3)

The blue and green squares are the anchors that Bezier paths move through, each with a start and end point on the circle:

The new images are much more energetic, and when the angles are small produce an internal flare of lines, as seen in the third image below.

All of the images (and possibly more, over time) are available over in the new Generative Art gallery. I hope this will be a fun new area to explore over time.

A Useless Picture Frame

27 Mar 2020

Many months ago my father gave me an old, delapidated, film splicer. I had the intention of cleaning it up and displaying it somewhere? Maybe? I didn’t really think it through, but I do love weird old things like that. The splicer was shuffled around a few times by me and my roomates, and eventually ended up sitting at the end of a wallway, mostly forgotten. Util two days ago.

Due to circumstances beyond my control I’ve found myself with some, ahem, extra free time, and while walking down the afformentioned hallway, saw the splicer, and knew extactly what to do with it.

The Hardware

The whole system fits neatly inside the original film viewer.

The whole system fits neatly inside the original film viewer.

A 1.44” TFT display, Wemos D1 mini, and battery are housed in the film viewer, which originally held a lightbulb in the top portion. I wired the original power switch to continue to control power for the system, and the barrel jack to charge the battery is in place where the original power cable went.

The Software

While the hardware was relatively straight forward, the software was another matter. This was the first time I’ve dabbled with running a display on an ESP board before.

I was thrilled when I eventually managed to get the C++ working to display a line of text, and even more so when I had a tiny web server running that let me remotely push text to the screen. Displaying images, however, was another story. Eventually I decided to switch from Arduino to MicroPython, which is a much more familiar programming environment.

I eventually found a display library that worked and was off to the races. With a little bit of Python I wrote a very simple slideshow player that pulled images out of a folder read them out and displayed them. After a few iterations the player even saved its current position between boots.

The files load incredibly slowly, and are displayed line-by-line, which I think gives a rather charming transition between images.

Displaying Images

The display I used has an astonishing resolution of 128x128 pixels, and a mere ~100x65 pixels that are actually visible through the magnifier. This, in my opinion, results in some delightfully lo-fi images.

The images need to be resized, matted, and converted to bitmaps before being uploaded to the board.

An image ready for display

An image ready for display

In Conclusion

The entire project only took a couple days and was built using entirely with parts I had lying around. When I showed my roomates the end result they had trouble even telling what the images were, and I think that’s part of the fun. This was a project just for me to experiment and try something new.

That being said, if anyone would like to build their own, all of the source code is published on GitHub.


18 Feb 2020

One of the tiniest annoyances using computers these days is keeping track of the cursor. On a single display losing the cursor isn’t terrible, macOS has a feature to help you find it, as long as you can see all of the displays. If you’re running a set with a remote viewing monitor it’s easy to accidentally move the cursor out of view and wrangling it back isn’t always easy.1

CaptureCursor does one thing: move the cursor to the center of the current Capture One session or catalogue window. All you have to do is hit a keyboard shortcut and CaptureCursor identifies the session, makes Capture One the active application, and centers the cursor in the window.

Much like my Capture One scripts, I wrote CaptureCursor for me to use on set, but I hope other DTs will find it useful. CaptureCursor is avaialble for $4.99 with a 14 day trial.

  1. Who amongst us hasn’t got the cursor stuck in the mis-aligned edges of a second display? [return]