Hi Todd,

From your resume, we are definitely interested in your skill set.
We would like you to answer the following test question to help us
further gauge your abilities:
 
Assume that a small, portable device is being developed to measure the
speed of a bullet fired from a handgun.  An average bullet speed is 1000
mph, and the device should function in range of 300..3000 mph with the
measurement error not exceeding 5% throughout the whole range of speeds.
 
The device's sensor consists of two coils (inductors) that report a
pulse when a bullet flies through them.  The pulses are already
amplified to LVTTL 3.3V levels.  As the software engineer, your
responsibility is to measure the time difference between the two pulses
and convert it into a numeric reading (in miles per hour.)
 
The device uses an Atmel AVR MCU and displays the number on a 4-digit
LED display (multiplexed, common anode.)

One obvious concern here is that the AVR MCU may be somewhat slow, and
the precision of the measurement may be unacceptable.  Please ascertain
the factors involved, and propose whatever it takes to ensure the
quality of the measurement.

Please provide the source code (C) for the AVR microcontroller.  The
device, upon application of power, should display nothing.  After each
test shot the speed is displayed.

Christina

Hi Christina,

I was pleased by your test question, and I took it as an excuse to
play around a little with a microcontroller to do some interval
measurements.  I had never done this before (with a microcontroller),
but had often thought it would be useful.

I don't have an AVR, but I have an MSP430, so I used that.  The development
board consists of just a header board and a watch crystal (you can see it
in one of the pics).  It is well-supported by open tools.  I used msp430gcc,
and I included the C source as an attachment.

So I will describe the test setup I used, my thinking on the
precision issues, the code that I wrote, and how you can connect
to my microcontroller to run the code yourself.

---

The problem is to measure the A/B time between the two pulses with
adequate accuracy and resolution.  I will assume that the distance
between the sensors is one meter.  It was not stated, and this seems like
a reasonable distance.

For the given speed range, the interval A/B is actually kind of long.
Three thousand mph sounds fast, but it works out to an A/B interval of
about 750 microseconds through the one-meter path.  Three quarters of a
millisecond.

If you do the arithmetic at this upper end in terms of speed, it turns
out that you need to resolve approximately 35 microseconds in your time
measurement to meet the five percent velocity accuracy specification.
If you're counting clock ticks, the clock need only tick about 28 kHz or
so, minimum.  That's not very fast.

---

I wanted to be able to conveniently simulate the output of the
sensors, so I could run the code I developed for real.  I used
a simple Tektronix function generator to provide the pulses.  I
run the pulses through a flip-flop arranged as a divide-by-2,
and take the two outputs from Q and Q-bar.  Here's the schematic:
This gives me two separate pulses, out of phase, and I can
conveniently vary the time between with the ftn generator knob.  The
time here is independent of duty cycle, and depends only on the ftn
generator frequency.

So that's the simulation of the sensors.  I already had a flip-flop
conveniently wired from a previous project. (And this was the only one
I could find!) 

The setup is convenient, and also isolates (to some extent) my msp430
board from the function generator, so I am less likely to fry the former.

Here are some pics of the ftn generator and the signal board:

---

