Hi every one since I am new to learn arduino but trying my best, can i write this alarm in finite state machine. Is any one idea,

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <DS3231.h>
#include <Wire.h>
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
DS3231 rtc(SDA, SCL);
Time t;
int hh = 0, mm = 0, ss = 0;
int Date = 1, Month = 1, Year = 2022;
const int setting = A0;
const int enter = A1;
const int inc = A2;
const int dec = A3;
const int ext = 10;
const int BUZZER = 11;
bool back = 0;
const char* set_month_str[] = {"Null", "January", "February", "March", "April",  "May", "June", "July", "August", "September", "October",  "November", "December"};
const char* set_day_str[] = {"Null", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY",  "FRIDAY", "SATURDAY", "SUNDAY"};//

void setup ()
{
  pinMode(setting, INPUT_PULLUP);
  pinMode(enter, INPUT_PULLUP);
  pinMode(inc, INPUT_PULLUP);
  pinMode(dec, INPUT_PULLUP);
  pinMode(ext, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, LOW);
  Wire.begin();
  rtc.begin();
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(" MAGIC ALARM");
  lcd.setCursor(0, 1);
  lcd.print("HAVE A NICE DAY");
  lcd.backlight();
  delay(3000);
  lcd.clear();
}
void loop ()
{

  t = rtc.getTime();
  int Hrs = t.hour;
  int Min = t.min;
  int Sec = t.sec;
 

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(rtc.getTimeStr());
  lcd.setCursor(9, 0);
  lcd.print(rtc.getDOWStr(FORMAT_SHORT));
  lcd.setCursor(0, 1);
  lcd.print(rtc.getDateStr());

  if (Hrs == 23 && Min == 37 && Sec == 20)   // RUNS EVERY DAY AT SPECIFIC TIME
  {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("ALARM ON");
    digitalWrite(BUZZER, HIGH);
    delay(500);
    digitalWrite(BUZZER, LOW);
    delay(500);
  }
  if (t.dow == 1 && Hrs == 15 && Min == 53 && Sec == 0) //RUNS ON EVERY WEEKDAYS
  {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("ALARM ON");
    digitalWrite(BUZZER, HIGH);
    delay(500);
    digitalWrite(BUZZER, LOW);
    delay(500);
  }
  if (t.date == 1, Month, Year && Hrs == 23 && Min == 59 && Sec == 00)     // RUNS EVERY 1ST DAY OF EVERY MONTH AND YEAR
  {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("ALARM ON");
    digitalWrite(BUZZER, HIGH);
    delay(500);
    digitalWrite(BUZZER, LOW);
    delay(500);
  }

  if (digitalRead(setting) == LOW)
  {
    delay(250);
    while (true)
    {
      lcd.setCursor(0, 0);
      lcd.print("  TIME SETTING  ");

      if (digitalRead(enter) == LOW)
      {
        delay(250);
        time_setting();
        break;
      }
      if (digitalRead(setting) == LOW)
      {
        break;
      }
    }
  }
  if (digitalRead(setting) == LOW)
  {
    delay(250);
    lcd.clear();
    while (true)
    {
      lcd.setCursor(0, 0);
      lcd.print("  DATE SETTING  ");

      if (digitalRead(enter) == LOW)
      {
        delay(250);
        date_setting();
        break;
      }
      if (digitalRead(setting) == LOW)
      {
        delay(250);
        lcd.clear();
        break;
      }
    }
  }
}
}
void time_setting()
{
  delay(250);
  hh = t.hour;
  mm = t.min;
A:
  lcd.clear();
  back = 0;
  while (true)
  {
    lcd.setCursor(0, 0);
    lcd.print("SET HOURS [HH]: ");
    lcd.setCursor(0, 1);
    if (hh < 10) lcd.print("0");
    lcd.print(hh);
    if (digitalRead(inc) == LOW)
    {
      hh = hh + 1;
      if (hh >= 24) hh = 0;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      hh = hh - 1;
      if (hh < 0) hh = 0;
      delay(200);
    }
    if (digitalRead(enter) == LOW)
    {
      delay(200);
      break;
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      return;
    }
    delay(50);
  }
  back = 0;
  while (true)
  {
    lcd.setCursor(0, 0);
    lcd.print("SET MINUTE [MM]: ");
    lcd.setCursor(0, 1);
    if (mm < 10) lcd.print("0");
    lcd.print(mm);
    if (digitalRead(inc) == LOW)
    {
      mm = mm + 1;
      if (mm >= 60) mm = 0;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      mm = mm - 1;
      if (mm < 0) mm = 0;
      delay(200);
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      back = 1;
      break;
    }
    if (digitalRead(enter) == LOW)
    {
      rtc.setTime(hh, mm, 0);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("   TIME SAVED   ");

      delay(1500);
      lcd.clear();
      break;
    }
    delay(50);
  }
  if (back == 1) goto A;
}

