Shapeoko 2 Customizations

Artwork Gallery

CNC Christmas Gifts 2015

Creating a 1 meter RGB POV display with Raspberry Pi and LPD8806 LED strips

First attempt to display a PNG image.

I set out to create a large POV display for a local quarterly art installation called The Urban Art Project, in Great Falls, Montana.  The space is 8 feet wide, 5′ 8″ tall, and around 17 inches deep.  Two 1 meter rotors fit nicely in the space.

3d Printed Parts
CNC Machined Parts
A/C Motors Tested
Possible Enhancements
Photo Gallery


I wanted a project that would incorporate mechanical, electronic, and software elements, and eventually deliver a canvas to build artistic creations upon.  The spinning POV display has caught my attention for years because of it’s apparent simplicity, yet it requires all of the disciplines listed.  Based on what I’ve found with Google, there aren’t very many large format RGB displays.  Challenge accepted!


  • Must run continuously for 90 days.  Ideally longer.
  • Must withstand temperatures of 100 F degrees.
  • Must achieve a minimum of 5 frames per second.
  • Must achieve an angular resolution of <LEDs across> * pi, or at least 188 divisions.
  • Display PNG, JPG and animated GIF images.
  • On-site software update via WiFi.

Hardware Used

  • LPD8806 LED strips with 60 LEDs per meter.  LEDs the full length of the rotor.  This seems like a no-brainer, but it reduces the needed RPM for good persistence by a factor of 2.
  • WS8212 LED strips were used to prototype before I had the LPD strips.  They proved to be too slow for this display, just as Adafruit’s product page advised.
  • Raspberry Pi A+
  • 3.3v -> 5v level shifter for SPI communication and WiFi dongle.
  • Level shifter and power/led/sensor connections are mounted on an Adafruit perma-proto board.
  • Hall effect sensor US5881LUA.
  • Timing belt and pulleys to reduce A/C motor RPM and increase torque to rotor.
  • 6 conductor (2 amps each) 12mm slip ring.  2 conductors for +5v, 2 conductors for ground, 2 conductors for SPI communcation.  Rated to 250 RPM.  These units worked great for around 3 weeks when overdriven to around 500 RPM.
  • Custom built 4 conductor carbon brushed slip rings.  These worked adequately for the remainder of the project.  Very noisy digital connection.
  • Carbon fiber arrow shafts for rotor arms.
  • Machined aluminum rotor hub.
  • Skateboard bearings.
  • USB Wireless Adapter 802.11n/g/b
  • Linksys WiFi router with dd-wrt router configured to bridge from my Samsung hotspot.

3d Printed Parts2015-09-14 11.02.27

  • Timing pulleys (
  • Hall effect sensor mount
  • LED strip mount to arrow shaft mounts
  • Motor fans
  • Bearing blocks for main rotor shaft.

CNC Machined Parts12015154_10153610779218088_4908512399410608213_o

  • Rotor hub
  • Motor mounts
  • Enclosure legs and back

A/C Motors Tested

  • Random 9″ fan motor – I threw this one out.  Similar to the 4M076D, but smaller.  Way underpowered.  4:1 pulley ratio resulted in around 200 RPM at the rotor.
  • Dayton 4M076D – 1/40 HP, 3000 RPM – underpowered, cooled with a desk fan, with 7.8:1 pulley ratio the rotor turned at ~250 RPM.  Got almost too hot to touch, but not as bad as the smaller, similar motor.  This was a bargain find at a local motor shop.
  • Dayton 3M563B – 1/40 HP, 1550 RPM – plenty of power but no built-in fan, so it required additional cooling.  This was a used motor that eventually died.  I decided to not pursue this one because of the cooling requirement.
  • Holmes 20″ box fan (Target) – Currently testing with a 6.5:1 pulley ratio.  I added a 120mm fan to the front of the 30 tooth pinion.  Rotor speed is ~320 RPM, and the motor is comfortably warm to the touch after over 1 hour.  Overnight tests showed excessive heat.
  • Century Motor # 419 – 1/15 hp 1550 RPM 115/230V CCWSE TEFC 3.3″.  This was the final production motor.  I ordered two and both ultimately failed.  The retainer clips on the main shaft wore out.  I was able to rebuild them by shimming the axle with washers.  These worked sufficiently but were not highly reliable.


The software stack was based on a standard Raspian image.

Initially I developed test routines for the LPD8806 and WS8212 strips using C code samples.  These were great for quick testing and making sure things worked.

Once I incorporated the hall effect sensor and prepared to display images, I needed access to GPIO and more rapid development.  I started using Python and the AdaFruit GPIO library which supported GPIO interrupts.

Pure Python was sufficient for test patterns and displaying static images.  I was able to achieve around 150 divisions per rotation at 250 RPM, using the PIL and Pillow image libraries.

Once I started working on GIF animations it became clear that I needed more speed. Python was doing too much behind the scenes to achieve decent performance.  I started work on a C-based framebuffer extension for Python which: initialized the SPI bus, set up double buffering for smoothness, monitored the hall effect sensor to determine refresh rate, calculated angular lines interpolated from the frame buffer, and finally, fired those arrays of data down the SPI bus to the strips.

The Python script imported the C extension and used the frame buffer directly via the PySDL library.  I could then use the SDL drawing routines to draw lines, text, and images directly into a fast and simple RGB buffer.

The Python+C implementation yielded over 400 divisions per rotation at 500 RPM – a huge improvement over pure Python.

Possible Enhancements

  • Rotary encoder – Every motor exhibits a certain amount of jitter in it’s rotation speed.  Using a single Hall effect sensor allows the software to determine the rotor’s position and speed once per revolution.  So you occasionally see the display rotate a few degrees for a single frame, then recover.  This effect looks cool and retro, but could be prevented.  Using a rotary encoder would allow the software to correct speed variations many times per revolution.  Combined with a Hall effect sensor, a very steady image could be created.
  • Properly rated motors – Using inexpensive motors with homebrew cooling allowed this project to happen, but if money were no object, the clear choice is a TEFC (enclosed, fan cooled) motor of appropriate size.  These start at around $100 each.  I ended up paying $115 each for motors that were still lacking.
  • More LEDs – Using LPD8806 LEDs, a C language frame buffer and SPI driver, twice as many LEDs can be driven.  Especially on a faster Raspberry Pi.  The current setup incorporates a delay after each update to minimize CPU usage. An FPGA is a cool exercise, but is not strictly needed.

LED Light Suit

This LED light suit was created for Halloween, 2014, and was developed over a period of 2 weeks.  6x 5 meter waterproof white LED strips were used, along with an Arduino Pro Mini, piezo microphone and amplifier, all running from a LiPo battery.  The strips were sewn onto track pants and jacket, and worn with snowboard boots, gloves, and goggles.

Custom Arduino firmware offered several modes of operation, including sound activated, pulse, steady on, and off.  A remote in the sleeve allowed control of mode, brightness, and sound sensitivity.  The firmware was created in the Arduino IDE.

A custom PCB housed the Arduino Pro Mini and 6 Mosfet transistors to drive each of 6 PWM channels at up to 2 amps.  A custom case was 3d printed for the electronics which fit into the front pocket.

BeagleBone Black Arcade Machine