Unexpected behavior with millis() function

dear everyone,

i have experience using millis() function for long time, and i used it instead of dealy.

but today i faced an unexpected problem

when i have this code

   startTimer = millis();
   Serial.println(millis()-startTimer);

  while((millis() - startTimer < 2000) && mode == 1)
{
some code here

}

i use print statement to see how much time is (millis() - startTimer)

with the first couple of uses it is always true (less than 2000)

but at some point, it becomes false because (millis() - startTimer) is always a specific number which is 65536

and only resetting the Arduino let it become normal again

why is that ? any hint will be appreciated

(**** today i noticed that my home floor has 30v AC difference than the ground wire which is missed up alot of my analog reading )

could this be a reason?

startTimer must be defined as unsigned long.

1 Like

let me try it

It is not clear what you actually mean by this, but "ground loops" can lead to very serious problems with line-powered computers connected together.

Make sure all your devices are powered by the same branch of the AC circuit, or use a battery powered laptop with the Arduino, and don't connect it to the AC line at all.

As stated int the forum guidelines, always show us a complete sketch that shows the problem you are experiencing.

the code i mentioned has all you need to figure the problem
i can post all the code but its complex

i tried change the variable from int to unsigned long but no luck same problem

i measured the voltage difference between the floor and the ground wire and i found 30V AC difference this is shocking actually and i will try to figure it out

i only said that to see if it contribute to the problem

Please follow the forum guidelines when asking questions to volunteers.

No it doesn't. Post ALL the code.

sorry , i appreicate tour help
i really tried to be as simple as i can

this is my complete code
my problem is in the while loops it doest enter it after some time from starting the program

i followed the problem and i found that difference (mills() - startTimer) is equal 65536 and not few milliseconds as expected

int minute = 1000*60;

#define P1 2
#define P2 3
#define P3 4

#define S1 5
#define S2 6
#define S3 7
#define S4 8
#define S5 9
#define S6 10

#define M1 11
#define M2 12

#define btn1 A4
#define btn2 A0
#define btn3 A1

unsigned long startTimer ;
unsigned long startTimer2;
int mode = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
pinMode(P1 , OUTPUT);
pinMode(P2 , OUTPUT);
pinMode(P3 , OUTPUT);

pinMode(S1 , OUTPUT);
pinMode(S2 , OUTPUT);
pinMode(S3 , OUTPUT);
pinMode(S4 , OUTPUT);
pinMode(S5 , OUTPUT);
pinMode(S6 , OUTPUT);

pinMode(M1 , OUTPUT);
pinMode(M2 , OUTPUT);

pinMode(btn1 , INPUT);
pinMode(btn2 , INPUT);
pinMode(btn3 , INPUT);


}

void loop() {
  // put your main code here, to run repeatedly:
  startingPoint:
resetMode();

while(mode == 0){
mode = check(0);
Serial.println("Waiting for button");
}

if(mode == 1)
{
  Serial.println("Starting button 1 sequence");

   startTimer = millis();
   Serial.println(millis()-startTimer);

  while((millis() - startTimer < 2000*2) && mode == 1)
  {
    Serial.println(mode);
      Serial.println("Inside the while loop");

    digitalWrite(P1, HIGH);
    digitalWrite(S1, HIGH);
    mode = check(mode);
    if(mode ==0)
    goto startingPoint;
    }
    digitalWrite(P1, LOW);
    digitalWrite(S1, LOW);    
 //***********************************************
    startTimer = millis();
    startTimer2 = millis();
   while((millis() - startTimer < 3000*2) && mode ==1){

     if(millis() - startTimer2 < 2000*2)
     {
      digitalWrite(P1, HIGH);
      digitalWrite(S3, HIGH);
      }
    else{
      digitalWrite(P1, LOW);
      digitalWrite(S3, LOW);      
      
      }  
    digitalWrite(P2, HIGH);
    digitalWrite(S2, HIGH);     
    mode = check(mode); 
        if(mode ==0)
    goto startingPoint;
    } 
    digitalWrite(P2, LOW);
    digitalWrite(S2, LOW); 
//***************************************
    startTimer = millis();
    startTimer2 = millis();
 
   while((millis() - startTimer < 4000*2 )&& mode ==1){

     if(millis() - startTimer2 < 3000*2)
     {
      digitalWrite(P2, HIGH);
      digitalWrite(S4, HIGH);
      }
    else{
      digitalWrite(P2, LOW);
      digitalWrite(S4, LOW);      
      
      }  
    digitalWrite(M1, HIGH);
    mode = check(mode); 
        if(mode ==0)
    goto startingPoint;
    }
    digitalWrite(M1, LOW);

    startTimer = millis();
    while((millis() - startTimer < 4000*2) && mode == 1)
    {
      digitalWrite(M2, HIGH);
      mode = check(mode);
          if(mode ==0)
    goto startingPoint;
      } 
   digitalWrite(M2, LOW);

//**************************
    startTimer = millis();
    while((millis() - startTimer < 4000*2) && mode == 1)
    {
      digitalWrite(M2, HIGH);
      mode = check(mode);
          if(mode ==0)
    goto startingPoint;
      } 
   digitalWrite(M2, LOW);
//**********************************

startTimer = millis();
while((millis() - startTimer < 1000*2) && mode==1)
{
  
      digitalWrite(P3, HIGH);
      digitalWrite(S5, HIGH);
  mode = check(mode);
      if(mode ==0)
    goto startingPoint;
  }

      digitalWrite(P3, LOW);
      digitalWrite(S5, LOW);
//**************************************

startTimer = millis();

while((millis() - startTimer < 1000*2) && mode ==1)
{
  
      digitalWrite(P3, HIGH);
      digitalWrite(S6, HIGH);  
      mode = check(mode);
          if(mode ==0)
    goto startingPoint;
  }

      digitalWrite(P3, LOW);
      digitalWrite(S6, LOW);

  //*****************************

  resetMode();
  }

if(mode == 2)
{
  startTimer = millis();
  while((millis() - startTimer < 1000*2)&& mode ==2)
{
      digitalWrite(P3, HIGH);
      digitalWrite(S5, HIGH);  
      mode = check(mode); 
          if(mode ==0)
    goto startingPoint;
  
 }
      digitalWrite(P3, LOW);
      digitalWrite(S5, LOW);  
  
  startTimer = millis();

  while((millis() - startTimer < 1000*2) && mode ==2)
  {
      digitalWrite(P3, HIGH);
      digitalWrite(S6, HIGH);  
      mode = check(mode);  
          if(mode ==0)
    goto startingPoint;   
    
    }
      digitalWrite(P3, LOW);
      digitalWrite(S6, LOW);   
  
 resetMode();
   
  }






}

