Pages: [1]   Go Down
Author Topic: microsecond interrupt?  (Read 3793 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Tesla Member
***
Karma: 106
Posts: 6371
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Tesla Member
***
Karma: 106
Posts: 6371
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This seems to work ok:
Code:
/*
 * 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(" ");
    }
}
Code:
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 Offline
Full Member
***
Karma: 0
Posts: 119
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Full Member
***
Karma: 0
Posts: 119
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nevermind... i posted that before i read the rest of your code.  i think i got it now.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 119
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
 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 Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Tesla Member
***
Karma: 106
Posts: 6371
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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

Pages: [1]   Go Up
Jump to: