Why doesn't the Alarm.alarmRepeat work?

I tested my code at about 7:25, and waited for 7:30 for the bell to work. The Alarm.alarmRepeat(7, 29, 50, firstPeriod); does not trigger the void firstPeriod(), so it did not write the "AM bell starts now" in the serial comms. Did I do something wrong in my code? (pls ignore the comments)

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

RTC_DS3231 rtc;
AlarmId;

#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] = { 11, 6, 7, 9 };
byte pin_column[numCols] = { 10, 12, 8 };
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;

// Variables list
char code[] = { '6', '6', '0', '1' };  // password is 6601
int i = 0, a = 0, j = 0;               // needed for password typing
int i1, i2, i3;                        // needed for calculations
char c1, c2, c3;
unsigned long time = millis();  // needed for the bell to function properly
unsigned long time2 = millis();
unsigned long displayTime = millis();
int intervalMins = 60;                   // number of minutes in a class
unsigned long intervalMillis = 3600000;  // intervalMins in milliseconds
int tentativeInt;                        // placeholder number in calculations
unsigned long length = 3000;
unsigned long length2 = 3000;
int customMins = 60;                   // number of minutes between 6:30 and the first bell
unsigned long customMillis = 3600000;  // 6:30 in 3600s is 7:30
char keypressed = myKeypad.getKey();
byte period;
byte period2;
bool alarmOngoing = false;  // not yet in a class day
bool alarmOngoingPM = false;
bool isMorning = false;    // for turning on morning alarms
bool isAfternoon = false;  // isMorning but afternoon
bool recessOn = true;      // customize whether to include recess in schedule
bool recessOnPM = true;
bool customTime = false;  // 6:30 is the start time

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;
    }
  }
  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__)));
  }

  // We don't need this
  rtc.disable32K();

  Alarm.alarmRepeat(7, 29, 50, firstPeriod);  // 6:30
  Alarm.alarmRepeat(12, 59, 50, pmPeriod);    // 1:00 pm
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
}

void loop() {
  goToMenu();
  digitalClockDisplay();

  do {
    goToMenu();
    alarmBegin();
  } while (alarmOngoing);

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

void goToMenu() {
  if (keypressed == '*') {
    Serial.println("Enter code:");
    getPassCode();
    if (a == sizeof(code)) {
      setupMenu();
    } else {
      wrongPassCodeMsg();
    }
  }

  if (keypressed == '#') {
    Serial.println("Enter code:");
    getPassCode();
    if (a == sizeof(code)) {
      customMenu();
    } else {
      wrongPassCodeMsg();
    }
  }
}

void alarmBegin() {
  isMorning = true;
  time = millis();
  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;
        if (recessOn) {
          period = 2;
        } else {
          period = 3;
        }
        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;
      case 12:
        time = millis();
        length = customMillis;
        period = 0;
        Serial.println("Not time yet");
    }
  }
}

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;
        if (recessOnPM) {
          period2 = 2;
        } else {
          period2 = 3;
        }
        Serial.print("Period is now ");
        Serial.println(period2);
        break;
      case 2:  // recess
        buzzer2();
        length2 = 900000;
        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(2000);
  digitalWrite(2, HIGH);
}

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

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

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

void wrongPassCodeMsg() {
  Serial.println("Wrong");
}

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

