This is post #1 in a series covering the hardware and software design for my work-in-progress GPS-guided rocket recovery project. The main index to the series of posts is here, and an introduction to the project (a PowerPoint presentation) is here.

In this post I’ll cover the hardware design, including the schematic, board layout, and Eagle PCB files from my “Rev3” hardware of March 2007. (That’s the most recent version I have working as of this writing.)  This post is also a good starting point even if you’re mainly interested in the software – as a tightly integrated system, an understanding of the hardware is key to the software as well.

About rights: I hereby grant everyone and everything in the universe permission to use and modify this hardware design for any purpose whatsoever. In exchange, you agree not to sue me about it. I make no promises. By using the design you agree that if you’re unhappy the most I owe you is what you paid me (zip).  That seems fair.

If you find this useful, I’ll be pleased if you drop me a note or leave a comment here (just so I know it’s been helpful to someone) and if you give credit to for the design in any publications. But you don’t have to.

The board was designed in Eagle PCB, which is available in a free “light” edition, limited to non-profit use and 2-layer boards of not more than 4.0 x 3.2 inches. (Sufficient for this board.) Eagle takes some getting used to, but works well.

If you want to modify my design, here are the Eagle PCB files for the schematic and board:

This hardware has made many successful flights, and supports the following features:

  • PIC18F2620 MCU (programmable in C)
  • GPS interface
  • Drives a hobby servo (to steer the parachute)
  • Pressure altimeter (good to about 2 feet precision)
  • Triggers parachute deployment at apogee
  • Able to log flight data in flash memory
  • Drives an in-flight digital camera
  • Piezo speaker output
  • 3 push-buttons, 3 LEDs

Figure 1 shows the schematic:

Rev3 Schematic

Fig. 1 - Rev3 schematic

A few comments about the circuit are in order.


The MCU is a PIC18LF2620. It has 3968 bytes of RAM and 64 kbytes of Flash memory, which is available for both program space and logging of flight data. It will run at up to 8 MHz off the PIC’s internal oscillator – I don’t use an external crystal.

Interestingly, these specs are very similar to those of the Apollo Guidance Computer. Except that the PIC is a single 28-pin chip, costs about $4, and draws only a couple of milliamps.

You can program the PIC using Microchip’s free C18 compiler and free MPLAB IDE environment – those are what I recommend.


The board was designed to interface with a GlobalSat EM-406 GPS using a serial UART interface. I’ve used others (see tweaks.h for a list); it will probably work fine with any serial-interface GPS.

The PIC transmits to the GPS on pin 17 of the PIC (TX).

Note that pins 4 and 5 of the PIC are tied together, and pin 6 (C1OUT)  is tied to pin 18 (RX). This is part of a no-hardware level-shifting scheme that allows the 5v PIC to read data from the EM-406 GPS, which outputs at 0v/2.85v.

Data received from the GPS goes into pin 2 of the PIC (AN0) , which is configured as an analog comparator input. Pin 5 (AN3) is the other input to the comparator. The PIC’s CVref output (think of it as a poor man’s DAC) on pin 4 is set to output 1.458 volts, which goes into pin 5 (AN3).

Pin 6 (C1OUT) is the output of the comparator, which is setup such that it goes low whenever the voltage on AN3 > AN0. (Comparator mode 001 binary.) So whenever the GPS output coming into pin 2 (AN0) is less than 1.458 volts (close to the midpoint of the GPS signal output range),then C1OUT (pin 6) goes low, and vice-versa. This level-converted output is then fed into the RX pin of the PIC on pin 18.  (See SetupHardware() in hardware.c.)

This is the only part of the design that is at all clever.

Fig. 2 - Rev3 PCB layout


The SERVO output will drive a standard hobby-type servo. (With appropriate software on the PIC, of course – see SetupHardware() and SetServoPos(), both in hardware.c, and my discussion in my post about isr.c.)

The servo is powered directly from the battery input to the 7805 regulator (normally 7 to 8 volts, which is fine).

The servo pinout is correct for the most common servos (Futaba/Hitech pinout), but servo wiring varies, so double-check whether you need an adaptor for your servo.  If you connect the servo incorrectly, you could damage it.


The altimeter uses a Freescale MPX4105A pressure sensor, which works very well.  Avoid mounting it where it will be in direct sunlight during flight – this will affect the readings.

