Hello, I’ve been putting together some code for a chronograph, which has turned into an exercise in accessing the internal 16 bit timer on the ATMega chip. The project is now a .5 microsecond (I think) stopwatch with a couple of interrupts attached to some hypothetical optical sensors. Would somebody mind taking a brief cruise through the ISR and setup() functions to make sure I’m actually counting .5 microsecond ticks? Specifically, the steps that involve setting TCNT1 to 253.
Won’t work. Given the “interrupt overhead” and a 16 MHz clock (at best, 16 processor instructions per microsecond), your processor will be doing nothing but processing timer interrupts. You can’t get 0.5 microsecond resolution that way, and in any case the interrupts don’t occur at regular intervals. Look up “interrupt latency” to see why, but here is one discussion: http://www.embeddedrelated.com/usenet/e … 1437-1.php Also see this introduction to interrupts http://www.avrfreaks.net/index.php?name … ic&t=89843
Finally just for fun, count the number of machine instructions on an AVR required just to increment a 32 bit integer, in this case “ticks”:
That’s a good point. Here’s another try. Instead of using the overflow/comparator interrupt to count time, I’ve restructured the program so that the first sensor sets TCNT1 to 0, and the second sensor reads the value of TCNT1. With a prescaler of 8, it works out to .5 microseconds per increment. It also gives me a maximum time period of ~3.2 miliseconds to play with before the timer just rolls over and I have to add more code. Working with a distance of 20cm, this gives me a lower limit of 66.6 m/s (218.5 ft/s.) The code is messy, but here’s a 2nd draft:
The cleanest, most accurate and by far the fastest way to measure the timing of an external event is to use the Input Capture Register, designed for the purpose. Its use is described in the atmega328p data sheet, section 16.6.
Interesting. I have two events (1st gate and 2nd gate,) I suppose I could place one sensor on the ICP1 pin, and the other on the ACO pin. The other option would be to use the 1st gate to set the timer to 0, then use the input capture register to stamp the 2nd gate.
Any approach using two pins adds to the confusion. If you are interested in precisely timing a duration (and it seems that you are), you would like to know exactly how many clock cycles have elapsed between the start and stop events. This is hard to do if the processor is involved, and impossible if you are using interrupts.
Instead you could use external logic to combine the two gates into one signal, with either positive or negative successive edges signifying start and stop. Then you can use the IPC1 pin to time the difference between edges, with the final result accurate to one timer increment cycle. If the optical gates are “open collector” or “open drain”, then you don’t even need external logic. Just have the two outputs share a common resistor to Vcc and look for successive negative-going signals. This is called a wired-or connection.
hobz:
The project is now a .5 microsecond (I think) stopwatch with a couple of interrupts attached to some hypothetical optical sensors.
What is the use of the chronograph ? Is it to time the difference in time btw external events, aka the optical sensors ? If so then the interrupt latency isn’t an issue, it’s the variability in the latency. I don’t know what that is for an AVR but one of links suggested that the interrupt had to be sync’ed to the internal (16 MHz) clock. So each external event could be off by a max of 1 clock cycle. Then there was something about finishing the instruction presently executing, 3 clocks. Is that always 3 clocks or a max of 3 clocks ? Meaning btw 1 and 3 clocks for each external event.
The worst case timing error might then be 1 + 1 + 2 clocks or under 200 nsec.
jremington:
If the optical gates are “open collector” or “open drain”, then you don’t even need external logic. Just have the two outputs share a common resistor to Vcc and look for successive negative-going signals. This is called a wired-or connection.
This seems to be the simplest solution. I suppose instead of resetting TCNT1 on interrupt, the main loop would just add 65536 to the first timestamp if it was smaller than the second timestamp and do some subtraction. (2nd edit: nevermind, got it with the analog comparator. (edit: After reviewing the datasheet, it seems as though the input capture unit can only detect state changes, and not falling/rising edges. So, not quite so simple after all.))
Mee_n_Mac makes a good point, if there’s regular latency for both interrupts/sensors then it should all work out in the end. This brings me to my next question: sensor choice. It seems as though an IR reflective transceiver would give the best results, but I’m having trouble narrowing choosing one. Would the ubiquitous Sharp distance sensors give me the sensitivity needed? From the datasheet it seems as though there’s a 5 ms delay between sensor readings, but that’s been covered. Can anyone shed any light (tee hee) on this?
According to the data sheet, the input capture pin is indeed an edge detector. However, the synchronization logic introduces 2.5-3.5 clock cycles of delay before the event is captured, so there would be a one-clock uncertainty in the timing. For these sorts of reasons, people interested in accurate event timing rely on custom hardware.
The sensor choice will depend to some extent on the optical characteristics of whatever are you planning on detecting. Can you elaborate?
It may come to pass that I have to build a few of my own sensors. This component I found on mauser (http://ca.mouser.com/ProductDetail/Vish … q4%252bw==) shows some promise, but I’m holding out for something that’s hopefully easier to work with.
The projectiles passing through the chronograph would be quite variable, ranging from metal bullets to plastic BBs to the occasional (small) stuffed animal. Conceivably, there could even be a potato involved. The smallest thing would probably be a 6mm white ABS plastic sphere, followed by a .22LR alloy bullet. The unit will be used outdoors, so I’m hesitant to go with an ambient light sensor. So far most of the sensors I’ve found have a range of <10 cm, which is a bit close for comfort. The sensors don’t necessarily need to detect their range to the projectile, only that there IS a projectile.
Just for fun, here’s the present code:
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned long timePeriod = 0;
volatile unsigned long timeStamp1 = 0;
volatile unsigned long timeStamp2 = 0;
volatile unsigned char oldSREG;
volatile int ICUcounter = 0;
// Both sensor gates using a wired-or connection to ICU pin
ISR(TIMER1_CAPT_vect){ // Input Capture unit
oldSREG = SREG; // Save register
cli(); // Clear interrupts
if (ICUcounter == 0){ //If first gate, timestamp1
timeStamp1 = ICR1;
ICUcounter++; // Increment counter
SREG = oldSREG;
} else { // If second gate, timestamp2
timeStamp2 = ICR1;
ICUcounter++;
SREG = oldSREG;
}
}
void setup()
{
Serial.begin(9600) ;
cli(); // disable all interrupts
//Input capture sensor pin
ACSR |= (1 << ACBG); // enable bandgap filter
ACSR |= (1 << ACIS1); // Set for falling edge
DDRB &= ~(1 << DDB0); // Set as input
PCMSK0 |= (1 << PCINT0); // Enable interrupt
TIMSK1 |= (1 << ICIE1); // enable timer interrupt mask
ACSR |= (1 << ACIE); // enable analog comparator interrupt
//timer1 setup
TCCR1A = 0; // Clear control registers
TCCR1B = 0;
TCCR1B |= (1 << CS11); // 8 prescaler
TCNT1 = 0; // Start timer at 0
sei(); // Enable all interrupts
}
void loop()
{
float velocity = 0.0;
if (ICUcounter == 2){
oldSREG = SREG; // no interrupts
cli();
if (timeStamp1 > timeStamp2) // Adjust for 16 bit rollover
{
timeStamp1 += 65536;
}
velocity = (((timeStamp2 - timeStamp1)*1000L)/(F_CPU/1000L))<<3; // Determine velocity
Serial.print("Velocity (m/s): ");
Serial.println(velocity);
ICUcounter, timeStamp1, timeStamp2 = 0;
SREG = oldSREG;
}
}
Photointerruptors would work to detect all those projectiles, although you would need to pay attention to the ambient light. They consist of a light source (LED) and a detector (phototransistor), usually with lenses to focus the beam. You can buy the components separately (http://www.sparkfun.com/products/241) or as a unit. The phototransistor will produce a high-going pulse as the light beam is momentarily interrupted.
Obviously the % of light blocked will be dependent on the physical size of the object; a BB … very little, your little brother … a whole lot. Most chrono’s I’ve seen at the range (mine included) use ambient light, which of course can vary from hour to hour, day to day. So either you have a fixed threshold, such that a voltage below that indicates an object above the sensor, and adjust it all the time. Or you use a comparator circuit with a strongly filtered (very slowly changing) input and a less filtered input. When the difference btw the 2 is some voltage, the comparator changes state.
As for the accuracy of your chrono … what are you looking for ? Most are +/-1% absolute accuracy and better relatively, which I think is more important if you’re reloading. No matter what you do, count on having to calibrate yours as the X-tal in the Arduino won’t be exactly 16 MHz, the distance btw screens/sensors won’t be exactly what you think it is, etc, etc. An O-scope would be most desired.
If the sensors are 18" apart, that’s 1.5 msec at 1000 FPS. The fastest thing I’ve ever seen run across is a .223 at about 3500 FPS. Obviously that’s about 428 usec. A 1% error is then about 4 usec, almost a factor of 10x from what you are looking for. Make up an error budget but be realistic.
No more progress on the code, but I’ve moved (with much protest and profanity) into the realm of sensor design. It seems as though I may end up building two versions of the chrono, one for the airsoft enthusiasts in my life (max velocity 500 fps, fits into a toy suppressor) and a bench rest version that will handle higher velocities (~1200 m/s) and an open sensor field. This would require two different kinds of sensors; the former a photo interruptor, and the latter a beam reflector.
The photo interruptor looks fairly straightforward, but isn’t really my main project. The sensors JRemington linked would work for the interruptor, and probably for the reflector as well. The dropoff time was measured to be about 250 uS, which is longer than I’d like. I also found these (http://www.digikey.ca/product-detail/en … ND/2798873), which have a quick response time. Depending on the sensitivity, using a NAND setup and building an array of these detectors into each gate may be necessary. Amplifying the sensor output may also be necessary. Looks like I may have to do more circuit design than I had anticipated.
In regards to accuracy, I’d like to get it as accurate as possible within the limits of reason. Better than +/- 1% absolute would be great, but with the right sensors and some careful measuring it may be possible to be more accurate. We’ll have to see once the parts start coming together.
For really fast response you need a photodiode rather than a phototransistor as the detector, with PIN diodes being the fastest (and most expensive). You will need amplification to turn these detectors into a usable digital signal and probably on an open configuration, input filters to minimize the effects of ambient light. Have fun!
I managed to find this amplifier schematic in an old nutz 'n voltz, which has been helpful in getting some ideas off the ground. There’s also some interesting stuff in the hamamatsu application guide.
The nuts & volts article is interesting, but I didn’t see where the author comments on the accuracy of the measurements. The LM224 is a slow op amp. Given that all screens would have about the same delay in response to projectile passage, perhaps the response times cancel out.
hobz:
Depending on the sensitivity, using a NAND setup and building an array of these detectors into each gate may be necessary. Amplifying the sensor output may also be necessary. Looks like I may have to do more circuit design than I had anticipated.
You need to come up with a good understanding of what's needed for a sensor (or array). A large FOV means the shadow created by the projectile is relatively small, meaning a smaller change in sensor output (lower sensitivity). An array means the sensors need to be aligned and the outputs combined. I am less than certain that IR sensors are the correct choice to maximize sensitivity. You need to consider the top speed you wish to measure. A short .223 bullet might be 0.68 in long and doing 4000 fps create a pulse perhaps as short as 15 usec, meaning something like at least a 100kHz BW. Higher speeds mean even larger BWs and proportionally more noise and thus requiring more *true* sensitivity out of the sensor to compensate.
Since you will have to mechanically place the 2 sensors, your final accuracy will likely depend more on your calibration accuracy than anything else.
Just to illustrate one way to process a sensor output, that allows “slow” but relatively large variations in output level while still detecting short pulses (due to the target). Naturally scaling, BWs and polarity are open for change.
Just to see if I’m interpreting this correctly, in the above schematic, the sensors V1/V2 are wired in series to the ± input of the opamp, the frequency of which is adjusted/determined by the value of Rled + 68 ohms for the NSCW100. Would sensorOut be where the analog pin would connect, or would that be where the LED is placed on U1?
The above circuit was a quickie modification of one I already had simulated. So the output components are not representative of what you’d probably do … it was just an easy way to demonstrate the concept.
So whatever sensor you might use was modeled by the series combo of voltage sources V1 and V2 ('cuz V1 already existed in the old model sim). V1 represents (not too realistically) the varying sensor output due to changing light falling on the sensor, perhaps due to clouds. The intent was to show a circuit that didn’t false trigger even when the ambient light changed by perhaps +/- 50%. V2 is the response due to a projectile passing over the sensor (in this case; a 1v drop for 15 usec). The combined output voltage of this hypothetical sensor is shown in the green plot. The red plot is then the current through the LED (pre-existing in the sim), really just an indication that the comparator changed state. You could well choose a different comparator and wire it to make a positive going voltage (vs the open collector of the device used from my prior sim). In either case I’d expect the comparator output to go to the MCU CCP input pin(s), perhaps w/a pull-up resistor, so as to start and stop the timing of the projectile.
Again the intent was to show how a comparator could be used to detect a quick pulse despite a large, slowly varying, change in sensor output. No moment-by-moment sensitivity adjustment needed (though possible by varying R3). This being accomplished by comparing a heavily LPF’ed path, scaled, to a less filtered path. A more complete understanding of the circuit req’s and component values TBD if that’s the circuit that becomes a prime choice. A lot of detail depends on the sensor chosen.