void setupMenu() {
  Serial.println("* - set start time  # - set period length");
  char keypressed2 = myKeypad.waitForKey();
  if (keypressed2 == '*') {
    Serial.println("Setting start time");
    delay(1500);
    Serial.println("Enter time of first bell");
    char keypressed3 = myKeypad.waitForKey();
    if (keypressed3 >= '6' && keypressed3 <= '8') {  // only accept numbers 6, 7, and 8
      c1 = keypressed3;
      Serial.print(c1);
      Serial.print(":");
    }
    char keypressed4 = myKeypad.waitForKey();
    if (keypressed3 == '6') {                          // keypressed3 is 6
      if (keypressed4 >= '3' && keypressed4 <= '5') {  // unsigned long customMillis does not accept negative numbers
        c2 = keypressed4;
        Serial.print(c2);
      }
    }
    if (keypressed3 == '7' || keypressed3 == '8') {  // keypressed3 is 7 or 8
      if (keypressed4 >= '0' && keypressed4 <= '5') {
        c2 = keypressed4;
        Serial.print(c2);
      }
    }
    char keypressed5 = myKeypad.waitForKey();
    if (keypressed5 >= '0' && keypressed5 <= '9') {
      c3 = keypressed5;
      Serial.println(c3);
    }
    i1 = (c1 - 54) * 60;  // calculation from time into minutes
    i2 = ((c2 - 48) * 10) - 30;
    i3 = c3 - 48;
    tentativeInt = i1 + i2 + i3;
    delay(500);
    if (tentativeInt >= 1) {
      Serial.print("Time period from 6:30 to bell: ");
      Serial.print(tentativeInt);
      Serial.println(" minutes");
      customMins = tentativeInt;
      customMillis = customMins * 60000;  // conversion from mins to milliseconds
      customTime = true;
    } else {  // tentativeInt is 0
      Serial.println("Returning to 6:30 bell");
      customTime = false;
    }
  } else if (keypressed2 == '#') {
    Serial.println("Setting period");
    delay(1500);
    Serial.println("Enter length:");
    char keypressed3 = myKeypad.waitForKey();
    if (keypressed3 != NO_KEY && keypressed3 != '#' && keypressed3 != '*') {
      c1 = keypressed3;
      Serial.print(c1);
    }
    char keypressed4 = myKeypad.waitForKey();
    if (keypressed4 != NO_KEY && keypressed4 != '#' && keypressed4 != '*') {
      c2 = keypressed4;
      Serial.println(c2);
    }
    i1 = (c1 - 48) * 10;
    i2 = c2 - 48;
    tentativeInt = i1 + i2;
    delay(500);
    if (tentativeInt > 60) {
      Serial.println("Don't input more than 1 hour");
    } else if (tentativeInt <= 60 && tentativeInt >= 2) {
      Serial.print("Class interval: ");
      Serial.print(tentativeInt);
      Serial.println(" minutes");
      intervalMins = tentativeInt;
      intervalMillis = intervalMins * 60000;
    } else {  // tentativeInt is 1 or 0
      Serial.println("Input invalid");
    }
  } else {
    Serial.println("Returning to time display");
  }
}

void customMenu() {
  Serial.println("* - toggle recess  # - time status");
  char keypressed2 = myKeypad.waitForKey();
  if (keypressed2 == '*') {
    Serial.println("AM recess on?");
    Serial.println("* - yes   # - no");
    char keypressed3 = myKeypad.waitForKey();
    if (keypressed3 == '*') {
      recessOn = true;
      Serial.println("AM recess on");
      delay(1500);
      pmRecessToggle();
    }
    if (keypressed3 == '#') {
      recessOn = false;
      Serial.println("AM recess off");
      delay(1500);
      pmRecessToggle();
    }
  } else if (keypressed2 == '#') {
    Serial.print("Time: ");
    Serial.print(hour());
    printDigits(minute());
    printDigits(second());
    delay(1000);
  } else {
    Serial.println("Returning to time display");
  }
}

void pmRecessToggle() {
  Serial.println("PM recess on?");
  Serial.println("* - yes   # - no");
  char keypressed4 = myKeypad.waitForKey();
  if (keypressed4 == '*') {
    recessOnPM = true;
    Serial.println("PM recess on");
  }
  if (keypressed4 == '#') {
    recessOnPM = false;
    Serial.println("PM recess off");
  }
}

void digitalClockDisplay() {
  if (millis() - displayTime >= 1000) {
    lcd.clear();
    lcd.print("Time: ");
    Serial.print(hour());
    lcd.print(hour());
    printDigits(minute());
    printDigits(second());
    Serial.println();
    displayTime = millis();
  }
}

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

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

void printDigits2(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.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;
}

I do not see your sketch calling Alarm.delay() as discussed in the Read Me section of the library documentation.

Your sketch should call the Alarm.delay() function instead of the Arduino delay() function when
using the Alarms library. The timeliness of triggers depends on sketch delays using this function.
Alarm.delay( period); // Similar to Arduino delay - pauses the program for the period (in milliseconds).

Did you run any library example sketches to verify your setup? Alarm.delay( ) is used in the examples.

Oh I see. I removed the alarm delay so the program always reads the goToMenu() so the user can access it whenever they want. Do I just have to add something like Alarm.delay(0) somewhere?

Discussion here
https://forum.arduino.cc/t/question-about-pjrcs-timealarms-library/515982

Do I just have to add something like Alarm.delay(0) somewhere?

"Somewhere" doesn't sound specific enough. :wink:

1 Like

Thank you good sir

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