Add countdown in Blink without delay sketch

HI,

I am trying to built cyclic ON / OFF timer which display the countdown time also. I modified the “Blink without delay” sketch and its working fine ON / OFF. But in countdown section it strat printing from “65535” due to " uint16_t seconds = 0; // max == 65535 " until first status change as in below serial output.

Thanks,

#include <LiquidCrystal_I2C.h>               //addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int relayPin =  2;
unsigned int relayState = LOW;
long offTime = 6000;
long onTime = 4000;
unsigned long previousMillis = 0;

uint16_t seconds = 0;      // max == 65535
uint32_t lastTime;

void setup() {
  Serial.begin (9600);
  lcd.begin(16, 2);
  pinMode(relayPin, OUTPUT);
}

void loop() {
  long currentMillis = millis();
  if ((relayState == HIGH) && (currentMillis - previousMillis >= offTime))
  {
    relayState = LOW;// turn it on
    seconds = onTime / 1000 ;
    previousMillis = currentMillis;   // Remember the time
    digitalWrite(relayPin, LOW);    // Update the actual relay
    lcd.setCursor(1, 2);
    lcd.print("Relay LOW ");
  }
  else if ((relayState == LOW) && (currentMillis - previousMillis >= onTime))
  {
    relayState = HIGH; // Turn it off
    seconds = offTime / 1000 ;
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(relayPin, HIGH);  // Update the actual relay
  }

///////////------Count down------////////////////////////


  if ((relayState == HIGH) && (currentMillis - previousMillis < offTime)) {
    if (currentMillis - lastTime >= 1000)
    {
      seconds--;
      lastTime += 1000;
      Serial.print("HIGH");
      Serial.print("\t");
      Serial.println(seconds);
    }
  }

  if ((relayState == LOW) && (currentMillis - previousMillis < onTime)) {
    if (currentMillis - lastTime >= 1000)
    {
      seconds--;
      lastTime += 1000;
      Serial.print("LOW");
      Serial.print("\t");
      Serial.println(seconds);
    }
  }
}

Serial output:

LOW	65535
LOW	65534
LOW	65533
HIGH	5
HIGH	4
HIGH	3
HIGH	2
HIGH	1
HIGH	0
LOW	3
LOW	2
LOW	1
LOW	0
HIGH	5
HIGH	4

Dunno what you expect to print out, but your time comparison is wrong. Regardless of the relay state you always should compare

  (currentMillis - previousMillis < interval)

never >= interval, that does not make sense and computes wrong.

I'd initialize previousMillis in setup(), as previousMillis=millis();

BlinkWithoutDelay contains some fundamental errors that won’t show up in that sketch until it runs almost 25 days straight.

Short story: always use unsigned integers when dealing with time on Arduino. If you’re new to programming just always use type unsigned long variables for time. If you’re not then you may know what you can get away with.

Mixed type variables math also takes knowing what you’re doing, it is best not to just to keep from getting unintended results.

#include <LiquidCrystal_I2C.h>               //addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const byte relayPin =  2;   // never use a 16-bit int where an 8-bit byte will do, make it a habit and save yourself time.
unsigned byte relayState = LOW;

unsigned long offTime = 6000;
unsigned long onTime = 4000;
unsigned long previousMillis = 0;

unsigned long seconds = 0;      
unsigned long lastTime;

void setup() {
  Serial.begin (9600);
  lcd.begin(16, 2);
  pinMode(relayPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  if ((relayState == HIGH) && (currentMillis - previousMillis >= offTime))
  {
    relayState = LOW;// turn it on
    seconds = onTime / 1000UL;

//    previousMillis = currentMillis;   // Remember the time
    previousMillis += offTime;   //  set previous to what the time is supposed to be, avoids creeping intervals

    digitalWrite(relayPin, LOW);    // Update the actual relay
    lcd.setCursor(1, 2);
    lcd.print("Relay LOW ");
  }
  else if ((relayState == LOW) && (currentMillis - previousMillis >= onTime))
  {
    relayState = HIGH; // Turn it off
    seconds = offTime / 1000 ;
    previousMillis += onTime;  // the time when the interval ended even if the code gets there late
    digitalWrite(relayPin, HIGH);  // Update the actual relay
  }

///////////------Count down------////////////////////////


  if ((relayState == HIGH) && (currentMillis - previousMillis < offTime)) {
    if (currentMillis - lastTime >= 1000UL)
    {
      seconds--;
      lastTime += 1000;
      Serial.print("HIGH");
      Serial.print("\t");
      Serial.println(seconds);
    }
  }

  if ((relayState == LOW) && (currentMillis - previousMillis < onTime)) {
    if (currentMillis - lastTime >= 1000UL)
    {
      seconds--;
      lastTime += 1000UL;
      Serial.print("LOW");
      Serial.print("\t");
      Serial.println(seconds);
    }
  }
}