Need help understanding why code works only a certain way

#define GREEN 7  // Pin 7 is assigned variable GREEN. Global variable.

unsigned long mintime = 2000;  // Global variable
unsigned long maxtime = 5000;  // Global variable

unsigned long previoustime = 0;  // used to reset timer. Global variable.

void setup() {
  pinMode(GREEN, OUTPUT);  // Writes code to pin 7
  // Serial.begin(9600); // Start up serial monitor, baud rate 9600
}

void loop() {

  unsigned long time = millis();  // starts timer named time. local variable

  if (time - previoustime >= mintime && time - previoustime <= maxtime) {  // if time - previoustime is greater than 1999 and time - previoustime is less than 5001
    digitalWrite(GREEN, HIGH);                                             // GREEN turns on
  } else {
    digitalWrite(GREEN, LOW);  // If not within min/max time, turn LED off
  }
  if (time - previoustime == maxtime) {  // if time - previoustime equals maxtime
    previoustime = time;                 // previoustime becomes time
  }
  // time(2000) - previoustime(0) = mintime(2000) :: time(5000) - previoustime(0) = maxtime(5000) // time(7000) - previoustime(5000) = mintime(2000) :: time(10000) - previoustime(5000) = maxtime(5000) // time(12000) - previoustime(10000) = mintime(2000) :: time(15000) - previoustime(10000) = maxtime(5000)

  delay(100);  // delay by .1 second for next loop
  // delay(1);  // If I set delay for 1 millisecond, it works fine.
}

I made code to turn on a GREEN led on if the time was between 2 to 5 seconds, and then right after the 5 second mark, it would reset the timer. When I use delay(100) the GREEN led did work, but only for 3 times. after that it wouldn't turn on. If I used delay(1) though, it worked for at least 2 minutes. Would the delay(1) have stopped eventually, if not, I would like to know why delay(100) ended the code after only 3 times.

  if (time - previoustime == maxtime) {  // if time - previoustime equals maxtime
    previoustime = time;                 // previoustime becomes time
  }

Be careful looking for exactly == maxtime, that will require that the condition be evaluated within a specific millisecond, no more and no less. Very difficult to hit it exactly if you have a delay.

The OP may not be entirely familiar that to mix delay() and millis() in the same code can cause issue.

