Practical Technomancy
IMG_7592.jpeg

Blog

Thinking out loud

Posts in Project: Witch Lights
Witch Lights troubleshooting, this sensor is going to kill me edition

I think I figured out why this motion sensor keeps going haywire.

(TL;DR: The more lifelike trail animation causes low-frequency AC and induction on the long power harness. I think.)

Witch Lights 2's sensor2worked just fine in July 2017, with version 1 of the FastLED implementation, which brought multi-sprite automation, and the SpriteManager and SpriteVector framework to manage and create/store/delete Sprite objects in memory, respectively.

It only started malfunctioning in late June 2018, when I pulled the harness out of storage in the spare bedroom for the winter.

What changed?

This year, just the software.

The v.1 FastLED Witch Lights were completed at the last second: the last commit date on GitHub for that build was submitted after midnight on July 2nd. The priority had been fixing memory leaks: the Witch Lights run for 6-9 hours on a single battery in warm weather, and a slow memory leak could cause them to crash in hour 4.

Fortunately, Jim is an excellent developer, and did in fact build an object-oriented animation framework for the Witch Lights gratis, so I owe him a perpetual debt of gratitude. (He also walked me through the class inheritance and the way the state machine sprites were configured and such when I began work on v.2 in spring of 2018. He's good people.)

Anyway, the way we drew the sprite at the time was, we loaded a static CRGB struct into RAM, and then used memcpy to update the leds struct (also CRGB which is like an array of 3-byte arrays, each containing an R, G, and B value) with a function called strpcpy.

(We did it that way because we draw the sprites 3 pixels off-strip, and having an abstracted function that we could feed a location of -3 without accidentally overwriting the bootloader—again—helped a lot.)

Anyway, we just moved pre-rendered sprites around for the travel mode of the Sprite state machine. The idle animation of the time also was a set of pre-rendered animations loaded into RAM as series of CRGB structs that got stepped through like animation frames.

We did that because this was the first time we were going to try animating more than one sprite at a time. We knew the Arduino Due was a significant upgrade from the Duemilanove the first builds of the software was tested on. We didn't, however, have a feel for what the processor capabilities were.

We only knew that v.1 ran for hours without crashing in 1K of SRAM while running a 30-pixel test strip on the 8-bit Duemilanove, and the Due had 96K to run 600-750 pixels. So we threw RAM at the first draft implementation.

insert animation comparison video

In the first half of this (over-long, but forgive me, it was done in 30 minutes before leaving for a trip) documentation video, you can see the result.

Here's a detail.

Witch Lights test home.gif

Note that the length of the tail is exactly the same throughout its travel. It's a series of pre-rendered color values. So, even though the sprite starts off slowly and accelerates, the trail doesn't stretch to emphasize that naturalistic motion.

In version 2, I fixed that.

Turns out, the ARM chip in the Due provided us with excess processor capacity, and so I could afford to play around a bit. Instead of a long, pre-rendered set of fading pixels, each traveling sprite is now three pixels long. And when a sprite moves forwards one pixel, it calls a recursive DimTrail() method on the pixel it left shining behind itself.

DimTrail() uses the FastLED FadeToBlackBy function to fade the brightness of its pixel by a factor which scales with the current updateInterval (framerate) of the Sprite. In english, it fades a certain pixel more if the Sprite is moving slowly, and fades less the faster the Sprite moves.

And then it calls DimTrail() on the pixel behind it.

(There's logic to prevent the Sprite from eating recursion and dying, don't worry.)

As a result, the sprites now have stretchy, lifelike trails.

Witch Lights CO dark.gif

And that means that the total number of pixels we're powering changes unpredictably. And it stands to reason that the amount of current the NeoPixel strips pull from the power rail will also change unpredictably.

In english, the changing trail length creates alternating current (AC) on the power rail.

The same power rail that is powering sensor2.

The 85-foot-long power rail.

That one.

Everyone was telling me it sounded like I needed a low-pass filter on the power line for the sensor at the end of such a long power harness. And I agreed. But what was killing me was:

Why did it work in 2017, and not now? What changed?

The software changed.

I also didn't understand why sensor2 would seem to work fine for some random but short amount of time, and then malfunction. It's because, if there's nothing animating with DimTrail(), we don't have AC on the power rail. As soon as we get one or two sprites animating for a few seconds, AC along the 85-foot power lines build up, and sensor2 probably does not like that.

Several friends with more (real) electronics experience said it sounded like AC or inductance on the power pin was making the sensor behave unpredictably.

The Adafruit Discord Server suggested testing an RC filter. They also believed low-frequency AC on the power pin would definitely cause these symptoms. As did I.

I just didn't know why.

I still don't. Not yet. I have to look for the thing I've predicted will be there: AC on the power line.

My multimeter isn't the right tool to find this bug. Fortunately, a generous friend has mailed me an oscilloscope, and it arrives Wednesday.

Once I have that, I can measure the frequency of the oscillation on the power pin (assuming it exists), and design an RC filter, and fix this without installing a separate power supply for the sensor lines.

Sketchbook Pages: Witch Lights redesign

After meeting with the Adafruit Discord at WMFNY this year, I wrote down some ideas for improvements to the design.

At this point I'm comfortable with the functionality enough to begin thinking of aesthetics and fabrication beyond 3D printing. Also plan to incorporate advice from the #projecthelp channel on how to make the power harness more reliable. Some notes:

  • Use step up and step down modules to push 12V down the length of the harness

  • Consider using plugs, rather than screw terminals, to connect power, LED, and data lines to circuit boards

  • Professionally fabricated circuit boards

  • Back to original vision: 5-meter segments of the harness link together as you install the lights in a location; 12-pin plugs connecting 2 halves of a machined or 3D-printed housing

  • Use LoRa to pass FaerieSprites from one set of Witch Lights to another along long paths and achieve original vision

  • Plug in additional modules, such as the (short) UV NeoPixel strips for Tree Spirits or other non-FaerieSprite animation

  • Moar sensors

  • Teensy Weensy could possibly be next gen brain replacement, having one 5V step-up pin for NeoPixel control

  • Solder a 3.3V power line to the low voltage VIN point of my existing PIR sensors to make them not go bugfuck at 3.3v

Sketchbook page: Witch Lights Harness

Trace paper is where I always start

At World Maker Faire last Sunday, an absolute highlight was being able to see Laura Kampf and Sophy Wong talk about design and making.

I sat with Alex Glow, and was totally thrilled with the presentation. I was especially happy when they showed their notebooks, because I, too, had documenting and sharing my sketchbook drilled into me in design school.

So that's why I'm so happy that I was able to find this photo of the most critical sketch for the Witch Lights, the paper copy of which is in one of about 6 boxes in my closet. This is where I started at one end of a roll of trace paper, and just outlined all the chain of components and elements I'd identified so far. That’s where I realized I could create a unified harness and LED structure with 3D printing.

When I started the sketch, I was considering using polypropylene chinese food containers for the junction boxes. They're recyclable, tough, water-tight, and inexpensive. But my experiment with a hole-saw and the conduit fittings had proved frustrating and laborious.

The conduit I had was 3 times the diameter of what I'd thought I was ordering at 2am the other week. But I liked the way I could make it form shapes in mid-air, and so here I was trying to lay out how using it would change the design.

Note on the left there’s an actual fitting for the harness. I had just found a solidworks model of these online, so I knew I could use my Solidworks assembly context skills to very quickly design hardware to fit it.

At the time I was thinking of printing lids for Chinese take-out containers.

In the upper left, you can see I started a marker sketch of a take-out housing, and then sketched a simpler, streamlined housing that allows the diameter of the conduit to say roughly the same all through the chain.

In the lower right: I figured out I could put sensors in the housings too, reducing another complexity

And you can also see the cable glands and 4-pin waterproof cables for the NeoPixels, which I had already figured out at this point.

It's so cool to find a moment where you pulled it all together and made a design decision that worked out. I'm excited about this!

So yeah... this is basically how I draw. It's not the best. But it gets the idea across I hope.

Next up: building an enchanted notebook so I have shots like this of all my in process work. Because I’ve lost another goddamn notebook.