Thanks everyone for your help so far. My Mega8 Orangutan is working well with the new Avrisp mkII, and I am very pleased with the MaxBotix sonar. Now I’m getting a little more into unknown (to me) territory, so forgive me if this sounds daft.
I am a mechanical engineering master’s student working at a robotics research lab, and I have recently been shifted onto a new project involving a flying robot (most likely a quad-rotor helicopter). Right now I am the only person working on this project, but we are hoping to stir up interest (funding) with a sort of functional mockup prototype of our concept. That is to say something that doesn’t necessarily fly on its own (although that would be nice), but that demonstrates and validates the electromechanical feasibility of every part of our system design. Then we can hire students from all the other departments to design custom hardware and program it, and show me everything I don’t know about electronics and device interfacing and microcontroller programming (don’t I wish!).
So, my immediate challenge: I need to synchronize two periodic logic pulse signals, from different microcontrollers that aren’t connected in any way. I would love to use Baby Orangutan’s for this, since I have two, and I want to learn to do more with them. In the end my hope is to trigger two MaxBotix sonars simultaneously. One of these sonars will be on the airframe, pointed vaguely down, while the other is on a pan-tilt sensor platform that will be precisely aimed at the first. The sonar on the airframe will receive the pulse from the ground station rather than its own reflected pulse, and send back the range from the ground station over a serial radio.
I have already tested this principle by triggering both sonars together with long wires. The beam is narrow, but if one sonar is well aimed at the other, I can get good readings from some decent ranges and angles up to about 80 degrees off normal. It helps that the pulse is a lot stronger when it hasn’t reflected off of a surface. Another advantage in using two sonars in a straight line is that I double the range, although I halve the resolution…
Anyway, I have a serial radio (LPRS Easy Radio) connected to one of the sonars, and my original thought was to just trigger both sonars with a serial character from one com port with a split line, i.e. going over a wire to one sonar and the serial radio to another. This obviously did not work, because there is about a 19ms delay between the beginning of the packet being sent to the ground radio transceiver, and the beginning of the packet coming out of the remote transceiver (in this time the ultrasonic pulse travels about six and a half meters in this time, I want to keep the added error under an inch!).
My next idea was to artificially match this delay on the ground with one of the Baby O’s (a horrible waste of potential I know, but we will add other functionality to it over time). I wrote some code that waits for an input pin to be brought high, delays using the avr delay.h library, then brings an output pin high. This would be problem-solved, except upon closer inspection (yay for oscilloscopes!) there is a random variability in the signal transmit/receive delay. This variability is small, +/- ~0.19ms, or +/- ~2.5 in but it jumps around that range unpredictably! It isn’t a problem if there is a small range error, or if that error grows over time, but if the range reading is jumping wildly up to five inches all the time it will be much harder to keep the airframe steady.
My professor’s suggestion at our last meeting was to simply (sure) synchronize two microcontrollers shortly before an experiment, and have them trigger the sonars periodically. I modified my simple delay code to loop, brought the reset and ground lines of my two Baby Orangutans together, reset them together, and separated them. Not surprisingly, the ceramic resonators weren’t all that accurate (well with their spec of course), and the periodic signals diverged by the equivalent of about an inch of error each second, but it was a start.
Now, as a mechanical engineer, my first impulse was to go find a more accurate crystal oscillator, do a little fine soldering, and watch my problems disappear. To run a ten minute experiment (about the battery life of our test airframe) with less than 1 inch of range error caused by pulse drift I would need crystals with frequencies accurate to 0.12 ppm. My quick math may be wrong, but I think the order of magnitude is correct, and all the oscillators I’m seeing on Digikey have tolerences of around 20 ppm. Also, articles on AVRFreaks make me think that getting a (non-real-time) crystal oscillator to work with an AVR is not as trivial as plug-and-play.
I still think this can be done with the baby Orangutans, and my oscilloscope tests make me think it might even work with their stock ceramic resonators, by running a real calibration between them at the beginning of each experiment. My level of AVR programming experience consists of copy-pasting C++ code (mostly from this forum) but I think I have a basic understanding of what I need to do.
One Orangutan will be the master, and one will be the slave. I will set a timer on the master O to bring a pin high briefly (30uS or so) five times a second (or so). This pin will eventually be hooked up to one of the sonars, but to start I will connect it to an interrupt pin on the slave O. The first pulse will cause an interrupt on the slave to start its own timer. When the slave is interrupted again ~250ms later the value of its timer will be written to a register. At the third pulse the slave will start its own timer counting repeatedly to the value stored in this register (and disable further interrupts). This timer will now be tied to an output pin on the slave, and I’m ready to go. The master will continue outputting a triggering pulse every 4,000,000 clock cycles, while the slave outputs one every 4,000,001 (or, you know, whatever) cycles. These pulses will of course drift apart, but if I can calibrate them to within a few clock cycles of optimal I think it will work.
In case you couldn’t tell I’ve italicized the words that I think I understand as abstract concepts, but not at all how to implement them in AVR architecture. Of course I’m not asking anyone to whip up a code for me, but more for a few pointers and a general stupidity check:
Is what I’m trying to do even feasible?
Is my current approach correct or flawed?
Am I misunderstanding something fundamental (i.e. “you can’t count that many clock cycles on a single timer”, or “you’ll have to do that in assembly code”)?
Is the hardware of the Baby Orangutan sufficient?
And of course, is there a simpler/better way to achieve my end goal (like “Oh, the Maxstream XBee serial radios have an instentaneous logic pin, plus they cost less!”)?
Thanks for reading this far, I tried to include all the background and reference information I always want when someone asks a short question on the forum that obviously has much wider significance. I wonder if I get the prize for longest (code-less) post?
-Adam