void date_setting()
{
  delay(250);
A:
  back = 0;
  lcd.clear();
  int y = t.dow;
  Date = t.date;
  while (true)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SET DAY: ");
    lcd.setCursor(0, 1);
    lcd.print(set_day_str[y]);
    if (digitalRead(inc) == LOW)
    {
      y = y + 1;
      if (y > 7) y = 1;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      y = y - 1;
      if (y < 1) y = 7;
      delay(200);
    }
    if (digitalRead(enter) == LOW)
    {
      delay(200);
      break;
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      return;
    }
    delay(50);
  }
B:
  back = 0;
  lcd.clear();
  while (true)
  {
    lcd.setCursor(0, 0);
    lcd.print("SET DATE [DD]: ");
    lcd.setCursor(0, 1);
    if (Date < 10) lcd.print("0");
    lcd.print(Date);
    if (digitalRead(inc) == LOW)
    {
      Date = Date + 1;
      if (Date > 31) Date = 1;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      Date = Date - 1;
      if (Date < 1) Date = 1;
      delay(200);
    }
    if (digitalRead(enter) == LOW)
    {
      delay(200);
      break;
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      back = 1;
      break;
    }
    delay(50);
  }
  if (back == 1) goto A;
C:
  back = 0;
  for (int i = 1; i <= 12; i++)
  {
    if (strcmp(rtc.getMonthStr(), set_month_str[i]) == 0)
    {
      Month = i;
      break;
    }
  }
  while (true)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SET MONTH: ");
    lcd.setCursor(0, 1);
    lcd.print(set_month_str[Month]);
    if (digitalRead(inc) == LOW)
    {
      Month = Month + 1;
      if (Month > 12) Month = 1;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      Month = Month - 1;
      if (Month < 1) Month = 1;
      delay(200);
    }
    if (digitalRead(enter) == LOW)
    {
      delay(200);
      break;
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      back = 1;
      break;
    }
    delay(50);
  }
  if (back == 1) goto B;
  back = 0;
  lcd.clear();
  while (true)
  {
    lcd.setCursor(0, 0);
    lcd.print("SET YEAR [YY]: ");
    lcd.setCursor(0, 1);
    lcd.print(Year);
    if (digitalRead(inc) == LOW)
    {
      Year = Year + 1;
      if (Year > 2100) Year = 2100;
      delay(200);
    }
    if (digitalRead(dec) == LOW)
    {
      Year = Year - 1;
      if (Year < 2020) Year = 2020;
      delay(200);
    }
    if (digitalRead(ext) == LOW)
    {
      delay(200);
      back = 1;
      break;
    }
    if (digitalRead(enter) == LOW)
    {
      rtc.setDate(Date, Month, Year);
      if (y == 1) rtc.setDOW(MONDAY);
      if (y == 2) rtc.setDOW(TUESDAY);
      if (y == 3) rtc.setDOW(WEDNESDAY);
      if (y == 4) rtc.setDOW(THURSDAY);
      if (y == 5) rtc.setDOW(FRIDAY);
      if (y == 6) rtc.setDOW(SATURDAY);
      if (y == 7) rtc.setDOW(SUNDAY);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("DATE SAVED");

      delay(1500);
      lcd.clear();
      break;
    }
    delay(50);
  }
  if (back == 1) goto C;
}

