So, you haven't seen an update out of me in a while. This is because I've been struggling over the past week with getting my clock to return accurate, or at least consistently inaccurate results.
My test method was to use a little program that I wrote that would give me a 10 second count down before starting a timer that increments the LEDs once per minute. The idea was to use the 10 seconds to synchronize the timer with a timer known to be accurate and then let it run for a few hours and see how far off the minute mark it was. Take the number of seconds it's off, divide by total number of seconds elapsed, and multiply by 1 million to get the parts per million (ppm) accuracy.
See, every crystal oscillator needs to be "tuned" with some Load Capacitors. I tried my best to match the Load Caps to the 22pF rating on the crystal's spec sheet (even taking into account the parasitic capacitance on the breadboard), but I still couldn't get good results.
This is me measuring the capacitance that the crystal and chip would see (so, just the load capacitors). I tried to get it as close to 22pF as possible.
Note the two twisted wire pairs sticking up; each of those account for about 2-3pF and were very touchy.
The most upsetting part was how inconsistent my results were. The only certain thing was that wild variations in the capacitance made for wild variations in accuracy.
Well, it turns out that the timer on my iPod, which I assumed to be accurate, was far from it. After switching over to a Timex stopwatch, I got much nicer results. First, I managed to get around 30-35ppm consistently for over a day. Convinced that it was at least consistent, I tried lowering the load capacitance to see if I could improve accuracy. Dropping the 20pF caps for 15pF got me 20ppm accuracy.
I don't think I'll be able to exactly account for all of the capacitances that can interfere with my circuit's accuracy off hand. I think my official solution is going to be guessing the proper load capacitance in my final circuit, and replacing it with a different set of capacitors if it turns out not to be accurate. I'm actually fairly certain that this is how the pros do it. Build a prototype, figure out the best capacitance, and then repeat for 10000 more. At 20ppm, it would lose about 1.7 seconds a day. This is already perfectly acceptable, but I'm sure I can get it even closer when I build the final version.
On another semi-positive note, I got my accelerometer working!
So, convinced that my accelerometer was completely fried last time, I ripped it off the board to survey the damage. It looked like it had been soldered well, but it still didn't work. I was pretty certain that I had baked the chip too hard.
This time around, I wanted to be careful. I grabbed my Le Cruset pot and an infra-red temperature gun and attempted to simulate a reflow oven using a gas stove. The goal was to heat it at 200C for as long as it needed to melt the solder paste and then remove it immediately after.
I even got a video of it!
Well, after all of this, I was sad to learn that my chip still wasn't responding to any input. I simply couldn't get it to acknowledge its own address. This is exactly the behavior I got last time. Completely removing the chip got the same results.
The chip's address consists of a 7-bit number. When talking to it, you always add an 8th bit to indicate if you want to read from it (1) or write to it (0). The address is always sent first followed by the 8th indicator bit.
The address of the accelerometer was listed as 0011100. I was transmitting 00011100, using the aforementioned protocol for writing to the address, and the chip was ignoring me. Well, I was reading up on the I2C protocol at work today when I realized that I was an idiot.
In I2C, numbers are always transmitted most significant bit ("leftmost bit") first! That means that instead of sending 00011100, I should have been sending 00111000! Well, I tried this first thing when I got home, and I got the chip to talk!
Now, it still took me an hour to work out some of the details of getting something useful out of the chip, and I'm fairly convinced that the datasheet is wrong on this one...
The datasheet says that in order to receive a single byte from the chip, you must do the following:
Doing this resulted in me receiving the address of the chip as the current accelerometer data. This was the value that I loaded into the "TWDR" register that was supposed to be replaced by the data from the accelerometer. I was convinced that the whole thing just wasn't working and therefore not updating my register value. I struggled with this for about an hour or so (I had some other bugs along the way), but then I tried this:
This is for reading more than one byte from the slave. Note that the "master" (my microcontroller) sends an Master Acknowledge (MAK) after the first bit of data. Well, I found that for some reason, the first bit of data is always just the address that you sent it. The second piece, however, is what you really want.
I'm not really sure what's going on here. I never got the "single data" condition to return anything but an address, but I suppose I can live with just throwing out a garbage value to get to the good stuff...
The sheet even talks about a special mode of addressing (where you add 0x80 to the subaddress (register address) that you're looking for), that enables "multiple reads", but I'm still not entirely sure how that works. I think it's supposed to run through all the registers sequentially, but I haven't really found a use for it.
If more trouble crops up in the future, I'll look into these issues more, but as is, the accelerometer works exactly how I want to.
Here it is showing its Y data in binary!
It's 2's compliment with each digit representing about 18 milli-Gs. I turned it to 90 degrees and got back 0b111000 which works out to about 1.008G! Awesome!
Now, the real sad part of this story is that, convinced that I had blown yet another chip, I went ahead and ordered another breakout board...two actually (just to be safe), all before realizing my addressing error. That's another $20 down the drain unless I use another .5mm pitch LGA-16 chip in the future. Also, I'll never know for sure, but I might have never fried the first chip after all...