Archive for December, 2010

Reverse Geocache

December 31st, 2010 9 comments

Finished puzzle box

This project was inspired by the “Reverse Geocache Puzzle Box“, an idea that has been duplicated a few times.  For Christmas this year, I drew my brother-in-law, Scott.  I know that he appreciates hand-made gifts, and my idea of hand make is almost always electronics related.  I thought for a while about a gift I could give that was hand-made, but appropriate to his interests.  While I wouldn’t say he’s interested in Geocaching, per se, but I know he will appreciate the destination.

That said, I began by designing the electronics.  In the original puzzle box, the designer used a commercial Pololu “soft” switch and an Arduino.  I decided to make everything custom, including a custom soft power switch.  When I say soft power switch, I mean a button you press to turn the system on.  When it’s time shut the system down, the controller can turn the power off.  The circuit I found was listed on this forum.  It was an O.K. start, but left something to be desired.  The given resistor values were all wrong for my application.  I think it was intended for a lower current applications, and the servo powering the latch draws a lot of power, relatively speaking.  Also, I’m not sure whether it it was an error on my part, but when the PIC shuts down, the output pins go into “high impedance” mode, as if they’re disconnected.  I had to add another resistor from the control wire to ground to hold it low while the system is off, otherwise it would never shut down.  In the future, I think I’ll approach it another way.

Reverse Geocache schematic

The remainder of the circuit is pretty straightforward.  There is a connector for the GPS, servo, programming header, and LCD.  I decided to use the 4-bit interface to the LCD to save some pins.  I designed a PCB from the schematic with home fabrication in mind.  While I don’t think the through-hole construction is necessary for homebuilding, it’s easier for some people.  I caution you that the sparkfun outline for the 16×2 LCD isn’t quite right.  The mounting holes didn’t line up.  Also, I didn’t have the pins for the servo correct, I had to move them around on the connector (5v and Ground are reversed).  Finally, another error in the design was that I didn’t notice until after I made the PCB that the 4-bit interface to the LCD is on pins D3-D7, not D0-D1.  I used a few wires to bridge over to those pins to fix it.

Reverse Geocache PCB

Once the design was complete, I made the board using the toner transfer method and etched it using ferric chloride.  I’ve refined my toner transfer technique recently, and I’ve been having really good luck.  I’ll write a post about it soon.  Drilling and assembling the PCB was otherwise unremarkable.

Prototyping and programming

It took a few days to program the microcontroller and test the electronics.  There was one significant stumbling block that wasted an entire day.  Hopefully google indexes this so other people don’t have the same pain I did.  Here it is:  If you’re having trouble with the USART on a PIC microcontroller, whether you’re using PICC, Microchip C, or Assembler, the Overrun flag stops the USART dead in it’s tracks.  I recommend that every time you poll the port, check the flag and reset it.  This is likely the problem if you can receive 2 bytes, then nothing.  Also, the transmitter will continue working.

Latitude/Longitude distance equation (r means radians)

This was the first time I used floating point math on a microcontroller, and I have to say I was a little impressed.  I use the distance equations from the aviation formulary.  I think it is an interesting equation because it accepts latitude and longitude in the form of radians, does a little trigonometry magic, and away you go!

Clasp design

With the code finished, I focused on the enclosure.  I started with a weird suitcase-looking wooden box from the crafts store.  Then, I measured it carefully and designed the clasp.  The main idea is that there is a rotating disk with a notch cut in it.  The screw fits within this notch and holds the lid closed.


With the measurements derived from the dimensional drawing, I drew a few circles.  The inner one is the diameter of the servo control arm shaft, the next circle out is the location of the screw.  The last circle is the desired maximum outside diameter.  Using these circles as a guide I drew the clasp.  The tongue has a little bulge to make sure you can’t wiggle it open.  I drew it over until it was nice and dark, then traced it onto a notepad sheet.  I cut this out and traced it to light-ply.  My Dremel with an end-mill made short work of cutting it out.

Completed clasp and pin

Clasp tolerances