Uh-oh.

if (t.date == 1, Month, Year && Hrs == 23 && Min == 59 && Sec == 00)

What's the comma for?

t.date == 1, month, year
this is equal to 1st date of every month every year

t.date == 1, 12, 2022
means 1 december 2022

when month and year is not mentioned in numeric that means all month and all year which will be read from rtc

Hello rababi
What is the case to use a FSM in your "well designed" sketch.
I´ve count 44 delay()´s and eight [8] while(true)´s.
Does these met your design goals?
Have a nice day and enjoy coding in C++.

p.s. and four [4] goto´s

You gave no description of the operation of your "alarm". Therefore, there is no way to determine if this code even meets the requirements of your "alarm". Furthermore, the code is really hard to follow, especially since you have many while(true) loops and gotos. Both unnecessary when coding for an Arduino. delay() calls will cause nothing but problems for you.

Unless you can provide a good description for the operation of your project you will probably not get much help.

That's a one second window. If you have any delay(), you risk not checking during the one second it is true.

Solution to this tiny problem: check only to the minute, giving you a one minute window, and set a flag to not do the triggered thing until the minute is over.

Also, isn't t.dow the day of the week? So this would only run once a week if you did manage to catch a break on the window thing.

a7

    delay(50);
  }
  if (back == 1) goto A;
}