The sensor is read by a 10 bit ADC in the PIC, oversampled to get higher resolution. (See #define ReadPressureSensor() in peripherals.h.)

The pressure altimeter is used to:

  • Detect launch
  • Detect apogee (to deploy the parachute system when using electronic ejection)
  • Log altitude data for post-flight analysis

C4 and C5 are filtering caps, as recommended by Freescale.

Fig. 3 - Rev3 PCB, unpopulated


Phototransistor “DET” (a Lite-On LTR-301) and 10k trimpot R6 are used to detect parachute deployment.

This is important when flying with motor ejection – you don’t want to start steering the parachute until it’s deployed, so you need a way to detect deployment.

The idea is that it’s dark in the electronics bay until the parachute deploys, which lets sunlight (or at least more light) reach the phototransistor. R6 adjusts the sensitivity (test and adjust before flight).

Second thoughts

This worked, but phototransistors are very sensitive in the infrared, which is a problem. Even with the nosecone on, enough IR was leaking through the paint to make reliable detection difficult. I had to apply many layers of black paint to get it dark enough in the electronics bay. Next time, I’ll use a CDS cell, which has its peak sensitivity in visible wavelengths.

Also, the side-looking phototransistor is mounted facing the wrong way (which didn’t help either).


Push buttons S1, S2, and S3 are inputs for ground testing and pre-flight setup.

As I recall (at a distance of 2 1/2 years), I didn’t put pull-down resistors on S2 and S3 because they’re on PIC port B, which has internal weak pull-ups.

But that doesn’t make sense, S1 is not on a pulled-up port. Probably this was a mistake, but it works anyway.


The PIEZO output drives a small sonalert-type piezo transducer, directly. This is tremendously useful for indicating status after the board is buttoned up inside the rocket. I toggle the state of the PIEZO output once each time thru the idle loop – small changes in pitch can tell you a lot about what’s going on in the software (one of my favorite old embedded-systems tricks).  (See the idle loop in main() and #define ServiceBuzzer() in peripherals.h.)

I also use the on/off state of the sound to indicate things like whether the parachute ejection system is armed, GPS has a valid fix, etc.

Finally, after the rocket has landed, I use the piezo buzzer to beep out the peak altitude (in feet AGL) reached on the flight. (See BeepOutMaxAltitude() in peripherals.c.)

Driving the pizeo element directly works pretty well, despite the piezo datasheet asking for more current. (PIC outputs can source/sink up to 25 mA each.)

The HORN output is meant to drive a loud smoke-alarm type horn (I used ones salvaged from broken smoke alarms). To drive the loud horn, I used an external 2N3904 transistor to get enough current (about 60 mA; see Figure 4).

The idea was to have the rocket “honk” the horn after landing, to make it easier to find.  This didn’t work as well as I expected.


The SHUTTER output was designed to be directly interfaced to the shutter button on a digital camera, to take pictures in-flight.

This worked, and many of the in-flight photos on this site were taken that way.

Later, I modified the software so that instead of being physically connected to the shutter circuit, the SHUTTER output drove an infrared LED to send remote-control IR signals to the camera. (Most IR remote-controlled devices use a simple code around 32 bits long, with a bit length of 1 millisecond, with each ON pulse modulated with a 48 kHz square wave. The PIC’s PWM module can be made to produce this.) This avoided physically hacking up the camera and in theory allowed sending different signals to the camera. (See SetupHardware() and TakePicture() in hardware.c and isr() in isr.c.)

Although that worked, it ultimately was less reliable than a physical connection.

Second thoughts

Digital cameras (esp. used ones with “broken screens”) are cheap enough now that I don’t mind hacking up one for riding in a rocket. Next time I’ll have 3 camera outputs instead of 1:

  • Shutter button (as in this version)
  • Shutter half-press (force camera to pre-focus, set exposure)
  • Power on/off

The latter will be particularly useful, as I found the camera battery would sometimes die after sitting on the pad for 45 minutes or more. (For that reason I strongly recommend the camera have it’s own battery, not shared with the flight-critical parachute deployment system.) With the ability to turn on the camera via software, it could be turned on only when launch is detected, then turned off after landing.


The ICSP connector is a standard Microchip In-Circuit Serial Programming (ICSP) interface to the PIC, which allows for programming and debugging the PIC, as well as downloading stored flight data.

I started by using a PICKit2 (now obsolete) to program the PIC, then switched to an ICD2 (also obsolete). Now I’m using an ICD3.

Second thoughts

The ICSP connector doesn’t leave enough clearance for easy connection of a PICKit2 or PICKit3. I had to make an extender.

External board connections

Fig. 4 - External board connections


Figure 4 shows all the external connections to the board.

The EJ_TRIG output fires the parachute deployment charge via a TIP100 transistor. I use AG1 flashbulbs (shown as “EJECTION” in Fig. 4) to ignite the ejection charge.

The LDET input was originally designed as a “launch detect” input. I tried using various forms of squat switches, but found them all too prone to false launch detection. Launch detect via the pressure sensor is far more reliable.

So I repurposed the LDET input to check continuity on the ejection trigger circuit (the AG1 flashbulb). Resistors R2 and R4 form a voltage divider. When the flashbulb has continuity, about 0.4 mA flows thru the flashbulb, pulling up the LDET input to a logic 1. If the flashbulb is not connected (or burnt out), R4 pulls the LDET input to logic 0.  This is simple and works great – many thanks to my friend Gary C. for thinking of it. (He helped with a lot of the analog stuff here; I’m not a hardware guy.)


The 5-pin COMPASS connector was originally designed for a Hitachi HM55B (Parallax 29123) magnetic compass, which sat on a little daughter board (see Figure 5).

I developed a bit-banging SPI interface to it, which worked fine (see compass.c).  I’d originally hoped the magnetic compass could be used to provide more frequent heading updates than the ones I could compute from the 1 Hz GPS fixes.  The compass worked, but its response to change of heading proved to be very slow and damped – so much so that the data was no fresher than what was obtained from the GPS. And the compass was the second most expensive part on the board.

So the COMPASS interface was freed up to provide 3 spare I/O pins, RC3, RC4, and RC5, plus power (Vdd) and ground connections.

Probably my biggest design oversight was failing to provide a way to disarm the parachute ejection charge on the pad. This is critical for safety – many times you need to approach the rocket to make adjustments before launch, or to take the rocket off the pad. You need a way to be sure the parachute ejection charge won’t fire in your face! When I designed the board I’d been flying exclusively on motor ejection, so somehow this neccesity never occurred to me.

As can be seen in Figure 4, the Vdd, RC5, and RC3 pins on the COMPASS connector connect to a SPST SAFE/ARM switch. RC3 is the input; logic 0 (ground) is SAFE mode, logic 1 (+5v) is ARMED.

Vdd is used as the source of the +5v for the ARMED state, and RC5 is driven as a logic 0 output for SAFE mode. R5, 20k, pulls down the input to logic 0, so in case of a broken or disconnected wire the rocket is SAFEed (it happens!). (R5 is mounted on the PCB, not at the switch.)

Finally, RC4 was a spare output so I used it as a “Z-80 speedometer”. This is simply an output bit that goes low whenever the software is in its idle loop, and high otherwise (when exiting the idle loop, and on entry to the ISR). That is used to drive a analog voltmeter, which effectively integrates the output. So a reading of 0v indicates the MCU is completely idle, and 5v indicates the MCU is “working as hard as it can”. It’s not as useful as the piezo buzzer trick, but it does provide valuable real-time insight into what the software is doing (and it’s fun to watch). Of course, this is connected up only for bench testing (not in the rocket).


I powered everything from either 2 lithium-ion cellphone batteries in series (around 7.6v) or 6 NiMH cells in series (7.2v), except for the camera, which had its own internal battery (this is a good idea, as mentioned earlier).

The 7805 regulator produces 5v to power the MCU and GPS. C2 and C3 are decoupling caps, and needed.

Second thoughts

The board is laid out for an obsolete TO-39 can type 7805 part, because that’s what I had in my parts box. You’ll want to change that.

The 7805 is a very unsophisticated way to get 5v – it wastes lots of power and drops out around 7 volts. Next time I plan to use a switching DC-DC converter or a LDO regulator.

I added a 470uF 16v capacitor between ground and Vdd. This allows the power connection to drop out for a few milliseconds without resetting the MCU. This can happen during flight if you have batteries in spring holders (not recommended), or bouncy power switches.

Also, I managed to burn out at least two 7805s by connecting the batteries backward by mistake. I suggest using keyed connectors or putting in a diode.

Last, if you’re going to use a pair of lithium cells to power it (I used surplus cellphone batteries), you’ll want to use a 3-pin connector so that you can easily balance the cells.

Fig. 5 - Rev3 PCB populated (note compass daughterboard on right)


This was my first PCB design ever, and it’s not perfect (although it does work). In addition to the second-thoughts mentioned above:

  • Decoupling capacitor C1 should have a pin spacing of 0.2″.
  • Capacitor C2 should have a pin spacing of 0.1″ (if tantalum) or 0.2″ (if mylar).
  • Capacitor C5 should have a pin spacing of 0.1″.
  • R2, R3, R4, and R4 are laid out for vertical mounting, “Japanese transistor radio style”. This produces a messy board.
  • I should have marked the cathode of the LEDs on the silk screen.

All connector pins are standard 0.1″ pitch square pins (many right-angle types).

I had the boards manufactured by – they did a great job at a very reasonable price (you have to be patient, however).


I’ve started work on a “Rev4” version of the board – this will use a PIC32 at 3.3v and SMD components.

I’m trying to avoid what Fred Brooks called the “second-system effect”, but I may not be succeeding. 🙂