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
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
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
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"
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
before going any further. He knows electronics pretty well, and
suggested what I needed were
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
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,
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
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
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
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
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
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.
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
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
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.
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
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
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
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
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
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
So, the procedure for scanning the keypad is
Attach the column wires to microcontroller inputs, with
internal pull-up resistors activated. (Internal pull-ups are a
really useful feature of many microcontrollers!)
Attach the row inputs to microcontroller outputs
Assert low on the first row, and high on the other three.
Scan each of the four inputs; if any are low, the key in the
corresponding column of the first row has been pressed.
Repeat the previous two steps for the second, third, and fourth
The connector for this keypad had a single-row,
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
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!
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!
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
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
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
for another post.
Here's the latest schematic and board layout, both with and without
the traces visible.
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
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.
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
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,
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!
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.
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
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:
Today I worked on the one part of this project that has
been consistently dogged by failure: getting analog gauges attached to
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
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).
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
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
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!
Really, what is failure but an opportunity for future success?
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
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")
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
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
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
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
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!
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
remain consistent, but we don't really care which microcontroller pin
is being used to drive the bus.
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
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
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
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!
Oct 4's entry described how the microcontroller will be able to
actuate the thrusters. But how does the microcontroller
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 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
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.
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
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
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
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!
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:
A small joystick interface board with two resistors, forming two
voltage dividers that can be read using the processor's ADC.
A rocket panel board with a processor on it. The joystick
interface board plugs into the CPU board's JOY1 input header.
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...
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.
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
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!
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!
I took a break from rocket work for about a month;
it was taking too much time and
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
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
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
Some evening this week I'll build the real board.
Tonight I soldered together the final power board.
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
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
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
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
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).
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
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.
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.
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
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!
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.
I haven't pulled the TWI all the way through into the networking stack
yet but, that's tomorrow's project.
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.
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.
Well, my friend, I'll take those odds, because you're
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.
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