The first concepts I had were:
- Keep the hardware modular in order to be able to design & test small components separately.
- Stream the image or animation to the LED display from a micro-SD card, so that: there's plenty of storage for rich animations, I will not need to worry too much about complicated compression schemes, and it would be really easy for anyone to deploy new animations.
- 256 LEDs per column, 512 columns per revolution, 50 revolutions per second = 6.55 Mbit/second = 39us per column.
- Serial communication between the motherboard and the LEDs to avoid having to run lots of wires and use a lot of IO on the microcontroller.
- Daisy-chain several LED boards, so that I can create an (almost) arc-shaped row of LEDs.
- Synchronize LEDs with rotation angle by using an IR LED on the base of the globe and an IR sensor on the motherboard.
- In circuit programming and UART connections on the motherboard for development & debug.
LED BoardsI started by designing the LED boards. I needed 16 boards of 16 LEDs each, which can be daisy-chained. My idea was one 16-bit serial-in parallel-and-serial-out shift register, one 16-bit latch and 16 LED drivers (transistors) per board. Apparently, this wasn't only my idea, and I soon found that there are off-the-shelf ICs that do just that, leaving me mostly with designing a very simple board that does little more than routing. A simple survey found that the TLC5927 of TI is a perfect match. I'll take this opportunity to really thank TI for being very generous with free samples - 20 pieces of this IC got to my home with a courier within 3 days!
Here is the circuit schematic and (double sided) layout for the LED boards:
And a picture of the home-etched board (these are actually two pieces connected):
BTW, this board has a shiny silver finish, as I finally managed to get my hands on Liquid Tin, after a trip to the US. No more rusty copper look...
Once built, I quickly hooked it to my loyal PICMAN for testing. I'm really starting to like this guy...
As it turns out, the best way to output a stream of bits out of a microcontroller is by using the SPI hardware. With the PICMAN's PIC18F4553, you can reach an effective rate of 12MHz.
Here's a video of the first experiment I did, a simple blinking pattern on 5 LEDs:
Then it was time to have some fun with POV effects, so I wrote a simple program that would display a Smiley pattern when the board is wiggled from side to side. It worked! Unfortunately the camera doesn't capture the effect as nicely as the human eye, but in this video you could still see the idea:
MotherboardFirst issue to tackle was communication with the SD card. After searching the Web for information, it turns out these devices support an SPI-based interface of up to 25MHz. I took a micro-SD to SD adapter to use as a socket, and soldered pin headers to it. Than I stuck it on the breadboard, connected it to the PICMAN and started playing around with it. Careful! SD-cards are 3.3V devices, so when working with a 5V microcontroller a simple voltage divider on the output pins is needed. After some messing around with the software, I was able to read data blocks from the device.
Now, how do you stream data from a micro-SD card to the LED boards at 8MHz (cheaply)?
A simple cycle of read-from-card -> write to LEDs would naively take at least a few cycles per-bit, which would require a rather fast microcontroller to support 8Mbit/sec. Fortunately, both the SD card and the LEDs speak SPI, so I had an idea to connect the serial input of the LED board directly to the serial out of the SD card, have the microcontroller initiate a read and then send a latch signal to the LEDs at the right time. This way, the microcontroller doesn't have to bother looking at the incoming data. It turned out to be a really neat trick, and I was able to easily stream data directly from the SD card @8HZ, using a cheap ATmega8A clocked at 16MHz!
From this point the design was rather simple: I added a reset button, UART and programming connections and a connector to the IR sensor. I also used a couple of fast MOSFET gate drivers (TC4427) to function as line drivers for the long lines driving the LEDs.
Here is the schematic and the (double sided) layout of the motherboard. Ignore some 0 resistors in the schematic, used solely as "bridges" above traces for solving layout constraints:
I used the PICMAN as an AVR programmer to program the ATMega, as described in my earlier post.
Hurray! A few long nights later, and I had a working system, able to stream data from the SD to the LEDs while synchronizing the rate to the input from the position sensor. In the video below, I'm using a push-button to simulate the IR sensor input. I generated a simple image file which generates a 32 LED scan pattern. You can see that the scan rate adapts to the rate of button pushes:
CaveatsThe motherboard has several problems that I'm intending to fix in the next version. The first problem is related to SD card latencies. After performing some timing measurements here's what I found:
|From issuing read command and until the first block is ready||1340|
|End of block until the immediately following block is ready||6|
|End of block until non-following block is ready||380|
The first value is not very interesting, since it only happens once when the program starts running.
The second value is interesting, because it happens every time we move from one block to the next - every 512 bytes = 4096 bits = 16 columns. This means that when we display a column that is in the beginning of a block, it will take us 6us (latency) + 32us (256 bit @8Hz) = 38us. Just below our spec of 39us/column!
The third value is problematic, because it means that every time we reach the end of the image, if we want to jump back to the beginning of the image we'll be late by about 10 columns. So my idea for solving this was to copy the first (or last) block of the image to the microcontroller flash when the program starts, and then stream this block from flash while the next one is fetched. Alas, I suddenly realized that the way my hardware is built, the LED serial-in is hard-wired to the MISO line, i.e. the SPI input of the microcontroller, and thus I can't stream data out of the microcontroller to the LEDs, only from the SD! As a temporary workaround, I'm just skipping the first block altogether and in order to make sure that those missing 16 columns don't happen too often, I'm just replicating the image many times on the SD.
Some other problems with the current design are not as bad, but I might as well address them on the next version. Those include: the translation from the microcontroller's 5V to the SD's 3.3V creates a really messy layout; the ability to stream data directly from the microcontroller is nice-to-have regardless of SD latency; ATmega8's are no longer cheaply (under $2.5) available; I really regretted not putting a general purpose button and LED on the board for some basic user interface and debug.
To address the first problem, the next version will include a mux to select between MOSI (microcontroller output) and MISO (SD output) as LED inputs.
To address the second problem, I'm moving to PIC18F23K20, which is $1.70 from Digikey, works on 3.3V, 16MIPS and 16MHz SPI, does not need an external crystal/resonator to operate at full-speed. In addition, the PICs don't suffer from some of AVR's annoyances, such as the ability to brick the chip by setting wrong fuse values and the sharing of the serial programming lines with the SPI. So much goodness that I just had to buy 10 of those...
I intend to first run a full system (with the said workaround) before designing the new motherboard, since I might encounter a few more problems down the road.
PowerQ: How do you transfer power to a circuit that's turning?
A: A slip ring.
A slip ring is simply a conductive ring attached to the rotating shaft and a stationary conductive "brush" the keeps in contact with the ring, but slips on it with minimal friction. For transferring power, you would need at least two of these.
Due to the nature of this connection, it is very noisy, and thus not generally suitable for data transfer. This is, by the way, why I put the motherboard on the rotating side. To filter out any noise, or short discontinuities in power, I used a big capacitor (2200uF) on the motherboard, in addition to 0.1uF decoupling capacitors close to each IC. Hopefully, it will do (haven't tried yet).
I made the slip ring myself: turned 2 aluminum rings and a plastic isolating sleeve on the lathe. Then I found that soldering to aluminum is really hard, so I used a conductive glue instead, and buried everything under a lump of hot melt glue.
Here's what the finished module looks like:
Next: POV Globe - Part IV - Software & Data