The Ravenna Ultra-Low-Altitude Vehicle is a treehouse equipped to explore the lower frontier of the troposphere.
Read: in chronological order newest entries first
Read about: All entries Jon's build log Jeremy's electronics log Grandma Jan's flight suit
Fixed TWI
Sunday, March 14, 2010 -- jelson

Jeremy:

I have a pile of other plans, including getting the rocket to work. Which I did. The rocket works. I'm 99% certain if you go to the back yard and reprogram it, it'll work.
Jon:
Well, my friend, I'll take those odds, because you're right! Woohoo! I'm sitting in the R-ULAV right now. svn up, make, attach cables while making, and everything just works, right out of the repository.
Jeremy:
The photo shows the test rig I used to get the rocket to today's glorious state. Center: sender and receiver boards running twitest. Left: My new TWI bus board (v2!), with extra headers for test probes and even a power light. Back: the Rigol scope and USBee logic analyzer. Center: two programming boards.

Cost of all this gear: $800.

Getting the rocket to work: priceless.


Got TWI working!
Sunday, February 21, 2010 -- jelson

That's a processor programmed as a TWI receiver displaying its output. A 2nd processor is attached that's sending a hello message once per second.

I just checked in a big pile of code. I refactored the network stack so that network.c is strictly packet-oriented, and the framing code is separated (but not working) in a separate file called framing.c, used for underlying physical interfaces that are byte-oriented.

I'm confident enough in this that I'm going to bring CPU1 in tomorrow so Jon can install it.


Getting TWI working
Tuesday, February 16, 2010 -- jelson

Last night I started out on getting the protocol working between rocket processors. It's a two-wire protocol called "TWI" or "I2C" (depending on manufacturer). I'd gotten serial ports working a few months ago for my clock, but TWI is way more complicated. Serial is a basic point-to-point, self-clocking protocol with two, non-interfering one-way channels; using it very simple. Just write a byte, and it goes out. TWI is a bus protocol with lots of flexibility (a.k.a. complexity) for doing things like framing bytes into packets, addressing packets to specific recipients on the bus, and allowing multiple masters to arbitrate for the bus. The processor's datasheet has a 35 page chapter describing how to use it!

I started working through this, luckily with my trusty logic analyzer which has I2C bus decoding logic built-in. (This task would have been impossible without it.) There were a bunch of hard-to-track-down software bugs to work out, but the biggest problem turned out to be an electrical one. For bus sharing, TWI bus members are "open collector" -- that is, the bus needs pull-up resistors so that it is defined as being high if no one has seized the bus. Each TWI bus member can drive the bus low, but the only way to make it high is to disengage the drivers and let the pullup resistor bring the line high again.

The issue was that the resistor had to be small enough that it could "charge" the bus back to Vcc in a timely manner. The definition of "timely" is a combination of the configured bit rate (i.e., how quickly the edge needs to reach its intended value) and the total bus capacitance (larger caps need more current to charge in that time). I arbitrarily picked a 10k resistor, since that's more or less the "usual" value of a pullup resistor, but things were acting very strangely. Out of desperation I searched the internet for advice on how to pick a TWI pullup resistor value, and found conflicting answers. One source said "I've seen values from 1k to 48k". Another said "4.7k is the standard value." Really, how much of a difference could it make to go to 4.7k to 10k?

Out of desperation, I tried it anyway. Watching the logic analyzer's signals go by, things seemed to work for the first time! Then they stopped. Then they started again. I finally decided to get out my new analog scope -- the one we used to diagnose the problems on our other bus -- and there it was, clear as day (image above).

This is a picture of the bus with 4.7k resistors. Wow. Those "square" waves aren't very square. It takes so long to charge the bus that the line isn't even getting all the way up to Vcc before it's time to discharge again for the next clock cycle -- it's about a volt shy. 10k resistors probably were, in fact, right on the edge: just a little bit slower, they charged the bus just a little less -- less than the detection threshold.

I fixed this in two ways. First, I changed the resistors to 2k resistors. Second, I reduced the bus speed from 500KHz to 100Khz (which is the TWI standard anyway). And now, voila!

We're reaching Vc and staying there for a while before it's time to discharge again. Now everything works -- here's the logic analyzer snooping on my first "hello" message from one CPU to another.

You can't quite see it at this scale but there's acking of each byte. The first block ("02 Write") means the master is saying "I want to send a message to node 2". The sliver after that is node 2 acking that it's ready to receive. Then, the master sends a series of bytes, each of which is individually acked by the receiver. Finally the master sends an end-of-message signal and releases the bus.

Yay!

I haven't pulled the TWI all the way through into the networking stack yet but, that's tomorrow's project.


EPB on a real scope
Saturday, February 6, 2010 -- jelson

Jeremy came over this afternoon with his new oscilloscope, and we diagnosed the ribbon cable crosstalk problem.
Here, we're running software that pulses all of the address and data lines (one shown in cyan), but never the strobe line (yellow); yet you can see the strobe line coupling pretty enthusiastically to the pulses.
Four volts of enthusiasm, in fact.

Yup, apparently violating all thirteen rules of capacitative and inductive coupling has resulted in a measurable amount of coupling. Notice also that even the valid signals are wandering -2V to +7.5V, on a system with only a 5V power supply.

Jeremy snipped the strobe line in preparation for replacing with a shielded wire. He measured the effect again -- and we saw 2V of coupling just from the nine inches of ribbon cable leading out of the CPU0 board.

But what really freaked Jeremy out was this: When he measured the strobe line on a board that wasn't plugged into the CPU, it was still coupled! The only coupling was through the power supply: the meteoric slew rate on the signal lines was enough to swing the power supply voltage almost a volt. Ouch.

Our plan is to first install the shielded conductor for the strobe signal, which should reduce the wire-to-wire coupling back down to 2V, which while ridiculous, will probably get the rocket working again. If it doesn't, I'll rebuild the buffer board a third time with JD's proposed resistors to damp the slew rate to something finite, which should clean everything up quite a bit. Here's hoping!


All boards assembled
Thursday, December 17, 2009 -- jelson

Over the past few days I've been soldering together the rest of the final rocket panel boards. Jon put together the 4 boards for his awesome matrix display; I've been gradually assembling the other 8. In reality this was a form of procrastination: I really need to design the audio board, but that requires some careful thought. Late at night just before bed, it's easier to do some thoughtless assembly rather than circuit layout. Pictured at right are the final boards:

  • (top) One of the two Flight Computer displays;
  • (center) Azimuth, Elevation and Roll Angles;
  • (bottom) Lunar Speed;
  • (left) The second HPAM board for controlling 12V equipment.
Including prototypes, I've now assembled about 15 of these boards, each of which has 20 chips and 8 LEDs on it. That's 420 individual components. I soldered the first 419 perfectly. The very last one -- I mean, the very last chip on the very last board -- I managed to solder in upside-down. (face palm) To make things worse, I didn't discover this until soldering the chip completely in. The somewhat violent process of removing it lifted one of the solder pads off the circuit board, breaking that circuit trace. Unfortunately that pin was an important one, so I ended up putting an extra wire on the back to replace the broken trace.


Final Power Board
Wednesday, December 9, 2009 -- jelson

Tonight I soldered together the final power board. It works!

