Need to add flashing LED subroutine

I have a timer im working on where I want to add a subroutine to start a flashing LED when the time is up and when the timer is reset, to turn off the flashing LED.

Im not sure if this code is appropriate or not.

But not sure how to fully implement it if necessary.

For instance, when the timer is up, I would need to add a line in here to tell the LED to turn on.

case OST_RUNNING:
          if ( now > next_tick ) {
            timer_tick_seconds();
            timer_display_count();
            if (( minutes_remaining == 0) && (seconds_remaining == 0)) {
              // FIRE RELAY 1!!!
              digitalWrite(RELAY1_PIN, 1);
              setOperatingState(OST_EXPIRED1);
              timer_restart(1); // One minute EXPIRED count
            }
          }
          break;

And when the timer is up, I need to tell the led to stop flashing in this part of the code.

 /**
       Return the relays to their "OFF" settings.
    */
    void reset_relays() {
      digitalWrite(RELAY1_PIN, 0);
      digitalWrite(RELAY2_PIN, 0);

    }

Thanks for any help. Im no pro at coding, but just working an an existing project that I want to modify.
I got so far as getting the LED to flash in an endless loop once the time is up, but in turn got everything else locking up and just freezing where it wouldnt allow me to even use the reset button.

#define BlinkHalfPeriod 500
#define BlinkPin 5

void setup() {
  pinMode(BlinkPin, OUTPUT);
}

void loop() {
  static uint32_t TimerBliking = 0;
  static bool isBlinkEnable = false;

  if (isBlinkEnable) {
    if ( millis() - TimerBliking >= BlinkHalfPeriod) {
      TimerBliking += BlinkHalfPeriod;
      digitalWrite(BlinkPin, !digitalRead(BlinkPin));
    }
  }  else digitalWrite(BlinkPin, LOW);
}

Thanks,
that is half working for me, im having the same issue however when I added similar code earlier.
Im probably doing something wrong, but it just locks up unresponsive once the time expires.
The LED comes on and flashes once the time is up, but the reset button no longer works.

