3

I am writing a timer function that uses the micros() function which generates a unsigned long value. To compensate for a roll over condition, I would like to use the maximum value for that variable type. I have a number, 4,294,967,295, but was expecting that to be a constant somewhere.

Is there a MAX_UNSIGNED_LONG constant in the Arduino compiler files somewhere?

I have tried that name and know it probably isn't that. Still poking around.

7

Various limits.h files in the avr-gcc hierarchy define ULONG_MAX, which may be the value you want. For example, on my system such files have paths ending with hardware/tools/avr/lib/gcc/avr/4.8.1/include-fixed/limits.h or with hardware/tools/avr/lib/gcc/avr/4.8.1/install-tools/include/limits.h and contain definitions like the following.

/* Maximum value an `unsigned long int' can hold.  (Minimum is 0).  */
#undef ULONG_MAX
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)

Note, LONG_MAX also is defined in limits.h.

Note, arithmetic done in a form like

timeDelta = micros() - prevTime;

will be correct (regardless of whether micros() overflowed) for elapsed times up to 2³² microseconds, or about 4295 seconds.

1

You don't need "to compensate for a roll over condition".

See my answer: https://arduino.stackexchange.com/a/33577/10794


in an Arduino compiler?

The "Arduino" compiler is a C++ compiler. That is the starting point for most questions. If you Google for:

maximum unsigned long in c++

You will find the first link leads to:

http://www.cplusplus.com/reference/climits/

In that it says:

ULONG_MAX   Maximum value for an object of type unsigned long int
0

Did you try to do this?:

unsigned long maxUnsignedLong = 0UL - 1UL;

or:

const unsigned long ULONG_MAX = 0UL - 1UL;
-2

From network, seems to me, it is not that easy to find the right answer of the maximum value of micros() of my own arduino boards, too.
In my case, seems that micros() rolls over about every 17 seconds. Finally, I wrote the Setup() for myself to catch 0x1111111 as the maximum value of micros() as follows.

void setup () {
  Serial.begin( 115200 ); // set the baud rate for writing messages.
  int go = 1; // set the flag to continue do-while loop; 
  int n, nMin = 0, nMax = 0; // see how many more the numbers of calling micros() to get different value;
  int d, dMin, dMax; // see the time interval of micros() having different values;
  unsigned long currT; // the time of current micros() calling
  unsigned long lastT = micros(); // the time of last micros() calling
  unsigned long T[200]; // keep tracking 200 different lastT values
  int it = 0; // use T[it%200] to keep each lastT (circular buffer)
  do {
    n = 0;
    while( (currT=micros()) == lastT ) n++; // get a different value
    T[ (it++) % 200 ] = currT; // save the value
    d = currT - lastT; // get the difference
    if ( d<0 ) { // if micros() rolls over
      go = 0; // stop this do-while loop
      Serial.println(); // print new line
      for ( int i=it-200, j=0; i<it; i++ ) {
        Serial.printf( "%9x", T[i%200] ); // the last 200 different lastT values
        if ( ++j%5==0 ) Serial.println(); // 
      }
      Serial.printf("\nat %d ms lastT 0x%x currT 0x%x n=[%d..%d] d=[%d..%d]\n",
        millis(), lastT, currT, nMin, nMax, dMin,dMax);
    }
    if ( !nMin && !nMax ) nMin = nMax = n, dMin = dMax = d;
    if ( nMin>n ) {
      PRINTF( "\nat %d ms nMin %d > n %d ", millis(), nMin, n);
      nMin = n;
    } else if ( nMax<n ) {
      PRINTF( "\nat %d ms nMax %d < n %d", millis(), nMax, n );
      nMax = n;
    }
    if ( dMin>d ) dMin = d;
    else if ( dMax<d ) dMax = d;
    lastT = currT;
  } while( go );
}
  • refine the comment of "int n, nMin = 0, nMax = 0;" – sam suan chen Aug 21 '17 at 2:02
  • No, this is entirely wrong. See arduino.cc/en/Reference/Micros there a rollover time of about 70 minutes is given, which matches the maximum of an unsigned long in microseconds, converted to minutes (actually 71 and half minutes) – Chris Stratton Aug 21 '17 at 2:07
  • Well, I've seen the rollover time of about 70 minutes. But, I really don't know why, on my wifi boy esp32 board, the micros() calling does roll over about every 17 seconds. Could you image it? – sam suan chen Aug 21 '17 at 2:39
  • This kind of "catch it in the act" experiment is flawed to begin with, but then gets further mixed up in AVR vs ESP differences - for example, this code wouldn't even be valid on an AVR, where %d would misinterpret an unsigned long - it might "almost" work on an ESP32, but would still mix up the sign bit. You really should read the documentation, or the source code of the core. – Chris Stratton Aug 21 '17 at 2:44
  • I found that actually my wifiboy esp32 is running at 240 Mhz. So the max unsigned long value of macros() 0xffffffff / 240 is 0x1111111. This is exactly what I got. Thanks very much! – sam suan chen Aug 21 '17 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.