As you can see, the final tolerances are really tight.  I’m very happy with this mechanism.  In fact, later in the process, I accidentally locked the box with bad software.  Luckily, the hinge is screwed on from the back and I could remove them.  However, the clasp was so tight, I still took several minutes to open it.

Measuring the LCD

With the clasp done, I moved on to the LCD.  In this case, I measured it and traced it onto the lid.  There are two rectangles.  One is the location of the mounting holes, and the inner is the outline of the black LCD frame.

LCD Module test fitting

Here you can see the LCD module installed in the case.  It was a tight fit.  In additing to cutting and drilling the case, I cut some acrylic to use as a window.  I’ve been trying to figure out how to hide that ugly black bezel for a while, now.

Acrylic window

I traced the outline of the display part of the LCD module.  I used this to mask out the clear part.

LCD Window

As you can see the bezel is hidden.  Unfortunately, some of the red paint leaked behind the masking tape.

Controller assembly

This is an image nearing final assembly.  I use 4-40 hardware through the front of the lid.  On the back side of the LCD I installed a nylon and steel washer, then a standoff.  On the Standoff threads, there is a nut on the top and bottom of the mainboard.  These are to set the spacing of the LCD and mainboard and hold the package securely.

Mainboard installation

With the mainboard installed, the GPS was installed.  I just used double-sided foam tape.  It is behind the lid, and the satellite signal simply travels through the lid.  It looks nice and still works great.  The wood is so thin, in fact, that the light from the LEDs shines through it.

Arm switch

Going back to the problems I was having with the soft power switch, I noticed that when I left the battery plugged in over night it drained somewhat.  It’s kinda cheap, but I had to hack-on a power switch in addition to the pushbutton.  I use an ancient RC airplane trick where you stick a control rod through the wall to access a switch on the inside.

Power switch outside

Now, you can hook a fingernail onto the wire.  Pull to enable, push to disable.  This also prevents from attempts being wasted during shipping.

Final programming

This is an image of the final time I programmed the controller.  Complete with the puzzle coordinates!  It was important to remember to not let the lid close unintentionally, as the target almost 1000 miles from here!

A note about the provided code.  It isn’t high quality.  It’s a little embarrassing, but I did it in a hurry.


Eagle files

RF Transceiver using the MRF49XA

December 8th, 2010 121 comments

Transceiver breakout boards

I’m just finishing up my last class ever!!!  (for credit, anyway.)  It was a really fun, mostly because I decided to have fun with my last class, and make it a 4/5 (undergrad/graduate).  This meant that it was much easier and less theory-heavy than those that I’m used to.  Anyway, as a grad student, I was expected to do something extra, and I decided to make a RF transceiver module.  I looked around for a little while, and I settled on the Microchip MRF49XA.  In general, it’s a nice chip.  It has about the same capability as the Micrel MICRF6xx modules that I’ve used in the past.  The Micrel modules cost $20/ea. and the Microchip IC is around $3.  I was able to make the whole breakout board for the MRF49XA for less than the Micrel module alone.  One of these days, I should dig out my notes from the Micrel project and post them, but I digress.  I noticed a distinct lack of programming information using the MRF49XA, so I’m posting not only my schematic and PCB, but the software library I wrote for the Atmel AVRmega.

Breakout board schematic

The schematic I created for the breakout board is, in large part, copied from the reference schematic from the datasheet.  There are a few parts that make up the complete schematic, including power regulation, microcontroller interface, RF balun, and the IC.  Everything but the balun is really easy to understand, the power input can be +5 volts or more (probably up to about 14 volts) while using the LM317, or if the LM317 is omitted, +3.3 volts.  The MRF49XA is really a 3.3 volt part, and expects 3.3 volt I/0.  Originally, and on the PCB I had made, I had 2 ground pins.  Since then I realized it would be useful to output regulated 3.3 volt output, so I changed one of the grounds for that.  The only other major portion of the circuit is the balun.  This is used to transform the balanced RF input/output from the IC to the unbalanced antenna connector.  This circuit also provides power to the RF power amplifier inside the IC.