On the far left is the input section. We'll terminate the Romex cable coming through the conduit from Jon's house with a couple of ring terminals that will attach to the board with screws. The input is 12V; a green LED shows that house power is on. Lower left is a 3-pin terminal where we'll attach the master power switch. That will feed power to both of the output sections: 12V and 5V. The 12V output section is just the raw house power, switched but unregulated. It will feed the cockpit lights and the HPAM -- which, in turn, switches power to the thrusters and paint shaker. Power for the 5V output is generated by a switching power regulator and will be used for all the avionics panels. Both output sections have red LEDs showing they're active. Right now the 5V output section only has 5 connectors, but that's just because I ran out of connectors. There's room for 18.

The photos on the right both show the new power board. The second photo shows the new board powering the mission clock panel and was taken with the lights off making the LEDs more clearly visible. Wow, those hundreths-of-a-second LEDs are ridiculously bright! Good thing we moved them from my office wall (where they're distracting) to the rocket (where they're just pure awesome).



The Power Board
Sunday, December 6, 2009 -- jelson

I took a break from rocket work for about a month; it was taking too much time and energy away from "real" work projects. But, in the past few days, I've been getting back to it. Oh dear rocket, you lovable little scamp, I could never stay mad at you! In the intervening weeks, Jon finalized all the rocket software and populated 4 of the circuit boards, so things feel like they're much closer to done now anyway.

Yesterday, I went to Jon's house to help him pull wires through the trench he'd built between the rocket and the basement. The trench will carry compressed air and water for the thrusters, power for the boards, and data between the house and the rocket. (The rocket has more utilities coming into it than my apartment!)

We realized that the next step on the critical path was building a board that would distribute power from the house supply out to all the various panels. We'd planned on having such a board from the beginning -- I ordered the necessary components from Digi-Key 3 months ago -- but hadn't needed to put them together until today.

I had a busy weekend, so only had an hour or so for board-building time. I thought for a while about the best way to construct the power board, drew a schematic, threw it out, drew a 2nd one, and then prototyped it on a breadboard. It'll have a big red power switch, two indicator LEDs, 12 5.5V outputs and 3 12V outputs, with room for future expansion. Some evening this week I'll build the real board.


Planning the final panel
Monday, October 26, 2009 -- jelson

A few days ago, Jon and I sat down to figure out what the final rocket control panel should look like. We'd had vague plans for a while -- a Lunar Distance display here, a Thruster Actuation Status display there. But last weekend, Jon, Alex and I actually put the rocket up (see Jon's Oct 18 entry) so the time finally came to decide exactly which displays would go where, and in what colors and sizes.

I used PowerPoint to draw a dozen different proposed panel modules. Then, one evening after work, Jon and I clambered into the newly risen rocket with a dozen correct-scale printouts of a rocket panel. We cut each module out and pasted the ones we liked all around us. I have to say, seeing all those displays up in the rocket, even though they were just paper, was pretty exciting.

Tonight, I started the process of building all the final boards -- labelling each one with its intended function, and taping all the right colors and sizes of LEDs into it. It feels like we're almost there!


Joysticks controlling thrusters -- it works!
Sunday, October 25, 2009 -- jelson

Today was a big day: I got a big and complicated part of the system to work properly. Even if I stop work today and never assemble another panel, the piece I have working right now would be enough to make the rocket cool. Specifically, I have the joystick controlling the rocket's thrusters (i.e., solenoid air valves).

I don't think I really appreciated how complex this project had become until I sat down yesterday to make this all work. I was shocked to discover that there are no less than 6 separate components that must be chained together in a long line:

  1. The joystick.
  2. A small joystick interface board with two resistors, forming two voltage dividers that can be read using the processor's ADC.
  3. A rocket panel board with a processor on it. The joystick interface board plugs into the CPU board's JOY1 input header.
  4. A display board specially hacked so that one of its latch outputs goes off-board on a 5-conductor cable rather than to LEDs. These 5 outputs go to the...
  5. HPAM (High Power Auxiliary Module), described in an earlier post, which takes low-current, 5-volt control inputs and uses power MOSFETs to switch a high-current 12V supply into up to 4 devices.
  6. The solenoid air valve itself, which takes 12V @500ma.

The past two days were mostly spent building all the special cables to connect the components to each other and writing software. ADC-read voltage values from the joystick are converted into positions assuming the hyperbolic resistance-to-voltage curve shown in the joystick entry. I settled on 40k resistors. The positions are scaled to a value from -99 to +99, with 0 at center. Hysteresis is used to threshold the joystick positions; +/-50 triggers, and +/- 30 releases. Depending on the joystick direction, one of the three thrusters is fired. It all works!

Here's a video showing the whole system:



Building a High Precision Clock
Monday, October 19, 2009 -- jelson

The original bread-boarded prototype of the UART interface to the PC. The extra chip is a MAX-232 level converter that converts between serial port voltages and microcontroller voltages. Also visible is a probe of my oscilloscope.
The final soldered version of the PC side of the clock interface. Serial port data (right) and 5v power (center) are combined into a single 4-conductor cable (left).
The clock side of the interface board. The 4-conductor cable is broken back out into serial and power. The MAX-232 converts the serial voltages down to TTL voltages.
I was away on business travel for 4 days last week so didn't get a chance to do much hardware hacking. But, once I got back, I spent 2 days on a non-rocket use for the v1.1 boards: building a clock! I love clocks, and did my Ph.D. thesis on time synchronization, so this was right up my alley. My plan was to hang it outside my office so people at work would be able to see the cool stuff I'd been working on at home.

Of course, having written a time-sync dissertation, this clock would need to be accurate. My original plan was to signal the start of each second using a single GPIO line, but Jon convinced me to use a full-fledged serial port to send complete time messages. After some resistance (I was afraid the serial port would be too complex) I agreed.

The first step was to establish a data link between my PC and the board. I bought some MAX-232's, which are chips that convert the voltage used by a PC serial port to the voltage used by typical microcontroller. I prototyped an interface board that would take a PC serial port, short-circuit the flow control lines like a null-modem does, and put the 2 data lines into the MAX-232. I wrote code on the controller to configure the UART, accept serial port interrupts, timestamp them with high precision, and enqueue the characters. As a first test, I wrote a simple program that would just read characters and display them. It was surprisingly cool: I could type on my PC keyboard, and see messages scroll across the 7-segment LEDs!

