Wednesday, January 28, 2009

Shift Registers on the Arduino

Well, I got my shfit registers and some more apt LEDs (that aren't 10mm blue LEDs) to play with. This is a step toward the Arduino flash programmer. I also have the ZIF socket I need and the stuff to make a shield, so really I'm all set to build it. But first, the shift registers.

From Arduino Shift Registers


The Arduino doesn't have all that many output pins. There are 13 digital pins, plus 6 analog pins that can be used as digital pins, but that's really not that many when you're trying to interface with parallel flash chips. First, pins 0 and 1 will be used for serial communications, so you're down to 18 pins. Then you realize the flash chip you want to program has 18 address pins, 8 data pins and 3 control pins. Hmm... not going to fit. You need to use a little external circuitry to extend your pins.

Grumpy_Mike on the Arduino forums recommend that I use an I2C extender chip called the MCP23016. I looked at this, but it was a little to complicated. And by that, I mean I've never used I2C, don't have this chip and didn't immediately understand how to use it. However, it's a better general solution as the 2 8-bit ports it provides are bi-directional, but since I'm only using this to reach the address pins, it's not a problem here.

Shift registers are much simpler. They're a chain of 8 flip-flops in a chip. You clock data into them, 1 bit at a time. Then, you pulse the latch pin on the chip and it saves the state of those 8 flip-flops into 8 other flip-flops that drive the output pins. It's as simple as you can imagine, but to explain it better and visualize this (and even play with a simulation of this), check out www.play-hookey.com. Of interest are the pages on Digital Logic, the D-Type Flip-Flop and of course the Shift Registers. These pages are amazing, they explain everything and give you interactive examples to play with. Really, check them out.

Shift registers can be chained or cascaded. The output of the last flip-flop is exposed on a pin, so it can be used as the input to the first flip-flop on the next pin. For just 3 pins on the Arduino, you can extend your Arduino's reach by any number of output pins. The first pin goes to the input of the first flip-flop, the second goes to the clock input of both flip-flops, and the third goes to the latch pin on both flip-flops. For just 3 pins and 2 external chips, I can reach 16 address lines on the flash chip. The remaining two, I can reach with pins on the Arduino.

For a more detailed account of using shift registers on the Arduino, see this tutorial on ShiftOut and shift registers. I even used the same chips as this (or close enough, I have 74HCT595's), only didn't find this until I encountered a problem hooking them up and started googling. My problem was simple, I just had a jumper in the wrong place. The ShiftOut function is easy to use, and can shift out bits in both bit orders.

There are disadvantages to using shift registers though. First, it takes time to shift out data. The shift registers I have only operate at 1MHz. This means my Arduino (which runs at 16MHz) has to sit in a wait cycle while shifting out bits. As opposed to having 16 digital pins (which are more or less instant), I have to wait to shift out all 16 bits. That might not be an issue with just 16 bits, but it limits the number of shift registers you can chain. It's not an issue here though, so I'm not worried about it.

Anyway, here's a few more pics. Oh, and the code is on pastie.

From Arduino Shift Registers


From Arduino Shift Registers

Website of the Day: Reddit

I've begun to really start looking at all of the features of the websites I use regularly and make an effort to use them more efficiently. I've started with perhaps the least original website you can imagine. Many of you probably use this site every day: Reddit.

To everyone who doesn't use Reddit, it's like Digg only not full of morons. Moreover, it has some really great subreddits that allow you to get to the link you want. If I'm not looking for interesting stuff on Reddit, I'm wasting time on /r/pics or /r/wtf.

But to use Reddit "efficiently," you first have to weed out a lot of crap. There are tons of links I'm just not interested in most of the time. Reddit separates submitted links into "subreddits," or categories. If you sign in and go to the subreddits page, you can see the subreddits you're subscribed to on the right, and a list of available subreddits on the left. Also note that there are thousands of subreddits, not just that one page! Unsubscribe from all subreddits you don't read regularly. I even unsubscribed from the "Reddit.com" subreddit to avoid the general time-wasting detritus that can suck you under. Only subscribe to the subreddits you're really interested in. If you want to see the stuff from the subreddits you unsubscribed from, you can go to them manually and read them.

So, I'm left with just a few subreddits on my main page. I really want to see stuff from these subreddits, and my reddit page is now full of links I really want. Nearly 100% of the links there I want to click on. This is good. No time wasted, no scanning an entire page for a single good link.

Next, vote! Vote up good stuff. Vote down bad stuff. Don't vote on stuff you haven't clicked on (unless it's really obvious it's bullshit), and don't vote on stuff you don't care either way about. Voting is important, especially on the smaller subreddits. On the main subreddits, you can feel like voting on a story that already has 2,000 votes won't do any good one way or the other. That's partially right, but you have a lot more influence on the subreddits not subject to the whim of a million trolls. So vote already!

Finally, comment. It's not hard. On the smaller subreddits, people will read those comments. Again, on the bigger subreddits, your voice may be drowned out, but that's just not the case on the smaller subreddits. Refrain from trying to make witty comments on everything. Unless it really is funny, no one cares. This is not 4chan, your memes are not funny here. Comment on what you thought of the article. It doesn't take long, and it can spark some really good discussion.

There you have it. It's 10 minutes of work to get set up, and a few minutes a day of reading good stuff, voting and commenting. You really have no excuse!

Monday, January 26, 2009

Charlieplexing on the Arduino

Charlieplexing is a way to drive many LEDs with just a few pins on a microcontroller. The technique exploits the microcontroller's ability to put arbitrary pins into high impedance input mode, essentially removing its effect (either sinking or sourcing current) from the circuit. The AVR chips can do this, so can the Arduino.

The easiest way to explain Charlieplexing is to just show you. Take a look at this two pin charlieplex network. The LEDs are connected in opposite directions. By setting both pins 3 and 4 to output mode, and writing HIGH to one and LOW to another, you can light either LED independently. Setting a pin to HIGH will make it source current, connecting it to +5v, while setting a pin to LOW will make it sink current, connecting it to ground. Since the LEDs are connected in opposite directions, only one will light depending on which pin is HIGH and which is LOW. So, to light LED 1, set pin 4 to HIGH and 3 to LOW.

From Arduino Charlieplex


You'll notice that a 2 LED charlieplex network is not very useful. You're lighting 2 LEDs with 2 pins and you can't even light them both at the same time. However, understanding, building and playing with this will help you understand larger charlieplex networks. You'll also notice that one of the resistors is not needed. The only reason two resistors are used here is to keep with the same pattern as the larger charlieplex networks.

Next, take a look at this larger charlieplex network. It's using 3 pins, so now there are 3 possible pairs of LEDs: pins 3+4, 4+5, and 3+5. To address any particular LED, put any pins not directly connected to the LED into input mode, essentially removing it from the circuit. You've reduced the circuit to a 2-pin charlieplex network that you can manipulate in the same way as the previous example. To light LED 5, which is addressed by pins 3+5, first put pin 4 into input mode. Next, set 5 to HIGH and 3 to LOW. Only LED 5 will light.

From Arduino Charlieplex


The natural progression to 4 pins is simple. There are now 6 pairs: 3+4, 4+5, 5+6, 3+5, 3+6, 4+6. To address any particular LED, put the two pins not directly connected to it in input mode and use it like a two pin charlieplex network in the first example. To light LED 9 (which is connected to pins 3+6), put pins 4 and 5 into input mode. Next, set pin 6 to HIGH and pin 3 to LOW.

From Arduino Charlieplex


The major limitation of charlieplexing is the inability to light more than one LED at a time. If more than one LED must be lit, you have to switch between the LEDs to be lit very quickly. This isn't very hard to do though, so it's not that much of a limitation. However, the amount of time any LED gets lit is proportional to the number of LEDs lit. If you have a very large LED matrix with every single LED lit, you may be able to see the LEDs flicker. In general, if an LED isn't being lit at at least 50Hz or higher, you'll be able to see it flicker. Also, since the LED is only being lit for a short period of time (a very low duty cycle), it will appear dimmer than it actually is.

However, it does save you significantly on external components. This LED matrix requires only 4 resistors. If I were using 12 pins, it would require 12 resistors. This can make it easier to make boards with charlieplexed LEDs, though the routes for the network itself are more complex.

Here are some pics of the charlieplex array I made. It's 12 big fat blue LEDs. Those are 10mm LEDs, which I ordered by mistake. However, they were also the only 12 I had of the same type, which is important as I'll explain after the pics.

From Arduino Charlieplex


Choosing your resistor size is important. If you go back to the 3 pin charlieplexing array, you'll see that when you light LED 1, there's an alternate path from pin 4 to pin 3 through LEDs 4 and 5. If your resistor is too small, you will have enough voltage to drive 2 LEDs in series, so LEDs 1, 4 and 5 will light. The fact that I used blue LEDs didn't help either, as they work on a slightly larger voltage range than other LEDs of longer wavelengths.

To choose your resistor, use the normal calculation to choose an optimal resistor size for the LED at 5v. My blue LEDs want 20mA @ 3.2V, so by using Ohm's law, I calculate resistance as 3.2v / 0.02A = 160 Ohms. Since there are two resistors on any pair of pins, divide this in half for 80 Ohms. Since you probably don't have resistors of this value, go slightly higher. To prevent LEDs on an alternate path from lighting up, I had to use 100 Ohm resistors. You'll want to find a resistance high enough to prevent LEDs from alternate paths from lighting up, but as low as possible if brightness is an issue.

So anyway, here's the code I used. It's not the most sophisticated, but it works. I'm going to re-do this in AVR assembly on the ATTiny13 anyway. Blogger doesn't like to format code correctly, so here's the code on Pastie.

Wednesday, January 14, 2009

Programming Flash Chips

I dug some Flash chips off a few old motherboards, and I wondered how difficult they would be to interface? It turns out, it's not that difficult at all.

I was lucky though. Some flash and eeprom chips require high voltage to be able to program, this one I have here requires only 5v. It's a 39SF020 flash chip. So how to program it with the Arduino?

The first problem to solve is accessing all the pins from the Arduino. The flash chip has 18 address pins, 8 data pins and 3 control pins. The Arduino just doesn't have this many pins, so you have to extend the Arduino's capabilities a little.

So I draw up a little schematic using some serial in parallel out (SIPO) shift registers. A SIPO shift register is a number of cascaded or chain flip flops. The input of the first flip flop in the chain is exposed to you, however the input of the other flip flops are connected to the output of the flip flop preceeding it in the chain. Also, the output of the final flip flop in the chip is also exposed on a pin, so you can use it to chain another chip onto the end of that chip. Each flip flop also drives an output pin, so the state of the flip flops are always being output. Using flip flops, you can change 2 pins (1 for data to the flip flops, another to clock it all) into literally as many as you want.

My first attempt at designing this on paper was a big mistake. I decided I'd try to use as few pins as possible from the Arduino. I chained up 4 shift registers to reach all data and address pins using only two pins. However, I realized that the data bus is bi-directional, the data bus has to be both read and written. In order to do that, I had to manipulate the output latch of the shift register on the data bus so it'll go into high impedence mode when I need to read it. Then, since I didn't want to use many pins on the Arduino, I also used a parallel in serial out shift register to read the data bus. It would have worked this way, but it would have taken 5 chips in total, and that won't fit on a proto board at all.

It was much easier to use just 2 shift registers to reach 16 of the address pins, and then use pins on the Arduino for everything else. It takes only two chips, but it uses just about every single pin the Arduino has, including re-assigning the analog pins to digital pins. And the best part, it'll fit onto a shield without too much work. A little work to overcome the non-standard spacing of the Arduino's pin headers, and I have all the stuff I need (except the ZIF socket and shift registers) in my junk bin.

As for programming the chips, it's pretty easy. Programming the chip involves putting commands on the data and address pins, pulsing some of the control pins low and waiting a set amount of time. That part looks pretty easy.

I'm pretty sure I'll be able to program all kinds of chips with this as well. There's a JEDEC standard that ensures the pinouts and command codes are the same for these chips. I looked at the datasheet for a similar chip made by AMD, and it all looked very familiar. I think any differences (except if the chip needs 12v to program) will be in software.

One more thing to note: shift registers are slow. It takes time to shift out 16 bits. Not much time, but if timing is really important, shift registers might not be the right thing to use. Another option is the octal latch. An octal latch has 8 inputs, 8 output and a latch pin. When you pulse the latch pin high, it will latch the 8 input pins into the inputs of 8 flip flops attached to the output pins. Using just 8 pins on the Arduino plus one pin for every latch chip you need, you can achieve much faster outputs.

There's even more options here as well. One chip made by Microchip uses the i2c bus to provide 2 8-pin bi-directional ports for just 2 pins. Multiple chips can be on the same i2c bus as well, provided you use a few more (up to 3) pins to define which chip you're addressing. This is a much more sophisticated option, and much more flexible. However, shift registers are easy to understand and can be as cheap as 25 cents each.