Step 5: In which I get software working but run out of RAM

Goal: Get a working CircuitPython light staff

An image from the inaugural photo shoot with the light staff:


I’d mostly ignored the CircuitPython implementation of this for a while, in favor of the ATMega328 version.

My ATMega328 version does a wide variety of interesting effects and 144 pixels is close to the limit of the amount of RAM in the device. After I spent a weekend trying out the different FastLED patterns and figuring out which ones I like, it’s been actually really smooth sailing.

When I try to find the same functionality on the CircuitPython side, it’s not really there. The thing I keep coming back to is that FastLED is really two libraries: One library is the low-level code that talks to the LEDs. The second library is the incredibly useful math-related code that makes it friendly to code interesting LED patterns.

There’s an extremely large category of useful things that can be done with procedural texturing. A long time ago, I was studying movie effects and they covered how to do procedural textures and I found that you can go really far with them.

So for a while, it was sitting near-abandoned while I worked on other things because I was perfectly able to do just about all I wanted to do on a device that has several orders of magnitude less capability than an M4.

I did finally hit on the real thing that was worth investigating, however: Loading bitmaps from the virtual disk and tiling them.

I got a reasonable version of things going with a 60 LED strip where I would load a bitmap into memory and pan through it or tile it, and that actually feels pretty reasonable.

Except that once I moved from 60 LEDs to a 144 LED strip and I replaced the 60 LED bitmap files with bigger files, I started running out of RAM. Even relatively tiny 40k bitmap files were causing problems.

I have some long term reservations. CircuitPython has not really felt any easier to deal with for me than an Arduino for the task of making a light painting staff, even though I’d started out thinking that it was the Arduino side of things that was slowing me down when it was really that I needed to study FastLED a little bit harder. In fact, other than the easy bitmap work, it’s been harder.

I could refactor more code to work a little more like the code in the CLUE demo looks to work and pull rows off of the SD card which would enable me to avoid running out of RAM, but that’s going to make my code a lot more complicated and that doesn’t get me anywhere. Again, if I’m going to make the code more complicated, it’s just as easy for me to work in the Arduino environment.

Given that there aren’t really any Feather boards with significantly more RAM, I decided that the upgrade path was to get a Teensy 4.1. A Teensy 4.1 has an NXP iMXRT1062 processor and it’s got a megabyte of RAM, so even with my inefficient workflow, it’s plenty.

So, I’m going to categorize this as a half-failure because it’s a completely working board for driving a 60 pixel LED staff with bitmaps but I couldn’t get it to scale further.

A year or two from now, this is going to be solidly practical and this particular project isn’t really a reason for you to not try CircuitPython. There are noises that there will be a Feather with a similar processor to the Teensy 4.1 and, if there’s not, there’s almost certainly going to be something else with more memory and CPU than the current crop because progress marches on.