How do I stop the serial monitor from accepting noise?

Hello. Please help me fix my code. I made a countdown timer program that accepts input from the serial monitor. Basically, the user opens the serial monitor and inputs the values to it. The timer takes hours, minutes and seconds as arguments. The program converts the input to seconds which the Arduino UNO uses to count down to zero. A relay switches to a closed state while the timer is active, allowing current to pass through whatever is connected to the relay (I connected an LED to check if the relay is active).

I’ve been testing the program and so far it works. My only problem is that whenever I open the serial monitor, the UNO flickers before going stable. This shouldn’t be a problem but in effect, the relay connected to it (and by extension the LED) flickers as well. This could pose a problem especially when I start connecting the relay to other, more complicated devices. This is the problem I’m trying to eliminate.

I suspect this has something to do with noise entering the serial monitor (correct me if I’m wrong on this one). I don’t have any code that blocks noise from entering the serial monitor nor the input while the timer is active.

I’ll start with the setup function.

void setup() {
  pinMode(RELAY, OUTPUT);
  Serial.begin(9600);
  while(!Serial) {;};
  lcd.begin(16, 2);
  lcd.clear();
}

Setup initializes the relay, serial monitor and lcd. The while statement above is supposed to block noise from entering the serial monitor whenever I open it. Here’s the other function for when I take in input from the serial monitor. This, and the code snippet above it, are the only functions that’ll make use of the serial monitor. It doesn’t have a way to block noise as well.

void inputPrompt() {
  lcd.clear();
  lcd.home();
  lcd.print("Set Time(H:M:S):");
  
  Serial.print("\nHRS = ");
  while(Serial.available() == 0) {}
  cd.hrs = Serial.parseInt();
  
  Serial.print("\nMIN = ");
  while(Serial.available() == 0) {}
  cd.mins = Serial.parseInt();
  
  Serial.print("\nSEC = ");
  while(Serial.available() == 0) {}
  cd.secs = Serial.parseInt();
}

I have a hunch this is is purely the code’s problem although I could be wrong. I’m posting the full code below just in case anyone’s interested.

#include <LiquidCrystal_I2C.h>

#define RELAY 13    // Changed pin assignments to define statements

const short HRS = 6;
const short MINS = 59;
const short SECS = 59;

struct set_countdown {
  unsigned int raw;
  int hrs;
  int mins;
  int secs;
};
struct set_countdown cd;

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  pinMode(RELAY, OUTPUT);
  Serial.begin(9600);
  while(!Serial) {;};
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {
  digitalWrite(RELAY, HIGH);
  inputPrompt();
  
  if ((cd.hrs < HRS) && (cd.mins <= MINS) && (cd.secs <= SECS)) {
    char char_buffer[6] = "";
    sprintf(char_buffer, "%02d:%02d:%02d", cd.hrs, cd.mins, cd.secs);
    Serial.print("\nTime has been set to ");
    Serial.println(char_buffer);  
    cd.raw = (cd.hrs * 3600) + (cd.mins * 60) + cd.secs;
    executeCountDown();
  } else {
    Serial.println("\nTime set denied. Set value out of bounds!");
  }
}

void inputPrompt() {
  lcd.clear();
  lcd.home();
  lcd.print("Set Time(H:M:S):");
  
  Serial.print("\nHRS = ");
  while(Serial.available() == 0) {}
  cd.hrs = Serial.parseInt();
  
  Serial.print("\nMIN = ");
  while(Serial.available() == 0) {}
  cd.mins = Serial.parseInt();
  
  Serial.print("\nSEC = ");
  while(Serial.available() == 0) {}
  cd.secs = Serial.parseInt();
}

void executeCountDown() {
  unsigned long previous_millis = 0;
  const int interval_sec = 1000;
  char lcd_buffer[8] = "";

  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Time Remaining");
  
  while(cd.raw > 0) { 
    digitalWrite(RELAY, LOW);
    lcd.setCursor(4, 1);
    sprintf(lcd_buffer, "%02d:%02d:%02d", cd.hrs, cd.mins, cd.secs);
    unsigned long current_millis = millis();
    if ((current_millis - previous_millis) >= interval_sec) {
      if ((cd.secs > 0) && (cd.mins >= 0) && (cd.hrs >= 0)) {
        // Seconds countdown to zero
        cd.secs--;
        cd.raw--;
        lcd.setCursor(4, 1);
        lcd.print(lcd_buffer);
        previous_millis = current_millis;
      } else if ((cd.secs == 0) && (cd.mins > 0) && (cd.hrs >= 0)) {
        // Seconds reach zero, decrement minute
        cd.mins--;
        cd.secs = 59;
        cd.raw--;
        lcd.setCursor(4, 1);
        lcd.print(lcd_buffer);
        previous_millis = current_millis;
      } else if ((cd.secs == 0) && (cd.mins == 0) && (cd.hrs > 0)) {
        // Minutes reach zero, seconds reach zero, decrement hour
        cd.hrs--;
        cd.mins = 59;
        cd.secs = 59;
        cd.raw--;
        lcd.setCursor(4, 1);
        lcd.print(lcd_buffer);
        previous_millis = current_millis;
      }
    } 
  }
  Serial.println("Set time has reached zero...");
}

Much help would be appreciated. Thank you and good day.

Hi,
When you open the serial monitor on the UNO, the UNO is reset.
This is not a fault, but a fact.

So each time you open your monitor the count will reset to zero.

Tom.. :slight_smile:

As already mentioned, every time you open the monitor the Arduino resets, and as soon as setup() runs your pinMode the pin goes low, which is the wrong way for your relay before you take control of it. (Many if not most relay modules are active low.)

You can do a digitalWrite() to the relay pin before you pinMode() it, so that it starts off the right way for you.

So probably that HIGH at the top of loop() can go before the pinMode in setup().

PS to previous...

I just verified what I said with my relay module.

With this in setup() on Uno power up, or reset with the reset button, or reset by opening the monitor, the relay starts energised (relay clicks and its led is on, multi meter confirms contacts are closed) then goes off after the delay:

pinMode(2, OUTPUT);
delay(1000);
digitalWrite(2, HIGH);

With this in setup, it starts de-energised (no click, no led):

digitalWrite(2, HIGH);
pinMode(2, OUTPUT);