Hello. I have been prototyping a product using an Arduino Diecimila board and have run into a problem. I am hoping that you great guys on this forum could help me track it down, please.
Sometimes the time given my micros() is less than a time given by micros() previously. This happens quite often under the right circumstances and is not caused by the micros number overflowing as that should only happen about once every 70 minutes. Here is some code that exhibits the problem. I invite you to load it into your own arduino and see what happens.
Note that it uses interrupts and outputs its own signal on one of the pins to trigger the interrupt. I started with a program that listened to an interrupt caused by outside circuitry but switched to this so you all could see the problem without replicating the circuitry.
//Created by Andy D on 10-15-09
//
const int basebandPin=2; //digital pin. Must be either 2 or 3, because these are the only two interrupt pins.
unsigned long usSinceStart = 0; // overflows @ 70 minutes since reboot.
unsigned long prevUsSinceStart = 0;
unsigned long countTimeGoesForward = 0;
unsigned long countTimeGoesBackward = 0;
void setup ()
{
//open serial port
Serial.begin(9600);
//Set the baseband pin to input mode:
pinMode(basebandPin, INPUT);
pinMode(basebandPin, OUTPUT);
//Set up our interrupt:
//The "interrupt number" is 0 if we use digital pin 2 and 1 if we use digital pin 3.
attachInterrupt(0,basebandChangeInterrupt,CHANGE);
}
//Execuded on 0-1 or 1-0 transistions of basebandPin:
void basebandChangeInterrupt()
{
prevUsSinceStart = usSinceStart;
//Get our time Now.
usSinceStart=micros(); //This will go overflow after 70 minutes, and we should allow for that somehow.
//if time seems to go backgwards:
if ( usSinceStart < prevUsSinceStart)
{
countTimeGoesBackward=countTimeGoesBackward+1;
Serial.print("micros() is less than before! Time shouldn't go backwards. ");
Serial.print(prevUsSinceStart);
Serial.print("-> ");
Serial.print(usSinceStart);
Serial.print(". Diff is: -");
Serial.print(prevUsSinceStart-usSinceStart);
Serial.print(". Happens ");
Serial.print(countTimeGoesBackward);
Serial.print(" of ");
Serial.print(countTimeGoesForward+countTimeGoesBackward);
Serial.print(" times");
Serial.println(".");
Serial.print("micros() in binary is now: ");
Serial.println(usSinceStart,BIN);
}
else
{
countTimeGoesForward=countTimeGoesForward+1;
}
}
void loop ()
{
//Use this loop to cause an interrupt:
digitalWrite(basebandPin,HIGH);
digitalWrite(basebandPin,LOW);
}
If you run the code you'll get a stream of text like this:
"
micros() is less than before! Time shouldn't go backwards. 1074160-> 1073156. Diff is: -1004. Happens 42 of 63751 times.
micros() in binary is now: 100000110000000000100
micros() is less than before! Time shouldn't go backwards. 1082352-> 1081348. Diff is: -1004. Happens 43 of 64205 times.
micros() in binary is now: 100001000000000000100
micros() is less than before! Time shouldn't go backwards. 1129460-> 1128452. Diff is: -1008. Happens 44 of 67030 times.
micros() in binary is now: 100010011100000000100
micros() is less than before! Time shouldn't go backwards. 17015796-> 17014788. Diff is: -1008. Happens 885 of 993586 times.
micros() in binary is now: 1000000111010000000000100
micros() is less than before! Time shouldn't go backwards. 17044468-> 17043460. Diff is: -1008. Happens 886 of 995280 times.
micros() in binary is now: 1000001000001000000000100
micros() is less than before! Time shouldn't go backwards. 17057780-> 17056772. Diff is: -1008. Happens 887 of 996038 times.
micros() in binary is now: 1000001000100010000000100
micros() is less than before! Time shouldn't go backwards. 17059828-> 17058820. Diff is: -1008. Happens 888 of 996110 times.
micros() in binary is now: 1000001000100110000000100
"
You'll notice that time as returned by micros() is going backwards sometimes. That's a problem.
In an effort to diagnose the problem I learned that when micros goes backwards it is always about 1024 less than it should be at that point (I can't tell exactly because the time a loop takes varies). That suggests that the 11th least significant bit is a 0 when it should be a 1 or most of the 10 least significant bits are 0's when they should be 1's. Also the issue seems to have something to do with the code being in the interrupt because if I copy it to the loop() function micros() never goes backwards. Unfortunately I need to use the code in an interrupt for my purposes.
Looking closer I told my program to print the micros() time in binary. That showed something very interesting (see the above output from the program). Whenever it happens the 10 least significant bits are always "0000000100". Furthermore it seems to happen every 889/1003428 time the interrupt is called which is .9 times out of 1024.
If you're reading this, can you please try this code on your arduino and let me know if it has the same problem? Maybe there is an arduino that uses a microprocessor that does't exhibit this problem, that I can switch to. Also, any insight you can provide would be of great help! Thank you so much!
Sincerely,
Andy D