Next, using my newfound power to get messages from the PC to the board, I set out to get my clock to tick correctly. I wrote a small program that runs on the PC which sends a message to the serial port once every minute, precisely at the beginning of the minute, telling the board what time it is. (The PC's clock is synchronized using NTP, via the Internet.) The clock board lets the clock run free in between the messages; when it gets one, it both sets the time and trains its oscillator so that the length of coming free-running minute will be accurate. It annoys me that most time-sync software doesn't do this; usually, they just jump the clock to the right value every few minutes, giving you a clock with a sawtooth pattern.

Finally, I built a permanent pair of small connector boards so I'd be able to feed both power and serial data into a single 4-conductor cable to run from my office PC to the clock.

If this sounds like a project that consists mostly of a hundred tiny little details, you're right. But the result is awesome, and I'd estimate remains accurate to within 20ms of the PC's clock throughout the entire minute between pulses:

It's now hanging on the wall outside my office. If you're ever at Microsoft, stop by 99/2374 and take a look at it!



v1.1 PCBs arrive!
Saturday, October 10, 2009 -- jelson

The Version 1.1 boards arrived from China today! I have to admit, I wasn't quite as excited as I was for the v1.0 PCBs. I guess nothing can ever beat your first time.

The v1.1 boards were more evolutionary than anything else, as you might know if you've read the rest of the entries in painstaking detail. Perhaps the most visible change is that it now supports larger LEDs (0.56", vs the original that only supported 0.39"). Through some clever routing, a single board can take either size of LED, or a combination. v1.1 also have some convenience features: mounting holes, a reset button, more analog-to-digital converter pins now available, a joystick port (a single header with 2 ADC inputs, plus a GPIO input for the trigger button), and so forth.

To the right is a picture I took of the first v1.1 board with LEDs soldered in, showing that both the larger (green) and smaller (orange) LEDs work together. This v1.1 board doesn't have a processor yet; it's being controlled via the data bus by one of the older v1.0 boards.

I also have a glamour shot of my "signature" on the new PCBs. By v1.1 I'd figured out how to add custom silkscreening so I put my name on it.



Reading a joystick
Thursday, October 8, 2009 -- jelson

Oct 4's entry described how the microcontroller will be able to actuate the thrusters. But how does the microcontroller know when? For it to be fun, the pilot (i.e., kid) needs to be able to actually "steer". The obvious choice: a joystick!

After some research, we discovered that old-style PC joysticks are actually just two potentiometers, one for the vertical and horizontal directions. Joystick buttons are just plain old pushbuttons that ground their inputs. This should make it easy to attach a joystick to a microcontroller. In theory.

Step one was finding a joystick. Modern joysticks are digital monstrosities with USB interfaces. We needed a 1990's era joystick, and they were surprisingly hard to find. No one uses them any more. Finally, one popped up on Craigslist for $1 nearby in Redmond, so I biked over there after work one afternoon a couple of weeks ago and picked it up. The 5-year-old previous owner was excited to hear his old toy was going into a rocket ship. I promised him a ride once it was finished!


Tonight I sat down to see if I could get the microcontroller to read the joystick's position. I thought it would be easy; I assumed that the top and bottom of the joystick's pot would be attached to +5V and GND, meaning the output would be some voltage in between, linearly mapped to the joystick's position, that could be easily read by the ADC. But... surprise! It turns out that for some reason, joysticks don't attach the bottom of the pot to GND, they just let it float. They just vary their resistance, as shown in the diagram to the right. The resistance varies between 0 and 100k ohms; 50k is center.


I think the easiest way to sense an unknown resistance when you have an ADC is to attach a series resistor between the joystick's output and ground, then read the voltage on the joystick side of that resistor. The problem is, no resistor value is ideal. This is illustrated in the plot on the right, which shows joystick position vs. voltage for 5 different series resistors: 1k, 10k, 35k, 75k, and 100k. The small resistors let you use the entire range of the ADC, but concentrate most of the precision on a small part of the joystick's range of motion. Higher values are closer to linear, but throw away 3/5ths of the ADC's precision across the board since they only vary by 2 volts. How annoying. I think I'll use the 35k resistor; that seems like a good balance. Unfortunately, this also means needing a small interface board between the joystick and rocket panel with nothing on it but 2 resistors. Again, annoying.

Wait, what am I talking about? Random stray circuit boards scattered around the rocket will just make it better!


The High Power Auxiliary Module
Sunday, October 4, 2009 -- jelson

My beloved rocket panel got no attention for about 2 weeks because of an important October 2 work deadline. But as soon as that passed, back to work!

Today's main project was building a small board that would let the main rocket panel actuate the rocket's "engine" and "thrusters". As Jon briefly describes in his todo list, he's going to run compressed air to the rocket from his garage air compressor. This will power both the rocket's "engines" (actually a paint shaker that will vibrate the rocket for "takeoff"!) and its "maneuvering thrusters" (actually pneumatic engine cleaning guns).

Jon's original plan was to rig up some kind of mechanical valve to let the pilot turn these systems on and off from the cockpit, but I convinced him to buy some $18 solenoid air valves I found on EBay. That gives us the flexibility to have the thrusters controlled both from software and manually by the pilot We're going to write some sort of "launch sequence" program that will fire up the engines and thrusters; once in orbit, the pilot will be able actuate the thrusters using a joystick. Jon was resistant to the idea at first, but as soon as the valves arrived and he saw one turn on his paint shaker, he was glad the rocket's electrical and pneumatic systems would be working as a team!

From my point of view, the plan was to choose one of the eight identical display boards as the controller, leave off one of its LEDs, and use the 8 unused latch outputs as control signals for 8 valves. Unfortunately, the latches can only source 25 milliamps at 5 volts, but the valves need 500 milliamps at 12 volts. The solution: a small board with power MOSFETs, using 5v control signals to switch the larger 12v valve power. More for fun than anything else, I also put LEDs on the board that light up every time one of the channels is active.

Since we only needed one or two of these boards, I just made them by hand rather than getting PCBs professionally manufactured. And, to really give the thing that 50's Fictional Space Program feel, we gave the board a ridiculous name: the High Power Auxiliary Module.

The ultimate plan is to attach them to one of the rocket panel boards. But, I decided (half for fun, and half because it made good engineering sense) to build a small box with manual pushbuttons, and design the HPAM so it could be plugged into either a rocket panel board or the manual button box. For maximum ridiculousness, I used the laser cutter at work to cut the 8 button holes and put a Fake Space Program label on the box. It's the HPAM "Digital Actuator". See, because you press it with your digits. Your fingers. Get it? Yeah, not that funny.

The end result, I must say, is super cool. Here's a video clip of Liesl playing with the button box. Each button press lights up an LED. I also attached a test solenoid to Channel 3; if you turn up the sound you can hear it clicking when she pushes Button 3. I'm heading to Jon's place tomorrow to try it with a solenoid that has real air running through it .... how exciting!



v1.1 PCBs ordered!
Thursday, September 24, 2009 -- jelson

v1.1 of the PCB -- schematic and board layout
Everything in the v1.0 PCB seemed to work, but I decided to go ahead and order the v1.1 PCBs anyway. They have a lot of features that will make life easier and I feel reasonably confident they'll work correctly, given that v1.0 worked so well. So tonight, I spent about 30 minutes putting some finishing touches on the design and sent it to China for production. Most significantly, I changed one of the joystick headers from 4 pins to 5, and brought our one remaining digital I/O pin out to it, so we'd be able to read the state of the joystick button. Once I actually had a joystick in my hand, it was hard to imagine the fire button not doing anything!

I also added a reset button, some nice silkscreened labels on everything, and more generous clearance between pads and vias to make the boards easier to solder without accidentally shorting two nets.

Ever the eternal optimist, I ordered 20 of these boards -- enough for two full stacks, plus a couple of extra for development, or just hanging on my office wall. Why not, they're less than $3 each (plus $90 setup fee and shipping). They should be here October 5 -- something to look forward to after the NSDI deadline has passed!

Here's the final schematic and board layout. Note the schematic is much cleaner once I learned how to attach remote nets just by giving them the same name; the ugly and not-very-informative blue bus no longer snakes its way through the center. Plus, the bus connector's pins are all assigned to a logical name, rather than a microcontroller pin: exactly how it should be, since from revision to revision, we want the mapping of the logical function (e.g., segment select) to position on the bus header to remain consistent, but we don't really care which microcontroller pin is being used to drive the bus.



The saga continues
Wednesday, September 23, 2009 -- jelson

Really, what is failure but an opportunity for future success? Ha.

I have been spending most of my days lately writing a paper for a work deadline coming up, but my thoughts occasionally drifted back to the problem of driving a gauge. A few minutes searching both Digi-Key and Google revealed that, for some reason, high-current digital pots just don't exist. No one makes them. People on the Internet ask where to find them and they're answered with "They don't exist." I don't understand why.

I started to think about taking a different approach. Really, why does the gauge want to see variable resistance? Presumably because it's measuring the resultant current. So, what if I found some other way to vary the current, other than varying the resistance? Transistors are current amplifiers ... might I use one?

People often use transistors as simple switches, because there is such high gain between what you put in the control pin (the "base current") and what flows through the high-current pin (the "collector current"). Put in any reasonable base current, and the collector current gets driven up to the transistor's maximum. This is called "saturating" the transistor. But there's a range of base currents, before saturation, for which small increases in base current give proportional increases in the collector current. I wondered -- could I try using a transistor in this way?

Yesterday, I measured the maximum current draw required by the gauge at 250ma for full deflection. (0 current gives 0 deflection.) It so happens I have some Darlington transistors here that have a current gain ("Hfe") of 20,000. So if I want 250ma of collector current, I'd need 250ma/20,000 = 12.5 microamps of base current. So I need a resistor on the base that gives me 12.5 micromps. Assume base voltage is 5v, transistor's forward voltage drop is 2v. That leaves 3 volts visible to the resistor. 3v / 12.5ua = 240Kohms. I attached a 200k ohm resistor to the base of my transistor, and sure enough, my gauge's needle went to full deflection and drew about 250ma.

Now, on to gradually reducing this current all the way to zero, so the gauge goes through its range of deflections. The easiest way to do this (rather than hugely increasing the base resistance) is to reduce the base voltage, using a pot configured as a voltage divider. That is, 5v and gnd on the top and bottom, of the pot and the base resistor attached to the wiper, as shown in the diagram to the right. I hooked up one of my mechanical pots and, sure enough, turning the pot got the gauge to gradually move between its two extremes!!

Sep 21st's entry showed a gauge moving when I had a mechnical pot attached, too. But there's an exciting difference here. Today's pot is only passing 12 microamps, not 250ma as before. In fact, I attached an ammeter in series with the pot, and it couldn't even measure the current flowing through it (its resolution was 1 milliamp). A dozen microamps is so small that I should be able to pass it through my digital pot, which is rated up to 1 milliamp, without melting it. I'll try attaching that tomorrow and see if it works! This is so exciting: another tool in my toolbox!



The gauge fiasco
Monday, September 21, 2009 -- jelson

Today I worked on the one part of this project that has been consistently dogged by failure: getting analog gauges attached to the rocket.

It's not too hard to find cheap used car gauges on Ebay. A couple of months ago, I paid all of $0.99 (shipping included!) for really cool-looking electroluminescent oil temperature and RPM gauges. We thought they'd be perfect for the rocket's control panel. Unfortunately, we couldn't figure out how to get them to do anything. They'd power up when attached to a 12V supply, but we couldn't figure out what kind of signal to put on the sense line to get the needle to move.

I learned that car part manufacturers don't document their interfaces as meticulously as most other electronics components. If you go onto Digi-Key and buy so much as a 7 cent LED, it'll come with 8 pages of documentation, exhaustively describing its electrical and mechanical properties. Car gauges seem to come with nothing more than a flyer that says "Put 'er in your car! Then go get a cigarette! Yee haw!"

After hours of web research I found a catalog page for a 3rd party fuel-tank sensor that said "Attaches to standard gauge (60 ohm full - 600 ohm empty)." At last, some data! Apparently you vary the resistance on that signal wire. I tried attaching our fancy gauges to a pot with the proper range but the needle still didn't budge. Finally, I speculated that perhaps the gauges were broken and that's why they cost $0.99. Jon took me on my first trip to a junkyard, charmingly named Pull-a-Part, and I paintakingly extricated a couple of gauges out of the dash of an Oldsmobile (I think). Hooked that up to a mechanical pot, and when I adjusted it with a screwdriver, the needle moved. Hooray! It's too bad those gauges are so ugly. The broken EL gauges looked rocket-y; the ones that work just scream "80s sedan".

That brings us to today. How do you get a microcontroller to provide variable resistance? I discovered a clever device called a digital pot that does exactly that: every time you strobe one of its pins, it increases (or decreases, your choice) its resistance among 100 pre-set values. Easy, right? I ordered a few of them last week, and today tried to get one working.

First try: breadboarded a prototype, using buttons to strobe the inputs, and measuring the outputs with an ohmmeter. Seemed to work, but jumped forward a lot every time I pushed the button. My little oscilloscope confirmed that button bounce was my problem (right).
Second try: I attached a capactior and a couple of series resistors such that the cap would slowly charge and discharge, smoothing the signal. It was sure nice and smooth, and was asserted far more slowly (milliseconds rather than microseconds), but the pot still jumped forward by several steps with each button press. Perhaps I need a smaller cap so the voltage doesn't camp out near the threshold for as long?
Third try: hooked the thing up to a microcontroller that did nothing but strobe pins. I hoped the controller would give cleaner transitions than my mechanical button. Much to my amazement, the pot seemed to just slide between its two extremes. What is going on?

Fourth try: the microcontroller and pot were powered off different halves of my power supply; maybe their grounds are floating relative to each other? I tied the two grounds together, and, success! I can now get the pot to increase its resistance by 10 ohms at a time.

Fifth try: I hooked the pot up to the actual gauge rather than an ohmmeter. Everything broke; when I put the ohmmeter back, the resistance was 10 kohm (even though the pot is only rated to go up to a max of 1 kohm!). Tried with a 2nd digital pot; worked with the ohmmeter, then broke when attached to a gauge. I took another look at the datasheet, and realized that the pot was only rated for 5v across its terminals at a max of 1 milliamp. What the hell use is that to anyone? The gauge has 12v from its its sense line to ground and when I hooked it up to an ammeter, it was pushing 250ma through it. Obviously I was just destroying the digital pots.

So ends the saga for now. I need to order some beefier digital pots and try again.

Everything has been working so well on this project up until now, I guess I was due for some failure!


September 20, 2009
Sunday, September 20, 2009 -- jelson

It's 1am Sunday. I've hacked on the boards all day (Saturday) and it's really incredible: they work. I tested

  • The bus & programming header
  • The keypad -- complete with the fix allowing the keypad not to cause two outputs to short, as happened with the protoboard
  • The ADC reading analog dials, complete with exponentially-weighted moving average filter
  • Getting a periodic timer interrupt, which enables all the event-driven software Jon and I are developing.
This evening, Jon was so excited that he used the simulator to write a ton of code that would make modules easy to write, and finally wrote a module that would scroll a message across the LEDs. After a little tweaking I got it to run on the real hardware:

Bang!


v1 PCBs Arrived!!
Saturday, September 19, 2009 -- jelson

Guess what was waiting for me when I got home from work yesterday?



There it is, hot off the Chinese presses -- v1 of the Rocket Panel Printed Circuit Board!

I soldered all the components on, loaded the digit-identifying program onto a new microcontroller, popped it in, and turned it on. It worked on the first try! Isn't it beautiful?


But wait, there's more! I soldered half of a second board together (alas, I had only 4 LEDs left) and put together a 16-pin ribbon cable a few inches long. I connected the two bus connectors and -- voila! Both boards are being controlled by a single processor!

As if that wasn't all cool enough, the programming header works, too! I was able to put new code on the microcontroller in place by just running a cable from the programming kit board to the programming header on my PCB. Total success!

There was one minor board bug I discovered even before receiving the boards: a wire I was supposed to connect, but didn't, that's needed to read from analog dials. But that's easy to manually fix.

Despite the fact that (amazingly) these boards work, I think I'm still going to order the v1.1 boards. They have lots of nice features, such as mounting holes, support for larger LEDs, support for 6 dials rather than just 2 (important because of our joystick, as I described on Sep 16th), and some other odds and ends.

Still on the To-Do list:

  • Software, software, software! Jon's collaborating on that.
  • Get v1.1 boards manufactured
  • Build three special boards:
    • Interface board for the high-current devices like Jon's new solenoids
    • Power conditioning board to give us a nice 5v from the pneumatically-driven alternator
    • Digital potentiomter board to drive the gauges
  • Figure out mounting: behind plexiglass?

Can you believe I'm running out of solder? That's like running out of baking soda. I think I've had my current spool of solder since I was in college.


September 16, 2009
Wednesday, September 16, 2009 -- jelson

I did a major revision of the schematic this evening, primarily because of yesterday's fantastic success with the analog dials. I wanted all the analog-to-digital converter inputs to be available to attach to pots. I completely changed the assignment of logical output pins (e.g. segment select 0-2) to physical pins on the microcontroller so that none of the ADC pins are used for generic digital I/O any more. Then I brought all the ADC pins out to their own headers.

One motivation for doing this is that Jon I were scheming today a way to attach a joystick (which is basically 2 pots attached to a lever) to the microcontroller. As the pilot moves the joystick, the microcontroller outputs will electrically control the solenoid air valves that actuate the thrusters and paint-shaker. I'll write more on this once we flesh it out.

I'd hoped that the 2nd batch of PCBs would have only tiny revisions compared to the first, to minimize the chance of introducing new bugs. But the changes are pretty substantial at this point. Oh well!


Analog Dials
Tuesday, September 15, 2009 -- jelson

A rocketship just wouldn't be a rocketship without some dials to turn. I mean, how else are you going to adjust your fuel flow and tune your navigational radio? With a keyboard? Puh-leeze.

One feature I added to the PCB at the last minute was a couple of headers for analog inputs. Each header has 3 wires: power, ground, and a line back to one of the controllers' ADC inputs. I hoped that by attaching those three leads to a potentiometer, I'd be able to read the position of a dial. Unfortunately I didn't actually get a chance to test this before sending the PCBs out to be produced.

I ordered a bunch of panel-mount 50k pots that arrived yesterday, and scrounged a rocket-looking knob out of the hardware lab at work. This evening I tried hooking them up to my proto-board, and wrote a few lines of code that would read the analog input once every 50msec, scale it to a value from 0 to 99, and display that value on the two LEDs on my protoboard. Amazingly, it worked (almost) without a hitch!

(The only hitch: the ADC input I was using is the same pin as one of the general purpose input/output pins. I had set all I/O pins as output pins, so a low value was being asserted on the same pin the ADC was trying to read, and always returned 0 -- except when the pot was at such a high value that it overcame the internal resistance of the output pin. When I reconfigured the GPIO as an input pin, everything worked.)


A Simulator
Saturday, September 12, 2009 -- jelson

For the past few days I've been thinking more seriously about the software that will run in the rocket. I wanted to figure out two things. First, what kind of software will be fun and thematic? It has to do something interesting that exploits all the interesting capabilities of the hardware. Second, what's the right software structure that will let us add features and models without the code turning into spaghetti? Luckily, software is my specialty; it's the hardware stuff that's so alien to me.

Sure, the hardware's not here yet. But, since when is a lack of completed hardware an excuse not to work on the software? I spent an hour or two writing a little Rocket Panel Simulator that runs on the console under Linux. It's essentially just a display module that I can link against the same code that goes on the real rocket. When the code is compiled in simulator mode, the functions that assert real I/O pins are replaced with functions that interact with my simulator module.

To the right is a screenshot of the simulator, configured to display 6 8-digit numbers, running the digit-identification program.

I also made some minor updates to the schematic and board layout yesterday. Primarily, I corrected the footprint of the dial connectors. Since the real footprints are smaller, there was also space to add a 3rd one. I also found the connectors at DigiKey that match the templates I used on the v1 boards. If the boards actually work, I may as well just buy the connectors that fit on the boards instead of doing something hacky.


PCB Layout v1.1
Thursday, September 10, 2009 -- jelson

I was so excited about getting the boards sent out that I started revising the design even before the first batch arrived!

The biggest difference in v1.1 is that the board now supports two different sizes of 7-segment LED displays. The original board only supported 0.39" high digits, because they're cheapest. But there are a couple of models of cheap 0.56" high digits too, which, being bigger, are naturally cooler. For maximum coolness, we really wanted to be able to mix up the sizes -- have a wall with digits in a variety of colors and sizes. But, for simplicity, we only wanted a single board, so our idea was to have a board that has two sets of mounting holes (and associated traces), fitting both sizes. This version of the board now has this feature. It mainly required learning how to extend the parts library in my PCB design software, since this particular type of 7-segment display wasn't in its pre-defined library.

And, hats off to Lite-On, the manufacturer of these LEDs. Their pin layouts really makes board design a lot easier. One, their two anode pins are 3 and 8, which are the middle pins in both rows. This means two good things: first, the supply line can run horizontally all the way across the board, without any turns. Second, you can mount LEDs upside-down, which is useful to make a clock (mounting every other digit upside-down gives you a series of colons, rather than decimal points). Also, even though their 0.56" LEDs have horizontal rows of pins, rather than vertical as in the 0.39" version, the segments are controlled by pins in the same quadrant, making the superimposition I was trying to do quite easy. And the supply lines end up being simple vertical tendrils off the long horizontal supply line for the smaller LEDs. The extra traces were all quite short and didn't intersect with each other. At right is a screenshot of two adjacent digit positions, each of which is a 0.39" and 0.56" LED superimposed so that either can be mounted.

I learned lots of other new features of my schematic editor, which let me do other cool things:

  • Per-IC capacitors. JD warned me that each IC should really have a cap. However, I couldn't figure out how to do this before, since when I made a row of caps next to each other, the auto-router routed the caps to each other, rather than having each lead of the cap going to the relatively far-away Vcc pin of each IC. Finally, I figured out how to manually route traces, and was able to put the caps in properly. Also, in v1.0 I'd accidentally and incorrectly used the footprint of a capacitor that looks like a miniature oil drum, rather than the M&M-shaped caps I was actually using. This is fixed in v1.1 too.
  • Wider power and ground leads. JD warned me I should use wider leads for power and ground, but an online trace-width calculator told me that 6 mil was good enough, and the traces were already 10 mil. Yesterday I realized that the boards I ordered were 1oz copper, but the calculator's default value is 2oz copper and the power leads should have been 12 mil. I widened them, and made all the other leads a narrower 6 mil to save space. (Eagle makes it super easy to say "make the following nets 12 mils wide".)
  • Silkscreening. I hadn't bothered to learn how to do a silkscreen layer before sending the first boards out, but once I figured it out, I put nice little labels on all the headers (e.g. PWR, BUS, PROG). I also added credits :-).
  • Mounting holes. Oops! I realized after I sent the boards off that I had neglected to add holes that could be used to mount the board to a panel (or standoff). The v1.1 board has mounting holes.
  • A square board. Yeah, long story, but, Eagle's snap-to-grid feature acts a little unusually, and the dimensions of my v1 board ended up being something like 6.50032234 inches by 2.30002451 inches, with non-square corners. I figured out how to enter nice round dimensions and fixed it.
Alas, I have already found a bug in the v1.0 boards that I have not yet fixed in v1.1 -- the footprints for the power and gauge connectors are wrong. I thought I'd found the right connectors in Eagle's library, but when the actual connectors arrived today from Digi-Key, they didn't match a 1:1 scale printout of the board schematic. I'll have to manually solder in power and ground wires for the v1.0 boards, I guess. If there's a more serious bug, I'll just spend another $110 and get v1.1 produced; they'll be way cooler with all of today's improvements, anyway.

I also blew another $75 at DigiKey today, getting enough ICs to build 3 fully-populated 8-LED boards (when the v1.0 PCBs arrive), and some other odds and ends. In particular, 4 electronic potentiometers so that the microcontroller can control the needle on a car gauge, and some manual knob potentiometers so the kids can twirl some knobs. I have a board design in mind to support the gauges, but that'll have to wait for another post.

Here's the latest schematic and board layout, both with and without the traces visible.


PCB Layout v1 Complete!
Sunday, September 6, 2009 -- jelson

I didn't do any work on the project for several months for a combination of reasons: vacation time, work projects, biking from Seattle to Portland. Finally, at the end of August, I picked the project back up -- goaded by Jon who was making phenomenal progress on the physical rocket.

The next step was to try getting a board manufactured. I redrew my schematic using different software, Eagle, that made it easier to go from a schematic to a physical board. I also added a few other features:

  • A new power connector -- with a 2-position locking molex connector rather than the screw-in connectors in my proto-board.
  • A programming header, so I can program/test/program without physically swapping the chip between the board and the programmer repeatedly. Completely untested of course (I didn't prototype it -- just drew it based on documentation), but we'll see if it works. The most likely-to-fail thing about the programming header is the reset pin. A pin of the microcontroller, /RESET, has been tied directly to VCC in my prototypes. However, the programming board needs to do something funky with /RESET when it programs. So, I tied /RESET to VCC with a 10k pullup resistor, and put the programming board on the microcontroller side of the resistor. Hopefully, this means that when the programming board tries to actually assert either high or low, it will succeed, and when the programming board is disconnected, the resistor will keep the chip in the not-reset state.
  • Horizontal bus connector on the edge of the board to make vertical board arrangement easy.
  • Two 3-position molex connectors for attaching analog dials as additional inputs. Each connector has 1 VCC (output) pin, 1 GND (output) pin, and 1 pin tied to an ADC (input) pin on the microcontroller. I hope this will let us use analog dials/pots as input, but of course, this is completely untested.
Eagle is cool: after you draw a logical diagram of your circuit, Eagle converts it into a physical board layout (with help from you). It has an extensive library of various commonly used electronics components, and both their electrical and physical characteristics. After connecting all the pins together in the logical diagram (schematic), you switch to a physical diagram where all parts are drawn to scale, including their pin positions. You place the parts where you want and hit a button, and it figures out where to put traces on the printed circuit board to make the electrical connections specified in the schematic.

I learned that it takes a lot of tweaking to get the board nice and compact. Early versions were way too spread out. Partly this was because Eagle's default minimum clearance between traces (i.e., the number of "wires" you can pack into a space) was conservative: 1/20'' (50 "mils") between traces. But, the board manufacturers I found claimed they could make boards down to 8 mils; the board got much smaller when I switched Eagle to using a 10 mil routing grid. I also tried to keep the wires from crossing where I had freedom. For example, the resistor ICs are symmetrical; you can go in on the left and come out on the right, or vice-versa. I had each wire enter the resistor on the same side as it exited the latch.

Finally, I ended up with a nice, compact board!

Exciting stuff! I sent this off to a PCB manufacturer in China called OurPCB and should have the boards back in two weeks or so. I'm getting 10 boards for $110. There's a $50 setup fee and $40 shipping; the boards themselves only cost about $2.50 each! Of course, if there were no shipping or setup fee, I'd make one board, see if it needs a correction, then get more. But since the boards themselves are such a small part of the overall cost, it's more cost-efficient to just order them all up-front if there's even a small chance they'll work. So I ordered 10. Keep your fingers crossed!


Adding a Keypad
Monday, June 1, 2009 -- jelson

A few weeks into this project, JD suggested that for the toy to be really fun, the kids should be able to interact with it in some way. It's not very fun to just look at a bunch of random digits endlessly being displayed. To really let the kids imagine they're flying a spaceship, we needed buttons to push and dials to turn! And have those buttons and dials actually do something.

Of course, as soon as he said this, I realized he was right. So I added another new feature: a 16-key membrane keypad, pictured below, that I bought on Ebay for $3 directly from some random electronics house in China. In fact, I bought two of them, since shipping was $4 no matter how many you buy. I'm not sure yet exactly how the toy will actually work; maybe if you push "A" and then punch in a number, a row of digits labelled "A" takes on that value and starts counting up or down. Or something. But, hey, the Apollo missions flew to the Moon using just a keypad and some rows of 7-segment LEDs so I'm sure I can do something at least as awesome.

The keypad has a simple interface: 8 conductors, one for each row and one for each column. When a button is pushed, it creates contact between one of the row and column conductors.

So, the procedure for scanning the keypad is

  1. Attach the column wires to microcontroller inputs, with internal pull-up resistors activated. (Internal pull-ups are a really useful feature of many microcontrollers!)
  2. Attach the row inputs to microcontroller outputs
  3. Assert low on the first row, and high on the other three.
  4. Scan each of the four inputs; if any are low, the key in the corresponding column of the first row has been pressed.
  5. Repeat the previous two steps for the second, third, and fourth rows.

The connector for this keypad had a single-row, 8-pin interface with standard (0.1'') spacing. It so happened that I'd already decided to make the board-to-board control bus a 2-row (16-pin) connector of the same spacing. So I thought I'd do something clever: try to save pins and connectors by plugging the keypad right into the bus connector. Unfortnately, I made a mistake.

The assignment of signal pins to positions on the bus connector is arbitrary. I reasoned that if I assigned the pins carefully, I could just plug the keypad right into the bus connector, and not even use any extra GPIO lines on the microcontroller. I assigned 8 address lines to the first row, and made sure the Enable pin was on the second row. I figured that as long as I kept the Enable pin un-asserted, I would be able to twiddle the other output pins in order to scan the keypad without affecting the state of the latches. I thought this was a clever way to conserve microcontroller IO pins.


I updated the software to periodically switch into keypad-scanning mode: switch 4 of outputs to inputs and scan using the procedure described above. This scanned the keypad perfectly. Unfortunately, what I failed to forsee is that if one of the keys is still being held down when the controller goes back into display-updating mode, the digits don't get programmed properly. The depressed key is now tying together two outputs that might be fighting over keeping their respective lines in different states. Oops!

To fix this, I updated the schematic to bring 4 dedicated input pins out to the first row of the bus connector, and move four of the outputs to the second row. Of course, there was no way I was going to update the physical wiring to test this...the test will have to wait until the prototype PCB arrives.

In the meantime, to test the scanning procedure, I changed the software to display the key pressed for 3 seconds after the key is released. That is, I could press "5" (the display failed while the key is pressed), and after releasing the key see "5" appear on the display for 3 seconds. Yay!


The Second Prototype
Monday, May 25, 2009 -- jelson

I was excited by my success so far but still had a way to go. The ultimate goal was to manufacture a real printed-circuit board, but I didn't feel ready to do that: too many components were still untested, and I didn't quite know what I was doing yet. I wanted to test things like the board-select circuitry and the driver that would amplify the data bus. However, I was running out of space on my little solderless breadboard. Also, as the number of wires went up, it got harder to keep the thing working without a wire popping out or two resistors touching each other. I needed something with more space and that would be more sturdy. I decided to solder together a prototype using a prototyping board.

The first step was to draw a real schematic; this was starting to get too complicated to keep everything in my head reliably.

Next I laid out all the components on the protoboard to get a sense for how they'd all fit together. This required working out a bunch more details, like finding a DIP switch, power connector, a connector for the control bus (and mating ribbon cable and socket), and a socket for the microcontroller (so I could swap it in and out, instead of soldering it permanently). I also switched from the individual wire-lead resistors to IC-shaped resistor chips -- basically just 8 resistors in a 16-pin package.

I soldered the components in, and, following my schematic, started to painstakingly make all the electrical connections. The process of cutting a wire to the right length, stripping the ends, and soldering it in is surprisingly time-consuming. It took many hours over several evenings, after which I'd only fully connected 2 LEDs. I decided there was no point in continuing. A board with 2 digits was complete enough to test what I wanted to test. I'd test with a 2-digit board and let a PCB manufacturer do the hard work of running every wire to a fully populated board.

I turned the thing on and was sad to discover it didn't work. After a while with a voltmeter, I concluded the driver wasn't working properly. Of course, the real problem was that I didn't understand how it was supposed to work. I'd thought that if you put a voltage in (low or high), the same voltage would come out. Not so: it's what's called an "open collector" driver. That means if you put in a low voltage, a low voltage comes out, but if you put in a high voltage, nothing comes out; the circuit is open, and whatever's on the other end just floats. The fix ended up being easy: I attached a pull-up resistor to each of the four outputs of the driver. Then it worked!

Next, I wrote a test program that commands all 64 LEDs in the entire board stack to identify themselves once per second. For example, LED digit 3 on board 5 is told to display "b...5...d...3". This test served two purposes. First, it let me test the board-select circuitry. As seen in the video below, if use the DIP switch to configure the board as Board 2, the right most digit says "b2d0". Then, if I change it to Board 4, it starts to display "b4d0". Cool -- it worked! The test was also useful because it shows the microcontroller (running at 1MHz) has plenty of time to individually program all 512 segments (8 segments x 64 digits) with no visible delay.


The first electrons flow
Tuesday, May 12, 2009 -- jelson

By May, I had a detailed plan in place. However, never having built anything even remotely like this before, the plan might have been completely nonsensical. Before drawing a more detailed schematic, I knew I'd have to do some basic component testing, starting simple and gradually getting more complex. I started ordering parts from DigiKey: the 7-segment LEDs, latches, and so forth.

The last time I'd tried to use an LED was when I was about 15 years old. I was really into electronics back then, but didn't have any good reference texts. One day, I saw a 7-segment LED in Radio Shack and thought "Wow, that would be cool to use!". It seemed simple enough: 7 individual power pins, one for each segment, and one common ground pin. I figured if I just attached a battery across the two, it would light up. I took it home and, unfortunately, couldn't get it to do anything. 20 years later, I started reading about LEDs and learned my problem: I had assumed that an LED was a resistive load, just like a light bulb. It turns out, diodes are magical things that cause a voltage drop but don't provide resistance. If you attach a battery directly across a diode, it's no better than a short circuit: the diode will immediately burn out.

The right design is to add a resistor, chosen so that the current flowing through it, taking into account the voltage drop inherent to the diode, is no more than what the diode says it can take. My plan was to run the system at 5V. The LED data sheet said that the diode drop was 2V. That leaves 3V "visible" to the resistor. My target was about 10 mA per segment so I picked a 300 ohm resistor (actually, 270: the closest value I had in stock).

My first test was simply to attach an LED segment to a 5V power supply and a resistor, to see if it would light up:

Wow! This was exciting. I'd already done way better than 15-year-old Jeremy!

Next I decided to try out a latch. I attached two segments of the LED to two of the latch's outputs (with resistors in between). Then I attached three buttons to the latch: one to the data input pin, one to the lowest bit of the "segment select" address line, and one to the Enable pin. And I finally learned just how to use pull-up/down resistors: you attach a high-value resistor to, say, a pin and ground. Then, on the pin side of the resistor, attach a push-button tied to Vcc. When the button is not pressed, the resistor (with no current flowing) keeps the pin at ground. When you push it, you tie it to Vcc instead; the resistor is so strong that the connection to ground is overcome.

If I pushed Enable without pushing Data, the segment would go out. If I hold down Data and then push Enable, it lights up. If I did all of this while holding down the Segment Select line, it would happen to segment #2.

I couldn't believe this was all working! I decided the next step was to get the microcontroller to flip the lines automatically, rather than me doing it manually with buttons. I hooked up all 7 segments to resistors and to the latch, and figured out how to use my new microcontroller programming kit. I made a table defining which of the seven segments should be lit up for each number 0-9, and each letter A-Z. (Some letters, like W, X, and Z, can't actually be represented by these displays.) Then I wrote a program having the controller cycle my LED through the all the numbers and letters. It worked!

Next I added a second digit and a second latch, and a first demultiplexor that would let me select which of the two digits I was controlling. The circuit was really starting to take shape now: I had a real data bus, and real segment-select bus, even though there were only two devices on each bus.


The basic design is decided, long-windedly
Thursday, April 2, 2009 -- jelson

My original thought was to do what sounded easiest: get a microcontroller with as many GPIO (general purpose input/output) pins as possible, and attach each segment of each LED to one of them. With my target of 30 digits, each of which has 7 segments plus a decimal point, that's 240 total segments that need controlling. The biggest microcontrollers I could find only had about 100 GPIO pins, so I started thinking of a more complex design: two or three microcontrollers, each controlling half of the digits. My plan was to use "I2C" (a microcontroller communication standard) to have the two controllers talk to each other, in order to synchronize.

Luckily, I ran this plan past my friend Lew before going any further. He knows electronics pretty well, and suggested what I needed were some latches. A '259-model latch is a basic memory device; it can remember 8 bits, and asserts those values on 8 output pins. To change them, you twiddle 5 inputs: first, assert 3 address lines, to tell it which of the 8 outputs you're trying to change; then, assert 1 data line, to tell it what value that output should take; then, "strobe" (i.e., go through an asserted/unasserted cycle) the Enable line.

So, by attaching each of the 8 segments of an LED digit (including decimal point) to the outputs of a latch, it's possible to control all 8 segments using just 5 control lines -- the latch's inputs -- instead of 8. But, more exciting is that this scheme scales well. If I want 24 digits instead of one, I need only 28 GPIO pins: the three address lines and one data line can run on a common bus, shared by every latch. 24 GPIO lines are then needed for each latch's Enable pin, letting us specify which latch we're actually talking to; the rest ignore the address and data lines because they're not being strobed. That is, we can program a latch by asserting the segment number on the three shared address lines (which I'll now call segment select), asserting the value of that segment on the shared data line, and then strobe the one (out of 24) Enable lines corresponding to the digit we're trying to change.

