This is the first post for a project I'm working on. The title is mostly a placeholder, as I haven't really figured out a name for it yet.
Anyway, the idea for this project is to create a wall hanging (or perhaps floor-standing that is next to a wall, depending on size and weight) that consists of semi-large pixels using discrete RGB LED's.
This post is going to be really big since this is about a month's worth of ideas coalescing into one post.
Current state of the project:
- Since I've decided on regular hexagons, I also have to deal with the whole square-root-of-3 issue involved. Basically, if a hexagon (if measured from one side to its opposite) is, say, 4", then each side of the hexagon ends up being 2*side/sqrt(3), or 8/sqrt(3), or approximately 4.62" (4.6188021535170061160731902440157...). All the measuring I'm going to be doing are approximations anyway, so this shouldn't be too much of an issue.
- I'm almost positive that I will be making the pixels hexagon-shaped. This has several issues, compared to square pixels. Square pixels can be constructed fairly easily using long, straight runs of whatever building material is used. Hexagons need to have lots of individually-cut pieces attached to something (most-likely a firm backing in my case) attached at 120-degree angles.
- I've settled in on hexagons that are 3.5" across (each side is just over 2"). This seems a decent size (10.6 sq. inches) and a happy medium between constructability and nice, small pixels. As the size of the hexagons gets smaller, the structural integrity of the walls between the pixels becomes less and less.
- For the overall size of the wall, the size I've kinda accepted is 11 wide by 14.5 tall. So, first of all, an explanation of how that even makes sense. Take a regular hexagon (any will do... they're all the same) and orient it so that two of the edges are parallel to the ground. This is how all of them are oriented. Now, take a single hexagon and then place another identical one to its right, one-half pixel above it so that a single of the diagonal edges from each of them are abutted. Now, take another one and put it one-half pixel below the one that was just placed, so that there is a single edge's length distance between the 1st and 3rd pixels. Continue doing this for 11 pixels and this is how wide it is. Do this for 14 times and then take an additional 5 pixels and place them at the bottom of it, so that if the whole thing was folded over, the top and bottom edges would line exactly up. This gives us 11*14+5 = 159 pixels for the entire display.
- I still haven't figured out what to make the walls between the pixels, or how big they should be. I'm open to any suggestions. Wood would be the cheapest, but since I'm working with slightly small pixels, I need to keep the width of the wood narrow. This doesn't work to well with wood, but as long as I would use nails and glue instead of screws, I should be OK.
- For the outward-facing window, I found a 7'x3' piece of 1/4" acrylic at Ax-Man (I was lucky to find it). It's irregularly-shaped and about 2' of the 7' aren't really usable for a top window, so that leaves me about 5'x3'. That's fine because I can have a decent piece to test stuff out with. I also picked up some coarse- and fine-grain sandpaper blocks to use at improving the diffusivity of the acrylic. It's normally completely clear (which is what you want most of the time), so I tested sanding the clear surface down and it seems to have worked decently. I might be playing around with different things, based on how well the 1/4" works.
- I've come up with a way to map square pixels into hexagonal pixels. There's a small amount of distortion (each square pixel is stretched horizontally by about 15%) because of the whole square-root-of-3 issue again. Basically, the hexagons are split into two groups: the A-set and the B-set. The A-set gets its shade from 2 side-by-side square pixels. It takes 5/6 of the color from one and adds it to 1/6 of the color of the other to get its approximated color. For the B-set, it is slightly more-complicated (because of the half-pixel offset). Each B-set pixel gets its color from a 4-square of square pixels. It takes 5/12 of one pixel, 5/12 of the pixel directly below it, & 1/12 of each of the two remaining pixels.
- Now, naturally, this will look like ass on anything but a large number of pixels with a small size. So why do it at all you ask? Why even do hexagonal pixels at all? Because they're cool. That's why. Also, you can get some nice radial patterns with them, instead of the jaggy ones you see with square pixels. Hexagons are a better approximation of circles (the tightest packing of circles in a 2-d space is the same as what hexagons end up being) and they're one of the 3 regular polygons that tile perfectly with just themselves (equillateral triangles and, of course, squares are the other two). There are 3 straight lines of pixels, as compared to just 2 with squares. Granted, they're all at 120-degree separations from each other, but there are 3. Plus, squares are too easy. How am I supposed to have fun with bland-looking squares? Everything we look at is rectilinear, so why not spice it up a bit, huh? That's what I thought. So why not equillateral triangles then? Mainly, because I haven't really thought about it until now. After careful consideration, I'm not really sure myself. I will have to keep that in mind.
- After "much deliberation" (a.k.a. very little), I've decided to use Atmel's AT89C5131A-M microcontroller (uC). It is a USB C51-based Microcontroller with 32K Bytes Flash, 1K Byte Data EEPROM, 1280 bytes RAM, 7 USB Endpoints (not entirely sure what this means yet), TWI (Two-Wire Interface), SPI (Serial Peripheral Interface), UART (For RS-232), PCA (Programmable Counter Array). Of main use to me are the USB interface and the TWI (explained below). This will handle all of the signals to/from a computer and then dish other signals out to the LED drivers (over the TWI).
- For my LED driver setup, I've decided to go with Maxim's MAX6964. It's a 17-output LED driver with 4 per-channel bits of intensity control. It can sink up to 50mA per output, or 350mA max (for my uses, it will be a limit of 20mA per output). It accepts signals over a 400kbps TWI (hey, how about that... the uC I've chosen has just such outputs... I wonder if they're compatible...). What's annoying about it is that it's in a 24-pin QSOP surface-mount package (that's 25 mil [1 mil = 0.001"] spacing between the pins).
- I've ordered a few different intensities of LED's to test with, so I still haven't figured that out quite yet. No real updates here.
- To go along with the uC, I ordered (and received) a starter kit (AT89STK-05) through Digikey. The board is a pretty sweet package. It's roughly 4"x3", has RS-232, USB, TWI, SPI, and "LPC Test Mode" (not really sure about the uses for that) connectors on it, as well as 2 48-pin headers for pretty much every pin on the chip (and board) and a DC-in jack and a vertical header for a 9V power supply. There's an on-off switch, a switch to tell FLIP (explained later) how to put the data on the chip, a reset, INT0 (interrupt), ISP (In-System Programming), and USB Unload buttons for various testing purposes. There're 2 LED's for general status indication, 2 LED's for the RS-232 port (Rx & Tx), and 4 general-use LED's that are tied to some of the P3 output ports. The entire thing is clocked with a(n included) 16 Mhz crystal. All-in-all, a pretty good investment. I can do most of my testing directly with this board, instead of kludging up something on breadboard.
- The starter kit board came with FLIP (the acronym meaning eludes me and is meaningless anyway), which is Atmel's programming utility. You have the ability to program it directly through the USB port (it's also powered off the USB port). No need for RS-232, PIC programming socketes, or higher voltages. Fuck that bullshit.
- I have come up with the beginnings of a board to use in the actual wall. No way am I going to use the starter kit board in the actual installation. Because it was free, I have been using ExpressPCB's software to design the schematics and PCB. They are sorta tied together (you can load the schematic you created in ExpressSCH with ExpressPCB) and it will highlight pins on the same net, so you can visually check it for errors. The board I've got layed out is in a nice 2"x2" space, with 4 1/8" mounting holes in the corners, the PLCC-52 socket for the uC; a USB connector; a current limiting circuit for the USB port; a voltage regulator (to bring any power down to 3.3V); an external voltage input header; a crystal socket; power & ALE status LED's; TWI header pins; reset, SPI, & USB Unload buttons;regulated power, ground, & reset signal header; a switch for selecting the voltage source; and a power switch. Almost all of the design is taken directly from the starter kit electrical schematic drawings. Kudos to them for providing it. Pictures will come as soon as I get somewhere to put them.
- With 159 pixels and 3 LED's per pixel, that makes 477 LED's. Each driver chip supports up to 17 LED's. So My current approach is to do 5 pixels per driver chip, making 15 LED's per chip. 159/5 = 31.8, so I would need 32 driver chips. Each driver chip can be one of 4 unique addresses, so that would "normally" mean that I would need 8 uC's to drive the entire wall. This is A) ludicrous, B) expensive as hell (at ~$10 for each uC chip), and C) way overkill for what the uC can do. But wait, there is hope! The pin that defines the address to be used can be set to power, ground, or one of the two signal pins. Hm... what if I just connected an output port from the uC directly to this port and then just normally set each port to ground and then pulled up each driver chip individually to power as I need it. That way, I can even send the same signal to multiple driver chips at the same time! (You'd almost think I thought of this before or something). As luck (yeah... right... luck...) would have it, there are exactly 32 usable output ports on the uC (there are 34, but I am using 2 for the TWI). So with the size of the wall at 11x14.5 pixels, I can use exactly 1 uC to drive the entire thing. Crazy how it all falls into place like that ;)
- I really haven't done much in this arena yet, as it's the section that's the furthest away and the section that I'm least-worried about. I wrote a quick program in C (yay... no need to learn C51 assembly at this point) to randomly (using a wonderful 15-bit pseudo-random number generator in their stdlib library) turn the LED's on the board on and off. Very cool and very simple.