Breakout board top

Breakout board top

The PCB designed from the schematic is also fairly straight-forward.  A few things are worth noting, however.  I’ve added some silkscreen between 2 of the pins on the LM317.  These are to indicate where you could jumper if the breakout board is supplied with regulated power.  I used a 0805 0-ohm resistor (see the image below).  The voltage output of the LM317 is selected with R1 and R2.  I decided not to include the “stop” layer on this image so as to not clutter it, but near the word “Fence” there is a strip without solder mask over the vias.  If you wanted to isolate the RF from the outside, you could build a fence out of copper foil (or something).  The Antenna connector is a end-launch SMA, though it could also be raw coax if you want to save some money.

Close up

The only pins necessary for complete functioning of the device are the standard SPI set (MOSI, MISO, SCK, !CS), and IRO (interrupt request out).  The IRO pin is not strictly necessary, but HIGHLY recommended.  The MRF module uses the IRO pin to notify the microcontroller of a few time-sensitive events, such as FIFO full/empty conditions.

MCU interface while transmitting (click to enlarge)

The diagram included above (from the MRF49XA datasheet) provides a useful overview for the transmitting process.  The take-away message is that you first send the “Transmit data enable” (TXDEN) command, which loads 0xAAAA into the transmit FIFO.  You can either leave this in there, as a preamble, or replace it with data of your choice.  Then, you send the “Transmit carrier enable” (TXCEN) command.  At this point, the PLL starts, and the PA turns on, then transmission starts.  When the first full byte leaves the FIFO the IRO asserts.  Hopefully this forces the MCU to jump to your interrupt service routine.  Once there, if the CS pin is held low, the MRF will bring SDO (MISO) high.  This is a clear signal that the FIFO needs attention.  You can continue this process for as long as you have data.  Once you’re done, you need to load a “dummy byte” into the FIFO so your last data byte makes it out.  Finally, on the next interrupt, shut down the transmitter by sending TXCEN and TXDEN = 0.

Receiving FIFO usage (click to enlarge)

This diagram illustrates another detail of the interface to the MRF.  Also borrowed from the datasheet, it describes the way to access the receive FIFO using SPI.  Typically, SPI interfaces don’t have a notion of registers quite like I2C does, but the MRF does.  To get access to the receive FIFO you initiate an SPI transfer to the MRF module with the contents equal to the address of the receive FIFO.  In this case it’s 0xA000.  Once the first byte of the transfer is complete, the MRF begins outputting the FIFO value on the SDO pin.  It is also possible to gain access to the receive FIFO using FSEL (FIFO Select, called “Data” on the schematic) pin.

Baseband Bandwidth calculation (click for full size)

Before going into some details on the implementation of the library, I’d like to talk briefly about the RF frequency, deviation, and bit rate determination.  I’ve attached another snippet from the datasheet (hopefully the last one), and I’m going to go through the math quickly with numbers for my application.  I’m using 434 Mhz band, with 9600 baud, using a 10ppm crystal.  This means that fxerror = 10 * (434000/1000000) = 4.34 Khz.  Then, our deviation must be 9.6 + 2*fxerror + 10 = 28.28; the closest modulation is 30 Khz.  Therefore, BBBW = 30*2 – 10 = 50 Khz.  The closest BBBW is 67 Khz.

Spectrum plot from alternating 1s and 0s

I recently gained access to a spectrum analyzer courtesy of the OSU Robotics Club.  This is a spectrum plot of 0xAA, or alternating 1’s and 0’s.  It’s a little strange that the distance between peaks is about 90 Khz, as it should be more like 60 Khz.  The comb-like appearance on the flanks is probably from the transceiver switching from 1 to 0 across the scan.

Transmitting ‘1’

This plot is while transmitting all 1’s.  It’s obvious this is much cleaner, but very little information is actually being transmitted here.