Ive inserted the code you quoted and used the following lines to activate it:

          if ( now > next_tick ) {
            timer_tick_seconds();
            timer_display_count();
            if (( minutes_remaining == 0) && (seconds_remaining == 0)) {
              // FIRE RELAY 1!!!
              digitalWrite(RELAY1_PIN, 1);
              isBlinkEnable = true;
              setOperatingState(OST_EXPIRED1);
              timer_restart(1); // One minute EXPIRED count
            }
          }
          break;
 /**
       Return the relays to their "OFF" settings.
    */
    void reset_relays() {
      digitalWrite(RELAY1_PIN, 0);
      digitalWrite(RELAY2_PIN, 0);
      static bool isBlinkEnable = false;

yep. you do something wrong.

Whats the correct way to call this routine up? If i just leave your code as inserted, the LED is blinking the whole time.

#define BlinkHalfPeriod 500UL
#define ChangeAfter 5000UL
#define BlinkPin 13

void setup() {
  pinMode(BlinkPin, OUTPUT);
}

void loop() {
  static uint32_t TimerPeriodes = 0;
  static uint32_t TimerBliking = 0;
  static bool isBlinkEnable = false;
  if ( millis() - TimerPeriodes >= ChangeAfter) {
    TimerPeriodes += ChangeAfter;
    isBlinkEnable = !isBlinkEnable;
  }
  if (isBlinkEnable) {
    if ( millis() - TimerBliking >= BlinkHalfPeriod) {
      TimerBliking += BlinkHalfPeriod;
      digitalWrite(BlinkPin, !digitalRead(BlinkPin));
    }
  }  else digitalWrite(BlinkPin, LOW);
}

When compiling that gives me the error "'isBlinkEnable' was not declared in this scope"
ive got the lines added isBlinkEnable = false when the timer resets and thats what gives me the error.
I can compile it successfully if i leave isBlinkEnable = true when the timer expires.

you are doing something massively wrong. isBlinkEnable is obviously defined

Its only doing it when I add that line further down in my code.
Ill PM you with the whole code so you can see what im trying to do.

  bool sw = ASSERTED swReset.query();
  if ( sw ) { // Reset held down
    if ( NOT swResetLast ) {
  if ( ! swReset.query() ) { // Reset held down
    if ( ! swResetLast ) {

is it OK for you

  bool keyLock = ! digitalRead(SECURITY_PIN);
  //bool kyKeyPress = digitalRead(KY_SET_PIN);
  if ( ! keyLock ) {
  if ( digitalRead(SECURITY_PIN) ) {

and here

yes thats fine

this is the compiler error i get though, which is unrelated.

    byte j;
    // detect if rotary encoder button pressed 0 = not pushed, 1 = pushed
    j = rotary.push();
    // ONLY allow set-mode if SECURITY SWITCH is ON
    if ( j == 1 ) { // act on button-release
    // detect if rotary encoder button pressed 0 = not pushed, 1 = pushed
    // ONLY allow set-mode if SECURITY SWITCH is ON
    if ( rotary.push() ) { // act on button-release

OK ?

not having any issues with that part of the code.

but this is issue

  char buf[3];
  buf[2] = 0;
  lcd.print(format_rj2( buf, encoderPosCount));

avoid using of uninitialized arrays

  char buf[3]={0};
  lcd.print(format_rj2( buf, encoderPosCount));

why this functions are all static ?

static void display_timer_set() {
  //lcd.clear();
  lcd.setCursor(0, 0); //Start at character 0 on line 1
  lcd.print("Timer set:");
  lcd.setCursor(2, 1); //Start at character 2 on line 1
  char buf[3];
  buf[2] = 0;
  //lcd.print(format_rj2( buf, encoderPosCount));
  lcd.print( " Minutes");
}

static void setOperatingState(OPERATING_STATE ost) {
  if ( ost != operating_state ) {
    lcd.clear();
  }
  operating_state = ost;
}

/**
   Restart the time count.
*/
static void timer_restart(int minutes) {
  unsigned long now = millis();
  time_started = now;
  //Serial.print("Timer Restart "); Serial.println(encoderPosCount);
  minutes_remaining = minutes; // MINUTES - todo - pull from EEPROM
  seconds_remaining = 0;
  next_tick = now + 1000; // msec = 1 second
}

/**
   Count down 1 second intervals
*/
static void timer_tick_seconds() {
  seconds_remaining--;
  if ( seconds_remaining < 0 ) {
    seconds_remaining = 59;
    minutes_remaining--;
  }
  next_tick = next_tick + 1000; // msec = 1 second
}

/**
   Display current time remaining.
*/
static void timer_display_count() {
  lcd.setCursor(0, 0); //Start at character 0 on line 0
  char buf[3];
  if ( minutes_remaining > 0 ) {
    lcd.print(format_rj2(buf, minutes_remaining));
    lcd.print(" Min. remain");
  } else {
    lcd.print(format_rj2(buf, seconds_remaining));
    lcd.print(" Sec. remain");
  }
  if ( operating_state == OST_EXPIRED1 ) {
    lcd.setCursor(0, 1); //Start at character 0 on line 0
    lcd.print("Expired");
  }
}

/**
   Right-justified format of a 2-digit number
*/
static char* format_rj2(char* buf, int n) {
  if ( n > 99 ) { // limit range.
    n = n % 100;
  }
  buf[1] = (n % 10) + '0';
  buf[0] = (n / 10) + '0';
  buf[2] = 0;
  if ( buf[0] == '0') {
    buf[0] = ' '; // leading space
  }
  return buf;
}

//**** EEPROM ****

const int ee_addr0 = 0;

static void timer_save(int count) {
  EEPROM.update(ee_addr0, (count >> 8) & 0xff);
  EEPROM.update(ee_addr0 + 1, (count) & 0xff);
}

static int timer_load() {
  int val = EEPROM.read(ee_addr0) << 8;
  val |= EEPROM.read(ee_addr0 + 1);
  return val;
}

and why you recreate arrays with 3 elements and use only 2, and every time you set buf[2] as 0 ?

I have no idea sorry, I didnt write this code.
I had a friend do it a while back, but was trying to add LED functions to it.

what is this timer? why it has SECURITY_PIN ?

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

#define OST_SET 1
#define OST_RUNNING 2
#define OST_EXPIRED1 3
#define OST_EXPIRED2 4
#define BlinkHalfPeriod 500UL
#define BlinkPin 13

const byte MAX_MINUTES = 60;
const byte RELAY1_PIN = 7;
const byte RELAY2_PIN = 8;

uint32_t TimerTick = 0;
uint16_t seconds_remaining = 0;
byte encoderPosCount = 1;
byte operating_state = OST_SET;

void setup() {
  pinMode(2, INPUT_PULLUP); //rotary encoder push button
  pinMode(3, INPUT_PULLUP); //rotary encoder A
  pinMode(4, INPUT_PULLUP); //rotary encoder B
  pinMode(RELAY1_PIN, OUTPUT);
  pinMode(RELAY2_PIN, OUTPUT);
  pinMode(BlinkPin, OUTPUT);
  lcd.init();
  lcd.backlight();
  lcd.print("Starting...");
  delay(500);
  lcd.clear();
}

void loop() {
  static uint32_t TimerBliking = 0;
  static bool isBlinkEnable = false;

  if (isBlinkEnable) {
    if ( millis() - TimerBliking >= BlinkHalfPeriod) {
      TimerBliking = millis();
      digitalWrite(BlinkPin, !digitalRead(BlinkPin));
    }
  }  else digitalWrite(BlinkPin, LOW);

  switch (operating_state) {
    case OST_SET:
      lcd.setCursor(1, 0);
      lcd.print("Timer setting");
      lcd.setCursor(5, 1);
      lcd.print("Minutes");
      handle_timer_set();
      break;
    case OST_RUNNING:
      if (millis() - TimerTick >= 1000) {
        timer_tick_seconds();
        if (seconds_remaining == 0) {
          digitalWrite(RELAY1_PIN, 1);// FIRE RELAY 1 !!
          isBlinkEnable = true;
          setOperatingState(OST_EXPIRED1);
          timer_start(1); // One minute EXPIRED count
        }
      }
      break;
    case OST_EXPIRED1:
      if (millis() - TimerTick >= 1000) {
        timer_tick_seconds();
        if (seconds_remaining == 0) {
          digitalWrite(RELAY2_PIN, 1);// FIRE RELAY 2 !!
          setOperatingState(OST_EXPIRED2);
          lcd.clear();
          lcd.setCursor(4, 0);
          lcd.print("EXPIRED");
        }
      }
      break;
    case OST_EXPIRED2:
      if (digitalRead(2) == LOW) {
        encoderPosCount = 1;
        isBlinkEnable = false;
        setOperatingState(OST_SET);
        delay(50);
        reset_relays();
        while (!digitalRead(2));
      }
      break;
  }
}

void reset_relays() {
  digitalWrite(RELAY1_PIN, 0);//Return the relays to their "OFF" settings.
  digitalWrite(RELAY2_PIN, 0);
}

void handle_timer_set() {//When we are in OST_SET state, we read the encoder and set the timer.
  static uint32_t Refresh = 0;
  static bool EncoderLastStat = false;
  while (digitalRead(2)) {
    bool EncA = digitalRead(3);
    bool EncB = digitalRead(4);
    if ( EncA && (!EncoderLastStat)) {
      if (EncB && encoderPosCount < MAX_MINUTES)encoderPosCount++;;
      if ((!EncB) && encoderPosCount > 1)encoderPosCount--;
    }
    EncoderLastStat = EncA;
    if (millis() - Refresh >= 500) {
      Refresh = millis();
      lcd.setCursor(2, 1);
      if (encoderPosCount < 10) lcd.print(' ');
      lcd.print(encoderPosCount);
    }
  }
  timer_start(encoderPosCount);
  setOperatingState(OST_RUNNING);
}

void setOperatingState(byte ost) {
  if (ost != operating_state)lcd.clear();
  operating_state = ost;
}

void timer_start(int Minutes) {//Start the time count.
  TimerTick = millis();
  seconds_remaining = Minutes * 60;
}

void timer_tick_seconds() {//Count down 1 second intervals
  if ( seconds_remaining > 0 ) {
    seconds_remaining--;
    TimerTick += 1000;
  }
  Show_Time();
}

void Show_Time() {//Display current time remaining.
  lcd.setCursor(0, 0);
  byte Min = seconds_remaining / 60;
  byte Sec = seconds_remaining % 60;
  if (Min < 10)lcd.print(' ');
  lcd.print(Min);
  lcd.print(':');
  if (Sec < 10)lcd.print('0');
  lcd.print(Sec);
}

The main thing is to post your complete sketch from the very first line to the very last line.

You can post code by using this method that adds the code-tags
There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

best regards Stefan

1 Like