void date_setting()
{
  delay(250);
A:
  back = 0;
  lcd.clear();
  int y = t.dow;

Does this compile? goto is considered harmful (!) by many, but certainly jumping into a function ought to offend everyone.

edit:
never mind I see another A label.

a7

Great.
Glad you got that sorted

This is the version of C++ where you can make up your own syntax and the compiler automatically knows what you mean.

That isn´t C++, that is C~~ :nerd_face:

1 Like

??? Why are you settine "Hrs" to the day of the week and "Min" to the day of the month ???

So... the 23rd day of the week on the 37th of the month?

Wouldn't that be "RUNS ON EVERY MONDAY" ???

Close. Once a week. Monday if that’s how you’ve decided to use the 1..7 which is the day of week register maintained.

I start my week on Sunday. :expressionless:

a7

const char* set_day_str[] = {"Null", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY",  "FRIDAY", "SATURDAY", "SUNDAY"};//

The implication of this bit of the sketch is that the value 1 maps to MONDAY.

For 'EVERY WEEKDAY' (Monday through Friday) use:
if (t.dow < 6 && ...)

Yes, I see.

I always think the DOW register should go 0..6, must notta been any C programmers around to help with that…

a7

sorry for that ,yes it was wrong i had already made correction

Can any one help, as i searched so many examples but still unable to find any clock code used state machine code, and i tried my self lcd screen dont refresh at every second to display clock, any clue, below is my code currently i am using

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <DS3231.h>
#include <Wire.h>
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
DS3231 rtc(SDA, SCL);
Time t;
int hh = 0, mm = 0, ss = 0;
int Date = 1, Month = 1, Year = 2022;
const int setting = A0;
const int enter = A1;
const int inc = A2;
const int dec = A3;
const int ext = 10;
const int BUZZER = 11;
bool back = 0;
const char* set_month_str[] = {"Null", "January", "February", "March", "April",  "May", "June", "July", "August", "September", "October",  "November", "December"};
const char* set_day_str[] = {"Null", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY",  "FRIDAY", "SATURDAY", "SUNDAY"};//

void setup ()
{
 pinMode(setting, INPUT_PULLUP);
 pinMode(enter, INPUT_PULLUP);
 pinMode(inc, INPUT_PULLUP);
 pinMode(dec, INPUT_PULLUP);
 pinMode(ext, INPUT_PULLUP);
 pinMode(BUZZER, OUTPUT);
 digitalWrite(BUZZER, LOW);
 Wire.begin();
 rtc.begin();
 lcd.begin(16, 2);
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" MAGIC ALARM");
 lcd.setCursor(0, 1);
 lcd.print("HAVE A NICE DAY");
 lcd.backlight();
 delay(3000);
 lcd.clear();
}
void loop ()
{

 t = rtc.getTime();
 int Hrs = t.hour;
 int Min = t.min;
 int Sec = t.sec;


 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(rtc.getTimeStr());
 lcd.setCursor(9, 0);
 lcd.print(rtc.getDOWStr(FORMAT_SHORT));
 lcd.setCursor(0, 1);
 lcd.print(rtc.getDateStr());

 if (Hrs == 23 && Min == 37 && Sec == 20)   // RUNS EVERY DAY AT SPECIFIC TIME
 {
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("ALARM ON");
   digitalWrite(BUZZER, HIGH);
   delay(500);
   digitalWrite(BUZZER, LOW);
   delay(500);
 }
 if (t.dow == 1 && Hrs == 15 && Min == 53 && Sec == 0) //RUNS ON EVERY WEEKDAYS
 {
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("ALARM ON");
   digitalWrite(BUZZER, HIGH);
   delay(500);
   digitalWrite(BUZZER, LOW);
   delay(500);
 }
 if (t.date == 1, Month, Year && Hrs == 23 && Min == 59 && Sec == 00)     // RUNS EVERY 1ST DAY OF EVERY MONTH AND YEAR
 {
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("ALARM ON");
   digitalWrite(BUZZER, HIGH);
   delay(500);
   digitalWrite(BUZZER, LOW);
   delay(500);
 }

 if (digitalRead(setting) == LOW)
 {
   delay(250);
   while (true)
   {
     lcd.setCursor(0, 0);
     lcd.print("  TIME SETTING  ");

     if (digitalRead(enter) == LOW)
     {
       delay(250);
       time_setting();
       break;
     }
     if (digitalRead(setting) == LOW)
     {
       break;
     }
   }
 }
 if (digitalRead(setting) == LOW)
 {
   delay(250);
   lcd.clear();
   while (true)
   {
     lcd.setCursor(0, 0);
     lcd.print("  DATE SETTING  ");

     if (digitalRead(enter) == LOW)
     {
       delay(250);
       date_setting();
       break;
     }
     if (digitalRead(setting) == LOW)
     {
       delay(250);
       lcd.clear();
       break;
     }
   }
 }
}
}
void time_setting()
{
 delay(250);
 hh = t.hour;
 mm = t.min;
A:
 lcd.clear();
 back = 0;
 while (true)
 {
   lcd.setCursor(0, 0);
   lcd.print("SET HOURS [HH]: ");
   lcd.setCursor(0, 1);
   if (hh < 10) lcd.print("0");
   lcd.print(hh);
   if (digitalRead(inc) == LOW)
   {
     hh = hh + 1;
     if (hh >= 24) hh = 0;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     hh = hh - 1;
     if (hh < 0) hh = 0;
     delay(200);
   }
   if (digitalRead(enter) == LOW)
   {
     delay(200);
     break;
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     return;
   }
   delay(50);
 }
 back = 0;
 while (true)
 {
   lcd.setCursor(0, 0);
   lcd.print("SET MINUTE [MM]: ");
   lcd.setCursor(0, 1);
   if (mm < 10) lcd.print("0");
   lcd.print(mm);
   if (digitalRead(inc) == LOW)
   {
     mm = mm + 1;
     if (mm >= 60) mm = 0;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     mm = mm - 1;
     if (mm < 0) mm = 0;
     delay(200);
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     back = 1;
     break;
   }
   if (digitalRead(enter) == LOW)
   {
     rtc.setTime(hh, mm, 0);
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print("   TIME SAVED   ");

     delay(1500);
     lcd.clear();
     break;
   }
   delay(50);
 }
 if (back == 1) goto A;
}

void date_setting()
{
 delay(250);
A:
 back = 0;
 lcd.clear();
 int y = t.dow;
 Date = t.date;
 while (true)
 {
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("SET DAY: ");
   lcd.setCursor(0, 1);
   lcd.print(set_day_str[y]);
   if (digitalRead(inc) == LOW)
   {
     y = y + 1;
     if (y > 7) y = 1;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     y = y - 1;
     if (y < 1) y = 7;
     delay(200);
   }
   if (digitalRead(enter) == LOW)
   {
     delay(200);
     break;
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     return;
   }
   delay(50);
 }
B:
 back = 0;
 lcd.clear();
 while (true)
 {
   lcd.setCursor(0, 0);
   lcd.print("SET DATE [DD]: ");
   lcd.setCursor(0, 1);
   if (Date < 10) lcd.print("0");
   lcd.print(Date);
   if (digitalRead(inc) == LOW)
   {
     Date = Date + 1;
     if (Date > 31) Date = 1;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     Date = Date - 1;
     if (Date < 1) Date = 1;
     delay(200);
   }
   if (digitalRead(enter) == LOW)
   {
     delay(200);
     break;
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     back = 1;
     break;
   }
   delay(50);
 }
 if (back == 1) goto A;
C:
 back = 0;
 for (int i = 1; i <= 12; i++)
 {
   if (strcmp(rtc.getMonthStr(), set_month_str[i]) == 0)
   {
     Month = i;
     break;
   }
 }
 while (true)
 {
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("SET MONTH: ");
   lcd.setCursor(0, 1);
   lcd.print(set_month_str[Month]);
   if (digitalRead(inc) == LOW)
   {
     Month = Month + 1;
     if (Month > 12) Month = 1;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     Month = Month - 1;
     if (Month < 1) Month = 1;
     delay(200);
   }
   if (digitalRead(enter) == LOW)
   {
     delay(200);
     break;
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     back = 1;
     break;
   }
   delay(50);
 }
 if (back == 1) goto B;
 back = 0;
 lcd.clear();
 while (true)
 {
   lcd.setCursor(0, 0);
   lcd.print("SET YEAR [YY]: ");
   lcd.setCursor(0, 1);
   lcd.print(Year);
   if (digitalRead(inc) == LOW)
   {
     Year = Year + 1;
     if (Year > 2100) Year = 2100;
     delay(200);
   }
   if (digitalRead(dec) == LOW)
   {
     Year = Year - 1;
     if (Year < 2020) Year = 2020;
     delay(200);
   }
   if (digitalRead(ext) == LOW)
   {
     delay(200);
     back = 1;
     break;
   }
   if (digitalRead(enter) == LOW)
   {
     rtc.setDate(Date, Month, Year);
     if (y == 1) rtc.setDOW(MONDAY);
     if (y == 2) rtc.setDOW(TUESDAY);
     if (y == 3) rtc.setDOW(WEDNESDAY);
     if (y == 4) rtc.setDOW(THURSDAY);
     if (y == 5) rtc.setDOW(FRIDAY);
     if (y == 6) rtc.setDOW(SATURDAY);
     if (y == 7) rtc.setDOW(SUNDAY);
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print("DATE SAVED");

     delay(1500);
     lcd.clear();
     break;
   }
   delay(50);
 }
 if (back == 1) goto C;
}

Your topic was MOVED to its current forum category as it is more suitable than the original

Flickering LCD ?

Have you tried only printing the values to the LCD when they change instead of every time through loop() ?

Even better, don't clear the LCD, only overwrite the value that has changed

Hello
Did I saw this sketch days ago, didn´t I?

	Line 213:  if (back == 1) goto A;
	Line 290:  if (back == 1) goto A;
	Line 333:  if (back == 1) goto B;
	Line 380:  if (back == 1) goto C;

Are you shure to code this ?
The editor has counted 44 calls of the delay() function.
Are you shure to code this ?
You may study the IPO model to design a structured sketch.
Have a nice day and enjoy coding in C++.