Pages: [1]   Go Down
Author Topic: Overflow, micros() ???  (Read 1425 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
    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...

Code:
#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);
    }
     

  }

}


Logged

No trees were harmed by the transmission of this message. However a few million electrons were temporarily inconvenienced.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 533
Posts: 26934
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

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

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

No trees were harmed by the transmission of this message. However a few million electrons were temporarily inconvenienced.

Austin, TX
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6146
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    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....
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 610
Posts: 49006
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

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?
Logged

No trees were harmed by the transmission of this message. However a few million electrons were temporarily inconvenienced.

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 205
Posts: 12844
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Quote
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.

Quote
How about resetting micros?
Unnecessary.
Logged

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

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.
Logged

No trees were harmed by the transmission of this message. However a few million electrons were temporarily inconvenienced.

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

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.

Code:
880
1444
2004
2572
1140
1700
2264
832
1396

This is the code that executes the time read and printout

Code:
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.

Logged

No trees were harmed by the transmission of this message. However a few million electrons were temporarily inconvenienced.

UK
Offline Offline
Full Member
***
Karma: 2
Posts: 110
Kittens eat Arduinos
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
 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.
« Last Edit: January 29, 2011, 09:40:44 am by dafid » Logged

Pages: [1]   Go Up
Jump to: