The relay does not trigger in longer period intervals

I'm a relatively new Arduino user. I use Arduino uno, DS3231 rtc, 5v relay, keypad, and lcd for my project. I'm trying to make an automatic school bell, and my project uses a relay that ticks on and off in a pattern of schedule. When I made the value for length and length2 very short (about 6 seconds or so), the void buzzer() ticks based on the intended schedule, but when I put 3,600,000 (1 hour) as the value for length, the void buzzer() just doesn't function 1 hour later, but the current time still keeps showing in serial. Admittedly, I only power my Arduino with usb cable connected to my laptop, since the battery I ordered still hasn't arrived. Does the battery help with this problem, or is it some sort of a limitation or fault in the code?

#include <Wire.h>
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <RTClib.h>
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>

RTC_DS3231 rtc;

#define I2C_ADDR 0x27  // LCD i2c address
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

// LCD setup
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);

// Keypad setup
const byte numRows = 4;  // 4 rows
const byte numCols = 3;  // 3 columns
char keymap[numRows][numCols] = {
  { '1', '2', '3' },
  { '4', '5', '6' },
  { '7', '8', '9' },
  { '*', '0', '#' }
};

byte pin_rows[numRows] = { 12, 11, 10, 9 };
byte pin_column[numCols] = { 8, 7, 6 };
Keypad myKeypad = Keypad(makeKeymap(keymap), pin_rows, pin_column, numRows, numCols);

// RTC setup
const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

tmElements_t tm;
char daysOfTheWeek[7][12] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

char code[] = { '6', '6', '0', '1' };  // password is 6601
int i = 0, a = 0, j = 0;               // needed for password typing
int i1, i2, i3;
char c1, c2, c3;
unsigned long time = millis();
unsigned long time2 = millis();
int intervalMins = 60;
int intervalMillis = 6000;
int tentativeInt;
int length = 3000;
int length2 = 3000;
byte period;
byte period2;
char keypressed = myKeypad.getKey();
byte firstBell = 2;
bool buzzerOn = false;
bool displayTime = true;
bool alarmOngoing = false;
bool alarmOngoingPM = false;
bool isMorning = false;
bool isAfternoon = false;


void setup() {
  bool parse = false;
  bool config = false;

  // get the date and time the compiler was run
  if (getDate(__DATE__) && getTime(__TIME__)) {
    parse = true;
    // and configure the RTC with this info
    if (RTC.write(tm)) {
      config = true;
    }
  }
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial)
    ;  // wait for Arduino Serial Monitor
  setSyncProvider(RTC.get);
  setTime(tm.Hour, tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year);

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC!");
    Serial.flush();
    while (1) delay(10);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power. Setting time...");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  rtc.disable32K();

  Alarm.alarmRepeat(7, 29, 50, firstPeriod);
  Alarm.alarmRepeat(12, 59, 50, pmPeriod);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
  do {
    alarmBegin();
    digitalClockDisplay();
  } while (alarmOngoing);

  do {
    alarmBegin2();
    digitalClockDisplay();
  } while (alarmOngoingPM);

  do {
    digitalClockDisplay2();
  } while (displayTime);

  if (keypressed == '*') {
    displayTime = false;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Enter code:");
    getPassCode();
    if (a == sizeof(code)) {
      setupMenu();
    } else {
      wrongPassCodeMsg();
    }
    displayTime = true;
  }
}

void alarmBegin() {
  if (isMorning == true && millis() - time >= length) {
    switch (period) {
      case 0:  // 1st period
        buzzer();
        length = intervalMillis;
        period = 1;
        Serial.print("Period is now ");
        Serial.println(period);
        break;
      case 1:  // 2nd period
        buzzer();
        length = intervalMillis;
        period = 2;
        Serial.print("Period is now ");
        Serial.println(period);
        break;
      case 2:  // recess
        buzzer();
        length = 3000;
        period = 3;
        Serial.print("Period is now ");
        Serial.println(period);
        break;
      case 3:  // 3rd period
        buzzer();
        length = intervalMillis;
        period = 4;
        Serial.print("Period is now ");
        Serial.println(period);
        break;
      case 4:  // 4th period
        buzzer();
        length = intervalMillis;
        period = 5;
        Serial.print("Period is now ");
        Serial.println(period);
        break;
      case 5:  // lunch
        buzzer();
        length = 0;
        period = 6;
        Serial.println("End of morning class");
        alarmOngoing = false;
        isMorning = false;
        break;
    }
  }
}