int check(int current){
  int btn1state = LOW;
  int btn2state = LOW;
  int btn3state = LOW;

   btn1state = analogRead(btn1);
   btn2state = analogRead(btn2);
   btn3state = analogRead(btn3);


  if (btn1state > 1000)
    mode = 1;
  else if(btn2state  > 1000 )
  mode = 2;
  else if(btn3state  > 1000)
  mode = 3;
  else
  mode = current;
  return mode ;
  }

void resetMode(){
  mode = 0;
   digitalWrite(S1, LOW); 
   digitalWrite(S2, LOW);
   digitalWrite(S3, LOW);
   digitalWrite(S4, LOW);
   digitalWrite(S5, LOW);
    digitalWrite(S6, LOW);
    digitalWrite(P1, LOW);
    digitalWrite(P2, LOW);
    digitalWrite(P3, LOW);
    digitalWrite(M1, LOW);
    digitalWrite(M2, LOW);
  }  ```

This won't work on an AVR based Arduino like the Uno, because the largest possible int is 32767.

Which Arduino do you have?

nano

but this variable is not used now and i didnt use it across the program

Get rid of that line, then.

deleted

its kind of working right now.
i will try to give it some run time and see if will break or not

but i can't work while i have 1.5 dc voltage difference in my hand that can miss with my analog reads if i touch the wire :expressionless: :upside_down_face:

You should avoid using GOTO statements... Computer Programming 101.

Suggest you study how to write sketches like this using the state machine technique.

As mentioned, do not use goto.

Avoid using while( ) loops for long events.

Because you changed startTimer to unsigned long.

Code 1 (int)

int startTimer = 0;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  startTimer = millis();

  Serial.print("millis = ");
  Serial.print(millis());
  Serial.print(" Diff = ");
  Serial.println(millis() - startTimer);

  delay(1000);
}

Output 1

12:25:29.800 -> millis = 30013 Diff = 0
12:25:30.784 -> millis = 31013 Diff = 0
12:25:31.799 -> millis = 32014 Diff = 0
12:25:32.785 -> millis = 33014 Diff = 65536
12:25:33.802 -> millis = 34015 Diff = 65536
12:25:34.810 -> millis = 35015 Diff = 65537
12:25:35.822 -> millis = 36017 Diff = 65537
12:25:36.837 -> millis = 37017 Diff = 65536

Code 2 (unsigned long)

unsigned long startTimer = 0;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  startTimer = millis();

  Serial.print("millis = ");
  Serial.print(millis());
  Serial.print(" Diff = ");
  Serial.println(millis() - startTimer);

  delay(1000);
}

Output 2

12:27:57.061 -> millis = 28012 Diff = 0
12:27:58.042 -> millis = 29012 Diff = 0
12:27:59.054 -> millis = 30013 Diff = 0
12:28:00.075 -> millis = 31013 Diff = 0
12:28:01.060 -> millis = 32014 Diff = 0
12:28:02.093 -> millis = 33014 Diff = 0
12:28:03.068 -> millis = 34015 Diff = 0
12:28:04.098 -> millis = 35015 Diff = 0
12:28:05.096 -> millis = 36016 Diff = 0
12:28:06.109 -> millis = 37016 Diff = 0
12:28:07.122 -> millis = 38017 Diff = 0
12:28:08.113 -> millis = 39017 Diff = 0
12:28:09.114 -> millis = 40017 Diff = 0
12:28:10.123 -> millis = 41018 Diff = 0

Nobody got it.

The millis timer has +/- 1 ms accuracy.
When you subtract 2 millis values the answer may be off by 1 and your example looks for 0.

Try using the micros() timer. When it counts, use micros()!

What a load of rubbish. You have no idea what you are talking about. The OP's issue was that they were using a 16 bit signed integer and comparing to a 32 bit unsigned value. Look at the example above and you can see exactly what the result is.