But wait! We can do even better! Another clever device, called a demultiplexer, can reduce our pin requirements even further. '138 series demultiplexers take 3 address lines and one Enable line as input, and have 8 outputs. Unlike a latch, a demux only asserts one of its outputs at a time. When we strobe its Enable line, it strobes whichever of the 8 output lines we've selected using its 3 address inputs. Now, controlling 24 LEDs requires even fewer control lines: we can attach each LED to a '259 latch, with a common bus for the 1-bit data channel and 3-bit segment select, then attach each of the latch's Enable pins to one of the outputs of a demultiplexer. For 24 digits, we'd need 3 demultiplexers, 8 latches on each. Of course, the addressing input lines of the demultiplexers can also be shared. I will now call these shared address lines digit select. Then, connect each of those 3 demux's Enable lines back to the microcontroller. Now we can control each of the 8 segments of 24 LEDs using only 13 GPIO pins: 1 data line, 3 segment select lines, 3 digit select lines, and 3 pins that lead back to the Enable pins of the 3 demultiplexors.

But wait! We're still not done! Now we can add a 2nd layer of demultiplexors. In other words, have one "top-level" demux, and attach each of its 8 outputs to the Enable lines of 8 more demux's. I will call the 3 address lines of this top-level demux the bank select lines. Each of the 2nd-level demux's can control 8 digits, so this is now a total of 64 digits, each with 8 segments (or a total of 512 segments) that can be individually controlled with only 11 output lines on the microcontroller:

