Pages: [1]   Go Down
Author Topic: velocity measuring chronograph  (Read 3535 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hello all arduiners!

Im trying to build my own chronograph so that I can measure the bullit velocity of my airgun.

hardware: 2 barriers with optosensors (working)

conditions: approx speed: 100-250m/s  ,, measuring distance: 0.1 -0.3m

software: need to count elapsed microseconds between sensor 1 & 2

basic idea: sensor 1 pulse = interrupt -> start timer ,, sensor 2 pulse = interrupt (?) -> stop timer -> save value -> calc speed given the distance -> print speed (and kinetic energy) on my 4x20 lcd


problem: using the right timer/method to prevent overflow and errors but still keeping the best resolution possible.



I have read thread after thread but haven't find the right info how to do this. I would be very grateful if someone could help me out with some code!! please keep in mind that I'm a beginner in programing

best regards //Oscar

Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
hardware: 2 barriers with optosensors (working)

I wouldn't mind seeing a schematic/diagram of this part...

Check out the micros() function.  I don't know what your hardware looks like, but I'd probably set up an ISR for each input, and grab the output of micros() for start and stop times, respectively.

-j
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I suggest you keep it simple. No need for interrupts because the sketch does not need to do anything else while waiting for the timing pulses.

Your loop could wait for the first sensor to change state. When that was detected, you call pulseIn on the second sensor to return the number of microseconds between pulses.  
Logged

Calgary, AB, Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 196
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As above, KISS applies.

Assuming your sensors give you a '1' normally and a '0' when beam is interrupted, and you are connected to pins 2 and 3:

Code:

while (digitalRead(2) == 1)
{
  //Wait for first sensor to trip
}
start_time=micros();
while(digitalRead(3) == 1)
{
  //First sensor was tripped, now wait for second sensor to trip
}
stop_time=micros();
calculated_time=stop_time - start_time;

Overflow is stated as around 70 minutes, so just make sure you reset the system right before you use it, and you'll be fine.
« Last Edit: July 04, 2009, 02:31:09 pm by brutus1975 » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It works! cant believe it was to be that easy, thanks a lot!!


1 have I interpreted the code right?

while (digitalRead(2) == 0)
{
  //Wait for first sensor to trip  
because here is no instruction: do nothing while sensor1 isn't tripped else start_time=micros();
}

and the same approach apply stop_time=micros()

2 in the loop, does it check the conditions of both sensor 1 and 2 every time? wouldnt it be best if it only check sensor 1 and only if it was tripped, start checking condition of sensor 2.

3 is it okey for me to put the rest of my code (display etc) underneath stop_time=micros(); ,, it will not disrupt the time critical start and stop code?


4 the function micros delivers one us at a time but has a resolution of 4us. meaning that the function multiplying the timers value by 4 just before delivering it to me?


5 what is the best method to do the math, keeping the resolution and display a value with say two decimals?

calculated_speed=((1000000*distance)/calculated_time);

1000.000 is for getting the value in m/s and not m/us  but then it of course gives me a value without decimals.

I can display my schematic later if you want, but it's very simple and only consist of 2 x transistors & IR photo diode/transistor


hope you bare with all my questions! thanks!
//Oscar
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24298
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
in the loop, does it check the conditions of both sensor 1 and 2 every time? wouldnt it be best if it only check sensor 1 and only if it was tripped, start checking condition of sensor 2.

Don't forget that each "while" loop blocks, that is they just sit and loop doing nothing but read the input pin until the condition evaluates to FALSE, so "loop ()" cannot get called again.
In the example, "loop" will only be called again after the "calculated_time" arithmetic has been executed.
So, yes, putting display code before the end of "loop" is the correct place to put it. At this point, there is no time-critical code, until "loop" gets called again.

Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Calgary, AB, Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 196
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
1 have I interpreted the code right?
for first sensor to trip  
because here is no instruction: do nothing while sensor1 isn't tripped else start_time=micros();

As stated, it just waits around for the sensor to trip.  Nothing Else.

Quote
and the same approach apply stop_time=micros()

Yep

Quote
2 in the loop, does it check the conditions of both sensor 1 and 2 every time? wouldnt it be best if it only check sensor 1 and only if it was tripped, start checking condition of sensor 2.

No code will execute during the WHILE loops.  Until that sensor trips, it's just going to keep checking the sensor.  Read THIS

Quote
3 is it okey for me to put the rest of my code (display etc) underneath stop_time=micros(); ,, it will not disrupt the time critical start and stop code?

Yep, you're fine to put it under that.  You can even wrap all the above into a function and just call it when you want the timed event.


Quote
4 the function micros delivers one us at a time but has a resolution of 4us. meaning that the function multiplying the timers value by 4 just before delivering it to me?

I would take that to mean it's rounded to the nearest 4µs.  So if it actual = 317µs, it would return 320µs


Quote
5 what is the best method to do the math, keeping the resolution and display a value with say two decimals?

calculated_speed=((1000000*distance)/calculated_time);

1000.000 is for getting the value in m/s and not m/us  but then it of course gives me a value without decimals.

Your call on that one smiley-wink

Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code with 2 while loops (known as blocking, because processing stops or blocks until you get an input) could require the occasional reset.  If the first sensor misses the signal it's no big deal.  If the second sensor misses, the system will hang until the second sensor triggers (e.g. on your next shot) or you reset the system.

-j
Logged

Calgary, AB, Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 196
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

probably could do with a break out condition in second loop.

While waiting for second sensor to trip, if > 1000ms elapsed, break and print error out.

if you're aiming for somewhere between 300 and 400fps, 1 sec is plenty of time to decide something's wrong.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now it is time again!

The chrono works very well!
Now I just want to display the value with decimals but don't know how to do this without building up arrays.

To get the display working I'm using Tomeks code found under
"4-bit mode with Hitachi LCD controller" in the playground area

actual code: http://www.arduino.cc/playground/uploads/Code/codeexample_lcd.txt


This allows me to display a number between 000-999

I want the value to be displayed on the form:  xxx.xxxx
and also without the zeros in front of the displayed value (example: 001 should only be 1 )


 :smiley


Logged

Offline Offline
Edison Member
*
Karma: 3
Posts: 1001
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The chrono works very well!
If you need decimal precision on your speed measurements, you may have to revisit your chrono code.  :-/

If your chrono code is based on above I'm afraid you've only scratched the surface when it comes to precise microsecond timing. At a speed of 250 m/s measured time over 20cm would be 800 microseconds. The code as written above will barely make it into the +/- 10% accuracy range for this interval.

Issues include the following:

- the micros function relies on a timer with 4 microsecond resolution (it is not averaged as BRuTuS suggests).
- digitalRead takes several microseconds to execute and the sensor may trip any time within this interval. The timing error for sensor 1 and 2 may accumulate.
- the Arduino core timer interrupt may execute any time between sensor 1 and sensor 2. The time it takes to service this interrupt may further add to the error.

So then what are the alternatives:

- Software timing
The Arduino pulseIn function relies on software timing loops that are quite accurate (sub microsecond). A careful rewrite of this function to serve your needs may be one way to go.

- 16-bit hardware timer
Another possibility is to measure time based off the AtMega 16-bit timer at full speed (16 ticks per microsecond on a 16MHz Arduino).

Coding for these alternatives however is non-trivial and requires quite some intimate knowledge and understanding of the Arduino/AtMega hardware. The potential is there however to get down to better than +/- one microsecond accuracy.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sorry for a late response in this thread BenF

I'm aware that this isn't the most effective programing but more about that further down. I need to know how to display float values (or values with decimals), not just to display velocity but also in setup functions (example: set bullet weight in grams)  

the consistency in velocity readings seems fairly god. with my softairgun (rated to 70m/s) I always get a reading of 68 +/- 2 (m/s)
but you are absolutly right that the timing becomes critical in high speeds and you mentions very good aspects witch some I have already taught of.
 
1. is there a better timer (than the 4us clock)?
2. the problem with digital read, would a interrupt be a better solution?
3. can you explain "core timer interrupt"





Logged

Waterloo, Canada
Offline Offline
Full Member
***
Karma: 1
Posts: 242
Engineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

With decimal precision...
Code:
float calculated_speed;
...
calculated_speed = (float(1000000*distance)/float(calculated_time));

For faster digitalread see http://arduino.cc/en/Reference/PortManipulation

By "core timer interrupt" I think BenF is referring to the overflow interrupt Arduino uses for delay() function monitoring.  This will occur regularly and will delay other chip activities by some small amount when it does.

The more advanced timer mode you would be interested in for this application is the "Input Capture Unit" which will capture the time of a digital input event when it occurs.  With this you could probably achieve resolution of  ~ 100 ns.
Logged

Lancashire, UK
Offline Offline
Edison Member
*
Karma: 8
Posts: 1992
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Increase the measuring distance and thus the time interval ?  

Logged


Pages: [1]   Go Up
Jump to: