Monday, August 9, 2010

POV Globe - Part III - Electronics

This is in continuation to: POV Globe - Part II - Mechanics

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.
I started designing the electronics by drafting the following specs:

  • 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 Boards

I 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:

Motherboard

First 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:
A micro-SD to SD adapter is soldered "standing" to the side of the board and reinforced with some hot melt glue.

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:


Caveats

The 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:
OperationDuration [us]
From issuing read command and until the first block is ready1340
End of block until the immediately following block is ready6
End of block until non-following block is ready380
Note: A block is 512 bytes. All read operations are always done in full blocks.

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.

Power

Q: 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:
And this is me, making this ring, in a really beautiful panoramic photo taken by Omer Calev:

Next: POV Globe - Part IV - Software & Data

9 comments:

  1. Hi, impressive work.
    A note on your note regarding block read size : you can set the read block size from 1 to 512 bytes.
    There is however a limitation : the read operation will fail if the 'logical' block you try to read crosses the boundary between physical (512 bytes) blocks.

    ReplyDelete
  2. Very impressive!

    I particularly like the trick of using a micro-to-regular SD adapter as a socket.

    To help your read latency problem: Have you tried a higher "class" SD card? I know that the higher class cards (6-10) are needed in DSLRs for their higher write rate; do they also have higher read rates? I'm just a noob, but thought it worth a try.

    ReplyDelete
  3. @Anonymous: Are smaller blocks expected to reduce the "seek" latency?

    @GeekDoc: Thanks for the info, I wasn't even aware that there are different classes. Do you have some numbers on the latencies of the higher-class cards (i.e. the respective values to the ones I have on the table above)?

    ReplyDelete
  4. @Ytai
    Not sure about latency, in my case I had to send 250 byte packets to an antiquated device over a serial link at the incredible speed of 9600 bauds ;)
    Just thought it might be usefull to adjust packet size to get a better data structure or easier data management.

    ReplyDelete
  5. @Ytai: I don't have any actual ratings, just the anecdotal evidence that high-performance DSLRs and HD-video cameras require higher class numbered SD cards. A friend tried, and his DSLR won't work with less than a Class-6. Last I saw, the highest was Class-10.

    ReplyDelete
  6. @Ytai:
    Found this on Wikipedia:
    http://en.wikipedia.org/wiki/SDHC#Speed_Class_Rating

    Looks like the speeds jump pretty good between class 2-4-6-10 (5 doesn't get you much over 4).

    ReplyDelete
  7. @GeekDoc: They don't say anything about info, but it's definitely worth the shot, as these cards are rather inexpensive. Thanks for the info and the will to help!

    ReplyDelete
  8. can i get a detail sketch on how to make it, pictures of every step

    ReplyDelete
    Replies
    1. I don't have one, and the actual setup is an ocean away. I can help with any specific questions if you want.

      Delete