1 data line
3 segment-select lines
3 digit-select lines
3 bank-select lines
1 master enable line
Awesome! And suddenly I more deeply understand how a computer's memory bus works.

Unfortunately we're not quite done. When I showed this plan to my friend and colleague JD, he pointed out a problem. The data and segment-select lines have a rather large fanout: the microcontroller asserts just one data line and it is taken as input to all 64 latches. Most parts are spec'd for a maximum fan-out of 10 or 15. So, we also have to add drivers -- basically amplifiers -- one for each of the 8 banks. That is, the microcontroller asserts data and segment-select lines to 8 drivers; each driver re-asserts it to 8 latches.

While the design seemed reasonable, the idea of assembling such a beast did not. Such a board would have hundreds of signal lines and close to 5,000 tiny holes that would need precise drilling. It didn't seem reasonable to try and fabricate it myself. I'd have to learn another new skill: how to draw a schematic and have a PCB professionally manufactured from it.

Board manufacturers charge by the square inch. We wanted the rows of digits to be spread out (leaving room in between for things like labels, dials, etc.), so I added one final feature to the design. Instead of one huge board with all 64 digits on it, I'd make 8 smaller, identical boards, with their 11 magical lines all connected to each other using a ribbon cable. I'd give each board a DIP switch that would let me tell it which "bank number" it was. I should then be able to put a microcontroller on one of the boards -- it doesn't matter which -- and let the ribbon cable distribute its 11 outputs to all the others. Then, we'd be able to manufacture smaller boards in larger quantities, rather than one huge board. Plus, it has the significant advantage of letting us spread the numbers out in the rocket ship a bit more.

