0
Offline
Newbie
Karma: 0
Posts: 26
Arduino rocks
|
 |
« on: October 28, 2007, 09:02:23 pm » |
Hi,
Is it possible to set an interrupt to go off every x number of microseconds? I've searched some and not found anything.
Or is there anyway to get something like a millis() function for micros? Right now I use 2 calls to millis and subtract the difference to get an approx microsend count.
Thanks.
|
|
|
|
|
Logged
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5450
Strongly opinionated, but not official!
|
 |
« Reply #1 on: October 29, 2007, 04:08:45 am » |
the timer that drives millis() ticks every 4 microseconds, but only interrupts on overflows (256 ticks, which is "about" 1 millisecond.) Interrupting every microsecond would probably be a bad idea, but you can get a higher resolution clock by reading the timer and timer overflow directly instead of using millis(); I'll see if I can come up with a concise example.
|
|
|
|
|
Logged
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5450
Strongly opinionated, but not official!
|
 |
« Reply #2 on: October 29, 2007, 04:28:14 am » |
This seems to work ok: /* * High precision time demo */
extern volatile unsigned long timer0_overflow_count;
unsigned long hpticks (void) { return (timer0_overflow_count << 8) + TCNT0; } void setup (void) { Serial.begin(38400); }
void loop (void) { unsigned long hptime, mstime;
if (Serial.read() > 0) { mstime = millis(); hptime = hpticks()*4; // convert ticks to microseconds Serial.print("millis = "); Serial.print(mstime); Serial.print(", high precision time = "); Serial.print(hptime); Serial.println(" "); } }
And from the serial monitor:
millis = 2948, high precision time = 2948816 millis = 7030, high precision time = 7031796 millis = 17497, high precision time = 17497508
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 119
Arduino rocks
|
 |
« Reply #3 on: November 05, 2007, 01:28:08 pm » |
awesome!
thanks very much for that function westfw. its pretty much exactly what i was looking for. here's a question:
what timespan do those ticks represent? from what i gather, they are about 4 usecs, is that right? i plan on using this function to determine when to send a pulse for a stepper that needs < 1 milli resolution, so hopefully it will work for that.
thanks!
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 119
Arduino rocks
|
 |
« Reply #4 on: November 05, 2007, 03:12:38 pm » |
nevermind... i posted that before i read the rest of your code. i think i got it now.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 119
Arduino rocks
|
 |
« Reply #5 on: November 06, 2007, 10:58:24 am » |
hey, just wanted to say thanks again for your help. with this function, i was able to get non-blocking stepper control working!!! if you've ever used the built-in stepper library for arduino, you know that its blocking... ie you either have to call each step manually, or just deal with waiting until the steps are done to do more stuff. using this function, i made a class so that you simply do if(stepper.canStep()) stepper.step(); and the stepper will step at the appropriate time, at the appropriate RPM. this is nice because you can do things like control multiple steppers independently, etc. more info, video, and code in blog post: http://builders.reprap.org/2007/11/non-blocking-stepper-control.html
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #6 on: December 23, 2008, 11:01:00 pm » |
This code doesn't seem to work any more. I get an error when compiling: undefined reference to 'timer0_overflow_count'
Any suggestions on how to fix this?
Thanks, Mike
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #7 on: December 24, 2008, 02:07:30 am » |
I managed to work out my own solution, but I'd still be interested in why timer0_overflow_count doesn't seem to exist anymore. My code for the curious: double tElapsed=0; //Refer to document http://www.atmel.com/dyn/resources/prod_documents/doc7530.pdf TCCR1A=0; //set WGM mode to normal. Refer to table 15-4 of above doc TCCR1B=B100; //set prescaler = 256. Refer to table 15-5 of above doc int prescaler=256; TCNT1=0; //set timer to 0. This is a 16 bit timer. Timer overflows at 1.048 seconds with prescaler=256
//...time an event or some code tElapsed = TCNT1*1.0/16E6*prescaler; //time in seconds
|
|
|
|
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #8 on: December 24, 2008, 08:00:20 am » |
Hi MikeD, Floating point is wasteful processing time (and memory) and should be avoided if possible in code that is time critical. Also, the code posted above uses a prescaler of 256 so with a 16mhz clock it can have an error of up to 127 microseconds. Here is a thread that has a discussion on precise timing on the Arduino: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226014847
|
|
|
|
« Last Edit: December 24, 2008, 08:01:59 am by mem »
|
Logged
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5450
Strongly opinionated, but not official!
|
 |
« Reply #9 on: December 24, 2008, 08:49:59 pm » |
I'd still be interested in why timer0_overflow_count doesn't seem to exist anymore. The old timer0/millis() algorithms had a significant problem with integer overflows after sketches had been running for "a while." In 0012, the way times were calculated was changed to fix this, and in the process it eliminated the timer0_overflow_count()
|
|
|
|
|
Logged
|
|
|
|
|
|