void alarmBegin2() {
  if (isAfternoon == true && millis() - time2 >= length2) {
    switch (period2) {
      case 0:  // 1st period pm
        buzzer2();
        length2 = intervalMillis;
        period2 = 1;
        Serial.print("Period is now ");
        Serial.println(period2);
        break;
      case 1:  // 2nd period pm
        buzzer2();
        length2 = intervalMillis;
        period2 = 2;
        Serial.print("Period is now ");
        Serial.println(period2);
        break;
      case 2:  // recess
        buzzer2();
        length2 = 3000;
        period2 = 3;
        Serial.print("Period is now ");
        Serial.println(period2);
        break;
      case 3:  // 3rd period pm
        buzzer2();
        length2 = intervalMillis;
        period2 = 4;
        Serial.print("Period is now ");
        Serial.println(period2);
        break;
      case 4:  // after class
        buzzer2();
        length2 = 0;
        period2 = 5;
        Serial.println("End of afternoon class");
        alarmOngoingPM = false;
        isAfternoon = false;
        break;
    }
  }
}

void buzzer() {
  time = millis();
  digitalWrite(2, LOW);
  Serial.println("Bell");
  Alarm.delay(1000);
  digitalWrite(2, HIGH);
}

void buzzer2() {
  time2 = millis();
  digitalWrite(2, LOW);
  Serial.println("Bell");
  Alarm.delay(1000);
  digitalWrite(2, HIGH);
}

void firstPeriod() {
  period = 0;
  isMorning = true;
  alarmOngoing = true;
  displayTime = false;
  Serial.println("AM bell starts now");
}

void pmPeriod() {
  period2 = 0;
  isAfternoon = true;
  alarmOngoingPM = true;
  displayTime = false;
  Serial.println("PM bell starts now");
}

void wrongPassCodeMsg() {
  lcd.clear();
  lcd.print("Wrong. Try again");
  delay(1500);
  lcd.clear();
}

void getPassCode() {
  i = 0;
  a = 0;
  j = 0;
  char keypressed = NO_KEY;
  while (keypressed != '#') {
    keypressed = myKeypad.getKey();
    if (keypressed != NO_KEY && keypressed != '#') {
      lcd.setCursor(j, 1);
      lcd.print("*");
      j++;
      if (keypressed == code[i] && i < sizeof(code)) {
        a++;
        i++;
      } else
        a--;
    }
  }
}

void setupMenu() {
  lcd.clear();
  lcd.print("Setting period");
  lcd.setCursor(0, 1);
  lcd.print("length...");
  delay(1500);
  lcd.clear();
  lcd.print("Enter length:");
  char keypressed3 = myKeypad.waitForKey();
  if (keypressed3 != NO_KEY && keypressed3 != '#' && keypressed3 != '*') {
    c1 = keypressed3;
    lcd.setCursor(0, 1);
    lcd.print(c1);
  }
  char keypressed4 = myKeypad.waitForKey();
  if (keypressed4 != NO_KEY && keypressed4 != '#' && keypressed4 != '*') {
    c2 = keypressed4;
    lcd.setCursor(1, 1);
    lcd.print(c2);
  }
  char keypressed5 = myKeypad.waitForKey();
  if (keypressed5 != NO_KEY && keypressed5 != '#' && keypressed5 != '*') {
    c3 = keypressed5;
    lcd.setCursor(2, 1);
    lcd.print(c3);
  }
  i1 = (c1 - 48) * 100;
  i2 = (c2 - 48) * 10;
  i3 = c3 - 48;
  tentativeInt = i1 + i2 + i3;
  delay(500);
  lcd.clear();
  if (tentativeInt > 180) {
    lcd.print("Don't input more");
    lcd.setCursor(0, 1);
    lcd.print("than 3 hours");
  } else if (tentativeInt <= 180 && tentativeInt != 0) {
    lcd.print("Class interval");
    lcd.setCursor(0, 1);
    lcd.print("set!");
    intervalMins = tentativeInt;
    intervalMillis = intervalMins * 60000;
  } else {  // tentativeInt == 0
    lcd.print("Input invalid");
  }
  delay(1500);
  lcd.clear();
}

void digitalClockDisplay() {
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
  Alarm.delay(1000);
}

void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void digitalClockDisplay2() {
  lcd.clear();
  lcd.print("Time: ");
  Serial.print(hour());
  lcd.print(hour());
  printDigits2(minute());
  printDigits2(second());
  Serial.println();
  Alarm.delay(1000);
}

void printDigits2(int digits) {
  Serial.print(":");
  lcd.print(":");
  if (digits < 10)
    Serial.print('0');
  lcd.print('0');
  Serial.print(digits);
  lcd.print(digits);
}

bool getTime(const char *str) {
  int Hour, Min, Sec;

  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}

bool getDate(const char *str) {
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;

  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0) break;
  }
  if (monthIndex >= 12) return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}

What are you expecting in this case? Your length variable has an int type. The maximum value of the int on Uno is 32768

All intervals used with millis() - should be defined as unsigned long type.

You should try to work in your "important" units as much as possible. So if the bell interval is measured in minutes, then convert milliseconds to minutes and use those for the operations. Little things like this make it much easier to reason about your program.

1 Like

Thank you for the help guys. Much appreciated

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.