With respect to the Atmel AVR library that I wrote, it includes a header file devoted entirely to defining the registers and bits as defined in the datasheet.  Each section includes a comment block description, and in the cases where some bit values need to be calculated, the equations used.  On the occasions where a bitfield is used for some integer value, I include a mask to ensure that if the derived values overrun the width of the bitfield they don’t pollute unrelated settings.  Below, I’ve included an example.

 * Convenience definitions for band setting
 * These defines are provided for use configuring the MRF49XA module.
 * Select the frequency band for the given hardware by uncommenting the
 * appropriate line.  Set the crystal load capacitance using the MRF_XTAL_LD_CAP
 * value.
 * The load capacitance is given by the following equation:
 * Cap pF = 8.5 + (LCS / 2)
 * LCS = (10 - 8.5) * 2
 * For 10pF: LCS = (10 - 8.5) * 2 = 1.5 * 2 = 3
#pragma mark General Configuration Register
#define MRF_GENCREG		0x8000		// General config. register
#define MRF_TXDEN		0x0080		// TX Data Register enable bit
#define MRF_FIFOEN		0x0040		// FIFO enable bit
#define MRF_FBS_MASK		0x0030		// Mask for the band selection
#define MRF_LCS_MASK		0x000F		// Load capacitance mask
// 10pF Crystal load capacitance
#define MRF_LCS			3		// Crystal Load capacitance
// Frequency band settings
#define MRF_FBS_434		0x0010		// 434 mHz band
#define MRF_FBS_868		0x0020		// 868 mHz band
#define MRF_FBS_915		0x0030		// 915 mHz band

All of the files in the library depend on a “hardware.h” file that defines the qualities of the hardware.  The hope is that this file is the only place that implementation-specific code lives.  There are some holes still, however.  Finally, the mrf49xa.c and mrf49xa.h files behave the way you would expect.  The module requires a total of 5 pins and one interrupt.  Some of those pins may be shared with other SPI devices.

void MRF_init(void);

uint8_t MRF_is_idle();
uint16_t MRF_statusRead(void);

// Packet structures
// the maximum payload size
#define MRF_PAYLOAD_LEN 40
// Space for preamble, sync, length and dummy

typedef struct {
	uint8_t	length;
	char		payload[MRF_PAYLOAD_LEN];
} MRF_packet_t;

// Packet based functions
void MRF_transmit_packet(MRF_packet_t *packet);
MRF_packet_t* MRF_receive_packet();

I’ve included a snippet of the header file above so I could mention the basic process for using the MRF module.  The MRF_init function expects the SPI bus to be configured, and it performs the basic initialization of the device.  Once it’s started, the interrupts on the AVR must be enabled.  In the main loop (or at least as often as a packet can be transmitted) you should call MRF_receive_packet.  This function will return NULL if no packet was received, and a pointer to a packet structure if it was.  MRF_transmit_packet takes a packet structure and transmits it.  This is an asynchronous operation, and you may use the packet structure (or it’s memory) once it returns.  This is useful if you want to use a packet structure created on the stack.  It is possible to get yourself into trouble with MRF_packet_transmit, as it spin-loops on a lock set in the ISR.  If for whatever reason that lock isn’t unlocked at some point you can hardlock.  I’ve done my best to ensure that it doesn’t happen, but beware.

And, finally, links to the files.  If there seems to be sufficient interest, I’ll open up a SVN (maybe Google Code, who knows) with these files and a main program useful for telemetry and the like.  Post in the comments if you’re interested, or send me a line.







Also, the PCB is available as a public design from BatchPCB.  I’ll include a bill of materials if necessary, though the components are clearly printed on the silkscreen.

Oh!  before you ask: No, I don’t know what the range is.  The longest I’ve tried is about 20 feet, and there weren’t any errors, but it was only about 100 bytes.  The chip is rated to 7dBm, I think, so go from there. :)


Here is a simple bill of materials, I used the Eagle export feature, and attempted to place digikey part numbers for each part.  I’m not saying they’re all right, you may want to make sure you’re getting what you think is correct.


Also, here are the eagle files.  They aren’t necessarily finalized