Thanks to the Python Imaging Library, the DotStar Pi Painter supports many common image formats and should read most any JPEG, PNG or GIF image, among others. No special size constraints or pre-processing is needed, just place files in the root directory of a USB flash drive (do not put them inside folders, the software won’t look for them there).
Images will be loaded in alphabetical order.
Each column of the image is “painted” left-to-right. If you need something else (like top to bottom), you’ll need to alter the image file (e.g. rotate 90° counter-clockwise) or tweak the software to perform the desired operations after loading.
Depending how your painter is built, you may need to tweak some values in the DotStarPiPainter.py script.
There’s a section near the top of the code that’s commented “CONFIGURABLE STUFF.”
num_leds is the total number of DotStar pixels in the LED strip.
pin_go, pin_next, pin_prev, pin_faster and pin_slower are the GPIO pin numbers to which buttons are connected to begin painting with the current image, load the next (or previous) image, and to set the paint time faster or slower. A momentary pushbutton should be connected to each of these pins, with the opposite leg connected to ground. If you installed the gpio-halt utility, do not use the same pin number for the painting controls.
order is the R/G/B color order used internally by the DotStar strip. Usually this will be 'brg' (with quotes)…but if you have some early DotStars (before 2015), use 'gbr' for proper colors.
vflip indicates whether the input end of the strip is at the bottom ('true' in quotes) or top ('false'). The Pi should be close to the strip input, so I placed this at the bottom to make the center of gravity lower.
spispeed sets the SPI data transfer rate, in bits per second. The default is 12 MHz (12000000). If you find the image “glitching,” you may need to try a smaller value here, like 8 MHz. Or you can try pushing a little higher for better dithering, but no guarantees.
A little further down, gamma and color_balance set the gamma correction curves and maximum brightness for red, green and blue.
power_settings is a list of two values, the average current (in milliamps) that the battery can sustain, and a peak current that it can provide for very short intervals (if in doubt, set peak to the same value as the average).
IMPORTANT: while some battery packs will have a rating like “2.1 Amps,” the output voltage drops slightly (on both USB ports) as current increases. If the voltage drops too low, the Raspberry Pi locks up and the LED strip will be stuck. If this happens, pull the plug and reboot the system, then edit these numbers to smaller values and try again.
The original NeoPixel Painter had an option for adding an optical rotary encoder to provide absolute positioning; with the light-painting rig installed on a bicycle or other wheeled motion base, it then had the spatial sense to provide a consistent aspect ratio for images and even multi-image animation.
The problems with bringing this same feature to the Pi are many: a quality optical rotary encoder is damn expensive, it would require some hairy C code to process the encoder input fast enough, and depending on the encoder it might not have sufficient spatial resolution to work well with the DotStar Pi Painter’s X-axis image interpolation.
A different tack was taken. Or, as they say, “It’s a UNIX system, I know this!”
Although we’re running the Raspberry Pi “headless,” it’s still possible for code to read the position of a mouse connected to one of the USB ports. If we can physically install an optical mouse just so (e.g. a millimeter or two from a tire’s sidewall), it might be a good enough position sensor…
A quick kludgey test with tape and a spare-parts-drawer mouse looks promising enough that I've added this feature to the code. If a mouse is plugged in when the DotStarPiPainter.py script starts, it’ll use the mouse position for painting speed (rather than a set time interval). Could still use some refinement, but it’s a start.
It’s very experimental and there’s some “gotchas” to be aware of:
- Mice can track only so fast. Perhaps a maximum of 1 foot per second, it totally varies from one make and model of mouse to another.
- Some mice are even more sensitive to voltage sags than the Raspberry Pi. If painting a particularly bright image, the voltage may dip low enough that the mouse drops the USB connection (though the Pi is OK). Currently the code doesn’t handle reconnects. Reduce the power_settings values in the code by 100 to 200 milliamps to ensure there’s enough overhead for the mouse to always work.
- The LED on the underside of the mouse might illuminate the wheel and create light streaks in photos (some mice even have corny top-side lighting). You may need to block this somehow.
- Physical installation is quite fussy, needs to hover just above or alongside the tire (most optical mice won’t work against the reflective wheel rim). Later I plan to make a nice 3D-printed bracket to hold it securely in just the right spot.