With all this decided, I drew up a basic block diagram showing what each board would look like. I was so excited: the project was already paying for itself in teaching me new things!

The diagram above shows the latches, but doesn't depict the LED or resistors attached to each latch. Also, it shows my cheesy board-select method: each output of the first-layer demux is attached to one switch in a bank of 8 DIP switches. Then all the outputs are bussed together. So, to select (say) board 4, you turn on switch 4, and turn all the others off. With some more complex logic, I could have made it work in binary (allowing you to select 256 boards), but this thing was already complex enough and other aspects of the design limited us to 8 boards per stack anyway.

My next task was to pick a microcontroller. The first sub-task was to pick a brand of microcontroller. My only past experience with them was tinkering with some PICs with my friend Guy back almost 15 years ago.

(Aside: We'd tried to build a board we could install in his apartment's front-door intercom so it would unlock the downstairs door if someone pushed the buzzer with a secret morse-code pattern. We hacked together an assembly-code program that seemed to do the right thing on a test board: lighting up an LED for a few seconds when we pushed a button in the right pattern. But it never worked when we actually installed it. Guy's dad, an electrical engineer, suggested a few changed, including "pull-up resistors", which neither of us had heard of at the time and had no Google to help us, so the project fizzled.)
I spent a day or two comparing Atmel, PIC, TI and a few others, and finally decided on Atmel. I liked them most of all because they're open: with a gcc-based toolchain and open-source C library the environment felt comfortable. Though I wasn't expecting to write assembly language, the instruction set for Atmel's microcontrollers seemed much easier than PIC's somewhat bizarre and tortured design. The Atmel has 32 registers -- more than my desktop machine has! The PIC is so weird that GCC can't even target it. The PIC's development board seemed a little better (cheaper, and USB rather than serial-port based), but ultimately I decided on Atmel.

The microcontroller I picked was the Atmel Atmega8, an 8-bit microcontroller with about 20 digital I/O pins, as well as some analog-to-digital converters, which will come into play later in the story.


Avionics origins
Wednesday, April 1, 2009 -- jelson

My home-designed printed circuit board displaying a test pattern. The rocket will eventually have 8 of these boards, interconnected by ribbon cables, plus several dials, gauges, and a joystick. "Thrusters" and "engines" will be controlled by the board as well.

Jeremy Elson – jelson at the domain "gmail dot com"

When Jon first started talking about building a rocket ship treehouse for his kids, it sounded like a static display: other than the shape and the material, pretty much the same as any other treehouse. But then he started talking about features that would make it come alive: pilot-controlled thrusters! A paint-shaker that simulates the rumble of takeoff! I got excited. I told Jon I thought his plans were desperately lacking something. The quintisenntial artifact that screams "1950's-era fictional space program": lots of flashing lights and dials and buttons and beeps.

One of the things I've been meaning to do for the past few years is improve my working knowledge of electronics. And, fresh off completion of my automatic closet light, I was ready for a bigger challenge. I offered my services as an avionics subcontractor, and Jon readily agreed.

My original idea for the control panel, in April of 2009, was relatively simple: lots of seven segment displays, perhaps 30 of them total, arranged in 6 groups of 5-digit numbers of varying colors. I'd imagined them flashing and counting, a constantly changing sci-fi display of random numbers. As we'll see, I rather dramatically under-estimated the ultimate complexity – and fun – of the project. The avionics ended up being

  • a stack of over 10 modular, interconnected boards, that
  • collects input from dials, joysticks and a keypad,
  • emits output via 7-segment digits and car gauges, and
  • controls high-current devices, such as solenoid air-valves, that actuate the rocket's "engines" and "thrusters"
But we're getting a bit ahead of ourselves.