Overflow, micros() ???

I'm not certain it is the micros() overflowing, but my Arduino does in fact stop working after 70 minutes. The part I think is overflowing is

    pulseIn(pps, HIGH, 2000000);
    fds = micros();
    pulseIn(freq, HIGH);
    fde = micros();
    freqdelay = (3000 + adj) - (fde - fds);

But I don't understand well why it would

Entire code at the moment...

#include <EEPROM.h>
char incomingByte = 0;
int freq = 7;
int pps = 8;
int pv = 12;
uint32_t fds = 0;
uint32_t fde = 0;
int freqdelay = 3750;
int c = 1;
int CTB = 9;
int adj = 0;

void setup() {
  Serial.begin(115200);
  int a = EEPROM.read(0);
  int b = EEPROM.read(1);
  int c = EEPROM.read(2);
  if(c == 0)
  {
    adj = a*256+b;
    adj = adj * -1;
  }
  if (c > 0)
  {
    adj = a*256+b;
  }
   

}

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
  }
  if(incomingByte == 'x')
  {
    for (uint32_t i=c; i>0; i--)
      pulseIn(freq, HIGH);
    delayMicroseconds(freqdelay);
    digitalWrite(CTB, HIGH);
    delay(5);
    digitalWrite(CTB, LOW);
    incomingByte = 0;
    pulseIn(pps, HIGH, 2000000);
    fds = micros();
    pulseIn(freq, HIGH);
    fde = micros();
    freqdelay = (3000 + adj) - (fde - fds);
    Serial.println(freqdelay);
  }
  if(incomingByte == '+')
  {
    incomingByte = 0;
    adj = adj++;
    Serial.print("The adjustment is now ");
    Serial.print(adj);
    Serial.println(" microseconds");    
  }

  if(incomingByte == '-')
  {
    incomingByte = 0;
    adj = adj--;
    Serial.print("The adjustment is now ");
    Serial.print(adj);
    Serial.println(" microseconds");
  }

  if(incomingByte == 'a')
  {
    incomingByte = 0;
    pulseIn(pps, HIGH);
    fds = micros();
    pulseIn(freq, HIGH);
    fde = micros();
    freqdelay = (3750 + adj) - (750 + (fde - fds));
    Serial.print("The adjustment has being applied to the delay has now being adjusted an it currently is ");
    Serial.println(freqdelay);
  }

  if(incomingByte == 's')
  {
    if(adj < 0)
    {
      int c = 0;
      EEPROM.write(2,c);
      adj = adj * -1;
      int a = adj/256;
      int b = adj % 256;
      EEPROM.write(0,a);
      EEPROM.write(1,b);
    }
    if(adj > 0)
    {
      int a = adj/256;
      int b = adj % 256;
      EEPROM.write(0,a);
      EEPROM.write(1,b);
    }
      

  }

}

I think you need to make all the variables that are dealing with the micros() data to be the same type, unsigned long.
You seem to have a mix of variable types, for example:
uint32_t fde = 0;
int freqdelay = 3750; <<< probably should be uint32_t here also as one example

I will change it as you suggested, but this variable is meant to be less than 4000 at any given time, but who knows.

    fds = micros();
    pulseIn(freq, HIGH);
    fde = micros();
    freqdelay = (3000 + adj) - (fde - fds);

This code is likely to fail on rollover. it is possible for micros() to rollover from the time you store fds until the time you store fde. In which case you are subtracting something similar to 0 - 0xFFFF....

Subtraction after rollover is guaranteed to give the correct results. 0 - 0xFFFF = 1.

1 Like

So if the rollover happens right then, it will give me an error, but not if it happens before or after that part of the code, so is likely to fail at a roll over at any given time. This is pretty bad even if it happens every once in a while so I need to find a way to account for this or another way to count without having to worry about the overflow. How about resetting micros?

bastukee:
So if the rollover happens right then, it will give me an error

No. So long as you use unsigned integers and subtract the two values you will arrive at an accurate delta.

so I need to find a way to account for this or another way to count without having to worry about the overflow

No, you don't. Use unsigned long. Subtract the stop time from the start. It is really that simple.

How about resetting micros?

Unnecessary.

Ok Thank you, I have it running overnight at work with the unsigned long now, I will check it out in the morning to see if it worked.

Seems that the overflow might be gone, it ran for hours no problem, but I'm running into another issue.

Initially I was using a 10 pps signal on pps pin 8, the goal is to use a 1 pps instead. I figure it would not change a thing on my code to make it work, but once I chance it to 1 pps, the time measured runs a bit wild. I have my code printing the value of freqdelay and this is what I"m getting.

880
1444
2004
2572
1140
1700
2264
832
1396

This is the code that executes the time read and printout

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
  }
  if(incomingByte == 'x')
  {
    for (uint32_t i=c; i>0; i--)
      pulseIn(freq, HIGH);
    delayMicroseconds(freqdelay);
    digitalWrite(CTB, HIGH);
    delay(5);
    digitalWrite(CTB, LOW);
    incomingByte = 0;
    pulseIn(pps, HIGH, 2000000);
    fds = micros();
    pulseIn(freq, HIGH);
    fde = micros();
    freqdelay = (3000 + adj) - (fde - fds);
    Serial.println(freqdelay);
  }

So why would 10 pps vs 1 pps be different? I tried extending the pulsein delay from 1 second to 2 but it does not seem to help.

I don't understand much here
10 pps => 10 pulses per second?
1 pps then is 1 pulse per second?

i have worked thru the code with more comments.. under the assumption that 1pps is 1 pulse per second.

  if(incomingByte == 'x')
  {
    incomingByte = 0;

    for (uint32_t i=c; i>0; i--) // what is 'c' - old code it is 1.
      pulseIn(freq, HIGH); 
    delayMicroseconds(freqdelay);
    digitalWrite(CTB, HIGH);  // what does this write to CTB do?
    delay(5);
    digitalWrite(CTB, LOW);  // again... what?

    pulseIn(pps, HIGH, 2000000);
    fds = micros();  // end of last pulse
    pulseIn(freq, HIGH);
    fde = micros();  // end of next pulse
    freqdelay = 
          (3000 + // what is the magic number 3000?, 3ms means what
            adj)   // what is adj, apart from an integer?
         - 
          (fde - fds); // this is the time for a cycle, in mico seconds.
                          // at 10 pulse per second approx 100,000
                          // at 1 pulse per second approx 1,000,000
          // integer - 1,000,000 => approximately - 1,000,000

 // If freqdelay is still an integer, then the results should be low 16 bits of the value.
 // The low 16 bits may not have an easy meaning to understand, but the are not random (was my first thought); but the part of the freqdelay modulo 65,536.
 // how stable is the source of the pulses, maybe the variation (order of 2 milliSecs) is
 // what the hardware achieves?


    Serial.println(freqdelay);
  }

ps
your first code had a bug in saving the adj value
EEPROM.write(2,c); should have been in > 0 branch as well.

Earlier screwy comments --
pulseIn(pps, HIGH, 2000000);
2,000,000 is bigger than an integers maximum value.
2000000L would get you what you think is happening maybe?Sorry - no 2000000 is interpreted as a long value correctly - the compiler is smarter than I am.