The OP might want to fix that with a if (time - previoustime >= maxtime.

if(time - previoustime == maxtime)
{
previoustime = time;
}

This line of code for delay(2500) would only run and update twice in the alloted timeframe(5000), while for delay(100) it would run and update 50 times. Delay(2500) gave me only one blink, while delay(100) gave me 3. So this would seem to indicate that the code in the loop takes no time except for the delay(whatever time), because I would expect the delay(100) to be only 1 blink while 2500 would be 3 blinks.

If you do delay(3000) or anything that doesn't fit into 2500 and 5000 nicely, then I do get since that would mean the code would run every 3 seconds. Which would mean the first loop would start off at 0, second loop would start at 3, and third loop would start at 6 seconds. Since my maxtime is 5000, even though Milli() did hit that time, the loop is only for every 3 seconds so that would be way off.

Thank you. I was not aware that doing those together would cause issues. I got rid of delay() and that worked. I also tried keeping dealy and just using >= maxtime which also worked. So I can't use delay() at the end of the loop. However, I can still use delay in a more localised fashion? Say I make a couple of if nested statements and at the end of the last if statement I say delay(). That wouldn't mess with any millis outside of that localised function, right?

I do not use delay() in my code. Using delay mixed with millis() might result in things working well or it might not. You'll have to give it a try and see.

Not sure you understood the point I was trying to make. Checking for the time interval being exactly equal to maxtime, as opposed to >=, will eventually fail. Because of the way millis() is implemented, it will occasionally skip a millisecond, with the millis count incrementing by two instead of one. There is a 1/5000 chance this will happen when the comparison with maxtime occurs. Made worse with the delay(100), since there is a 1/100 change the last millisecond of the delay period will be when the skip occurs.

Hello frost_10

I´m trying to understand the task of the sketch.

Should the sketch flash an LED with different times for the ON and OFF states?

If so, take a look at the BLINKWITHOUTFELAY example in the IDE and do some modification to the timer.

As you are yet not so experienced you should not mix-up delay() and millis().

Understanding non-blocking timing and how to avoid each and every delay() requires more than just looking at the classical blink without delay-demo-code.

After having understood the real nature of non-blocking coding you wil RE-recognise the principle inside the blink-without-delay-example. In short "BWD"

But IMHO only looking at the BWD-example makes it hard to understand the fundamental difference between delay-ing and non-blocking-coding.

It is not just a matter of 20 minutes playing around with the BWD-example.
Depending on your talent and how long you want to learn on it per day
it is realistic to estimate learning the basics of non-blocking coding will take some hours or maybe some days.

Me myself I haven't found a textbased online tutorial that would explain it all in a way that
with judging with my personal criteria I would say "very well explained"

Some parts are epxlained in two tutorials I have written.

This is about non-blocking timing

This is about state-machines (written by me though not in the quality that I myself would say all details explained in sufficient deepness)

I have some ideas how to give the overview about non-blocking-coding = multitasking without an RTOS but not yet written.

best regards Stefan

Ok. I took out the delay from the code and used serial.println() to see what numbers I got. I saw that a lot of numbers were skipped. For me, it seemed to be usually skipping every 3 numbers. I had 13 zeroes and then 9 ones, then it started counting 4, 7, 10, 14, 18, 22, 26, 30(for as far as I could tell, it counted mostly by 4s after this point, except there were numbers that were maybe 5 numbers away rather than 4). Is this what you were talking about?

The task of the sketch is to turn on the GREEN led for 3 seconds. Those 3 seconds were in between 2-5 seconds, then right after the timer hits 5 seconds, previoustime should reset so it would loop and be able to turn on again for 3 seconds. I forgot about the inbuilt guides, that would have helped me with the const ints and ints and #define, lol. Probably should take a look at them before I play around with Arduino again.

Thank you. I am still pretty new and do have a lot of things to learn.

Not exactly what I was talking about. What you are seeing is the delay caused by the Serial transmit buffer being full. Once the buffer is full, Serial.print becomes a blocking function, waiting for characters to be sent so there will be space in the buffer. Assuming you are using 9600 baud for Serial, each character takes a little over 1mS to send, so there will be a delay of approximately 4mS when printing a 2-digit number (two characters for the number, with another two characters for newline and carriage return).

Hello
Post a timing diagram to show your design goal.

I second that.
You tried in multiple attempts to describe it in words. But your worded description was vague
Your worded descriptions leaves out details that are important.

A timing diagram a picture showing the timely relation between when is switched what.

I did no planning before playing with the Arduino. This was the simpliest example of a time diagram I saw online and should work for this sketch.

Well done posting the timing-diagram

OK LED 2 seconds off 3 seconds on 2 seconds off 3 seconds on ......

void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );  
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

const unsigned long offTime = 2000ul;
const unsigned long ON_Time = 3000ul;

unsigned long waitingTime;

unsigned long MyLEDTimer   = 0;     // Timer-variables MUST be of type unsigned long
const byte    greenLED_Pin = 7;


void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  digitalWrite(greenLED_Pin,LOW);
  pinMode(greenLED_Pin,OUTPUT);
  PrintFileNameDateTime();
  waitingTime = offTime;
  MyLEDTimer = millis();
}


void loop() {

  // check if the amount of milliseconds that are stored in 
  // variable "waitingTime" have passed by
  if ( TimePeriodIsOver(MyLEDTimer,waitingTime) ) {
    //if the amount of milliseconds stored in waitingTime
    // are REALLY over execute code inside if-condition
    Serial.print("now ");
    Serial.print(waitingTime);
    Serial.println(" millisconds are over");
    
    if ( digitalRead(greenLED_Pin) == LOW) { // if LED is off 
      Serial.println("LED is off");
      digitalWrite(greenLED_Pin,HIGH);       // switch LED on
      Serial.println("LED switched ON");
      waitingTime = ON_Time;                 // new time to wait is the ON-time
      Serial.println();
      Serial.println();
    }
    else { // else means LED is ON 
      Serial.println("LED is ON");
      digitalWrite(greenLED_Pin,LOW);        // switch LED off
      Serial.println("LED switched off");
      waitingTime = offTime;                 // new time to wait is the offtime
      Serial.println();
      Serial.println();
    }    
  }  
}

best regards Stefan

Hello frost_10
see post #8.

I see this as an attempt for trying to keep alive the "keep_infos_short_culture"

by using short infos. My expectation: it will fail because newcomers need so much time to understand the short infos.

In this case, Mr. frost_10 should be old enough to ask questions if necessary.