The MSP430 has a flexible clock system.  You can use a real xtal, up to
8 MHz I think.  But my system uses just a simple 32768 Hz watch
crystal.  This is not very limiting, because the chip can clock off
of an onchip high-freq oscillator, which is disciplined to the watch
xtal through a software loop.  It also has abundant I/O, timers, and my
version has at least two uarts built-in also.  (It's cheap, too.)

With this system I was able to do measurements of A/B time to an accuracy
of 5 microseconds or so.  I could probably do better, but this already
greatly exceeds the required accuracy.

I run the onboard clock at 1.536 MHz, and use the timer_A capture facility
to timestamp the rising transitions on the input.  The timer ticks
themselves are sub-microsecond resolution.

This clock speed is also convenient to run the on-chip uart, which I run
at 9600 baud.  This lets me conveniently communicate with the device over
a serial line.  I wrote a little command-line interface with which I can
specify various measurements to be made, and reported via the serial line.

---

The microcontroller itself hangs off of the rs232 port of a spare linux box.
It draws its power from the serial port, via a circuit that I had already
built up from a previous project.  This circuit also does the necessary
level conversion from bipolar rs232 to CMOS logic levels.

Schematic of circuit:
Picture of mcu and interface circuit hanging off the serial port of
a linux box:
To recap, the setup goes like this: Function generator to flip flop to
get two outputs to measure, A/B.  Those A/B outputs go to the MSP430,
which hangs off the serial port via another circuit which powers it
and level shifts.  (The MSP430 also connects to the parallel port, and
that's how I download code to it.)

---

The attached 
C file
is the complete source code, except for a standard module which at
startup initializes the clock (in this case, to 1.536 MHz), as sketched above.

Most of the code is user interface, and is involved with communicating
with the user through the serial port.  (Your problem mentioned an LED display,
but I just went ahead and used the uart.  No doubt I could drive the LED
if I needed to.)

The actual measurement code ended up being simple and flexible.  The measurements
are done by setting up a timer_A capture of an appropriate transition.  When
that happens, you get an interrupt and the timer value is stored in a register.
While you are waiting for such an event, you sleep.

The code looks, in some sense, non-microcontroller like.  For example,
the routine interval_time() takes a pair of function pointers which
do the actual measurements.  There is no tradeoff of accuracy here.
That's because the actual measurements are carefully done.  The code
is well factored and reused, but not by cut and paste.

It would be trivial to add commands to compute duty cycle and other things
of interest.
---

Here is a typescript from a recent session.  At the slow end:
N3TD interval timer for MSP430
    time -- measures and reports time elapsed between leading edges
    freq -- frequency, determined from measuring one cycle
    timeAB -- A/B interval timer, two different inputs
    bullet -- A/B interval, interpreted as velocity across 1 meter

Command> time
  period of A: 22615 ticks, 14723 microsecs

Command> freq
  frequency of A: 67 Hz

Command> timeAB
  A/B interval: 11309 ticks, 7362 microsecs

Command> bullet
  bullet speed: 303 mph

Command> 

Then I went to the function generator and cranked it up:
N3TD interval timer for MSP430
    time -- measures and reports time elapsed between leading edges
    freq -- frequency, determined from measuring one cycle
    timeAB -- A/B interval timer, two different inputs
    bullet -- A/B interval, interpreted as velocity across 1 meter

Command> time
  period of A: 1087 ticks, 707 microsecs

Command> freq
  frequency of A: 1414 Hz

Command> timeAB
  A/B interval: 544 ticks, 354 microsecs

Command> bullet
  bullet speed: 6338 mph

Command> 
---

I have a very accurate frequency counter hooked up also, so I can actually
measure the accuracy.  The actual period is 708.39 microseconds.  The accuracy
here is well more than specified (and the corresponding bullet speed is also
twice the required maximum).

I will omit the details, but the system as it is clearly does quite a bit
better than required by the problem, throughout its range.

---

Another big advantage of using the serial port is that it is easy to connect
it to things.  Through use of the standard "ser2net" program, I am able to
telnet to the linux box on a port, and be connected to the serial port.
Anything I type to telnet ends up going down the serial line to the
MSP430.  Conversely, anything the MSP430 sends out its serial line ends
up going out over the telnet connection.

That, in fact, is the only way I ever connected--with telnet.  I have set up
the routing here so that you may telnet to my location and run the code
yourself.  Please do!  You type the following

  telnet mathsym.org 2001

The port 2001 is important.  That gets routed to the MSP430.  When you
connect, just type Return and the MSP430 will give you the help
banner.  Just type any of the commands indicated.  I will leave the
function generator and all that connected for a few days.  You'll actually
be measuring whatever the ftn generator is set to.  If you want me to change
the freq, just let me know.

Here's what the setup ended up looking like, when it was all done:
You can see the counter I used to verify the accuracy.  For the timebase,
it uses the box below the table, which is a rubidium frequency reference.

---

Well, I enjoyed the little project.  I hope I was clear enough in my description
for you to be able to tell what I did.

In part I did this because I've been meaning to play with
microcontroller-as-test-equipment.  In part I wanted to demonstrate
that I am not afraid to get things done.

Please understand that, while I think the code is good, it is basically
a day-and-a-half project, start to finish.  If it were intended for production,
I would start out the same way, and be where I am now.  But I would then continue
and do more.  I would put a watchdog timer to catch bad measurments.  I would think
a bit harder about the numerical error of the various time-to-whatever conversions.

Most interestingly, I would investigate why the system isn't one or two orders of
magnitude better than it is.  It far exceeds the required accuracy, but I'm not sure
at this point why it isn't better.  It's not the watch xtal.  I measured it, and it
is accurate to within 2 ppm.  I suspect the high-speed DCO is involved, but it is a matter
for investigation.

But this has taken more time than I imagined, and I really wanted to respond to your
test question before the end of the week!

---

From what I've been able to figure out looking at your web page, and from the
attitude that I perceive from your posts and your question, I am very
interested in discussing with you further how I might be able to work on your
projects.

Sincerely,

Todd Doucet