-1

I have two function implementations that I expected to work the same:

#define HEAD_STEP_DELAY 1000
unsigned long HeadLastMicros;
void HeadUpdate()
{
    if ((micros()>=HeadLastMicros) && ((micros()-HeadLastMicros)<HEAD_STEP_DELAY)) {
        return;
    }
    HeadLastMicros = micros();
    HeadStep(true);
}

and

#define HEAD_STEP_DELAY 1
unsigned long HeadLastMillis;
void HeadUpdate()
{
    if ((millis()>=HeadLastMillis) && ((millis()-HeadLastMillis)<HEAD_STEP_DELAY)) {
        return;
    }
    HeadLastMillis = millis();
    HeadStep(true);
}

I know that the resolution of micros() is limited to about 8us, but I figure given that I have a 1000us wait, both of the above ought to be relatively close to the same behavior. I'm driving a stepper motor from this code, and the stepper that used micros() was behaving erratically. I haven't put the scope on it yet, so I don't know for sure, but the torque was significantly less (motor stalled easily) and it sounded wonky.

I'm using an ATMEGA324A together with the MightyCore library.

Is there anything wrong with my approach? Thanks.

EDIT: I did put the scope on it after my initial post, and the period of the micros() code is approximately half the period of the millis() code.

smbaker
  • 19
  • 5

1 Answers1

4

First off, when dealing with a time system that wraps around, don't compare two times. Compare the differences.

Second, cache your function call results if you are going to use it more than once.

Third, if you want a consistent time interval, ask for it. Your current micros() based code could well take 1990µs on some iterations and 1001µs on others.

Fourth, don't use the current time more than once...

Do something like (not specifying millis() or micros()):

unsigned long HeadLast; /* This should be initialized somewhere (HeadStart()?),
                           as otherwise things could go weird.  
                           On the Arduino platform, initializing to 0
                           may work.  On other systems, time can start anywhen.
                           This caused Microsoft Windows to have trouble after
                           being up for 49 days (started at 0), while X Windows
                           has no such issue (start anywhen).
                           */
void HeadUpdate()
{
    /* compile with -O and this will optimize to a register. */
    unsigned long now = get_time_function();
/* We don't need to test now &gt;= HeadLast, as time is monotonic. */
if ((now-HeadLast)&lt;HEAD_STEP_DELAY)) {
    return;
}
/* Select the time we consider this to have started at.  
   This may well be before the current time. */
HeadLast += HEAD_STEP_DELAY;
HeadStep(true);

}

David G.
  • 161
  • 1
  • 1
  • 4