I previously tried removing the lcd.clear(); at the beginning of the timer() but didn't solve the issue.
Here's the full code:
//v3.7 brings the addition of a DH11 sensor module, which will output the temp and humidity.
//3.8-4.9 were failed attempts at making a special character font clock.
//v5.0 adds the BMP180 atm pressure and temp sensor
//Replaced dht11 temp readings with BMP180, as it is more accurate
//v5.1 removes 2 unrequired variables
//v5.2 adds switch case for the mode selectors and removes unnecessary brackets from if else statements
//v5.5 brings a new weather mode, giving all details about the current weather. also changes the temp, humidity and pressure readings a bit.
//removed some unused special characters, added some more like rain, sunny, clear. will display these characters if the weather is right.
//v5.6 tests out the hd44780 library
//the new hd44780 library works wonders. changed the layout of the clock face.
//v5.7 finally is capable of deactivating the alarm. Also shows if any alarms are active or not in the home face.
//rearranged the temp and humidity readings. fixed the avg pressure issue. increased time of ir detection to save bit more power.
//if humidity > 90% then it will show rain drops
//v5.8: 1)reduce delay times. 2)change pressure average timing
//v5.9: 1)removed boolean backlight() func. 2)changed the average logic by using weighted averages
//v6.0: 1)remove unwanted processing 2)improved the accuracy of the averagePressure part. 3) timer
#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings
#include <Arduino.h>
#include <EEPROM.h>
#include <virtuabotixRTC.h>
virtuabotixRTC myRTC(6, 7, 8);
//Libraries for DHT11(temp and humidity sensor) module
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Math.h>
#define DHTPIN 12
#define DHTTYPE DHT11
DHT_Unified dht(DHTPIN, DHTTYPE);
//Libraries for BMP180 (Pressure and temp sensor)
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
//button variables
const int btnChange = 9;
const int btnOK = 10;
const int btnMode = 11;
//buzzer
const int buzzer = 16;
//IR
const unsigned int ir = 17;
int buttonState = 0;
int oldButtonState = LOW;
boolean ledState = false;
unsigned long previousMillis = 0;
int alarmHour = 12;
int alarmMinutes = 0;
boolean hourMode = 0;
boolean alarmOn = 1;
boolean alrmState = false;
int M = 06;
int D = 01;
int Y = 2024;
int dy = 7;
int h = 00;
int m = 00;
int addrH[] = { 0, 1, 2, 3, 4 };
int addrM[] = { 5, 6, 7, 8, 9 };
int addrActive[] = { 10, 11, 12, 13, 14 };
int mode = 1;
int submode = 1;
int slot = 0;
int timerH = 0, timerM = 0, timerS = 0;
int scroll = 1;
boolean timerActivate = false;
const static char* WeekDays[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
uint8_t moon[8] = { B11100, B01110, B00111, B00111, B00111, B00111, B01110, B11100 };
uint8_t alarmChar[8] = { B00100, B01110, B01110, B01110, B11111, B00000, B00100, B00000 };
uint8_t sunny[8] = { B00100, B10101, B01110, B11011, B01110, B10101, B00100, B00000 };
uint8_t rain[8] = { B00100, B01110, B01110, B11111, B11111, B11111, B01110, B00000 };
uint8_t same[8] = { B01000, B11101, B10111, B00010, B01000, B11101, B10111, B00010 };
uint8_t temperature[8] = { B00100, B01010, B01010, B01010, B01010, B11101, B11111, B01110 };
uint8_t pressure[8] = { B01110, B01110, B01110, B01110, B01110, B11111, B01110, B00100 };
uint8_t hourGlass[8] = { B11111, B10001, B11111, B01110, B00100, B01010, B10101,B11111};
float currentPressure;
float ave = 0.0;
boolean flag = false;
#define NO_BACKLIGHT
#define BACKLIGHT_ALWAYS_ON
#define BACKLIGHT_TIMEOUT 10000
void setup() {
dht.begin();
bmp.begin();
lcd.begin(16, 2);
pinMode(btnChange, INPUT_PULLUP);
pinMode(btnOK, INPUT_PULLUP);
pinMode(btnMode, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
pinMode(ir, INPUT_PULLUP);
lcd.init();
lcd.init();
lcd.backlight(); // Turn on the blacklight
lcd.createChar(0, moon);
lcd.createChar(1, alarmChar);
lcd.createChar(2, sunny);
lcd.createChar(3, rain);
lcd.createChar(4, same);
lcd.createChar(5, temperature);
lcd.createChar(6, pressure);
lcd.createChar(7, hourGlass);
digitalWrite(buzzer, HIGH);
lcd.setCursor(1, 0); //initial splash screen
lcd.print("Arduino Alarm");
lcd.setCursor(2, 1);
lcd.print("Clock v6.0");
delay(1000);
}
void loop() {
buttonState = digitalRead(ir);
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 150) {
previousMillis = currentMillis;
if (buttonState != oldButtonState && buttonState == HIGH) {
ledState = (ledState == false ? true : false);
if (ledState == true)
lcd.backlight();
else
lcd.noBacklight();
}
oldButtonState = buttonState;
}
if (digitalRead(btnMode) == LOW) {
digitalWrite(buzzer, LOW);
delay(50);
digitalWrite(buzzer, HIGH);
mode++;
if (mode == 6) {
mode = 1;
}
//The delays after every submode serves a purpose. If you remove them the modes changes very quickly while pressing the mode button
//which makes it difficult to navigate to the desired mode
submode = 0;
lcd.clear();
delay(100);
}
switch (mode) {
case 1:
clockDisplay();
break;
case 2:
weatherMode();
delay(100);
break;
case 3:
alarmMode();
delay(100);
break;
case 4:
timerInterface();
timer();
delay(100);
break;
case 5:
updateRTC();
delay(100);
break;
// case 0:
// // alarm();
// // EEPROM.write(addrActive, 0);
// break;
default:
break;
}
for (int x = 0; x < 5; x++)
if (EEPROM.read(addrActive[x]) == 1) {
alrmState = true;
if (myRTC.hours == EEPROM.read(addrH[x]) && myRTC.minutes == EEPROM.read(addrM[x])) {
EEPROM.write(addrActive[x], 0);
alarm('a');
EEPROM.write(addrActive, 0);
}
}
}
boolean alarm(char alarmOrTimer) {
if (alarmOrTimer == 'a')
clockDisplay();
else if (alarmOrTimer == 't') {
lcd.clear();
lcd.setCursor(4, 0);
if (timerH < 10)
lcd.print("0");
lcd.print(timerH);
lcd.print(":");
if (timerM < 10)
lcd.print("0");
lcd.print(timerM);
lcd.print(":");
if (timerS < 10)
lcd.print("0");
lcd.print(timerS);
}
for (int i = 0; i < 60; i++) {
if (digitalRead(btnMode) == LOW || digitalRead(btnChange) == LOW || digitalRead(btnOK) == LOW || digitalRead(ir) == LOW)
return true;
lcd.noBacklight();
digitalWrite(buzzer, LOW);
delay(200);
lcd.backlight();
digitalWrite(buzzer, HIGH);
delay(200);
lcd.noBacklight();
digitalWrite(buzzer, LOW);
delay(200);
lcd.backlight();
digitalWrite(buzzer, HIGH);
delay(400);
if (digitalRead(btnMode) == LOW || digitalRead(btnChange) == LOW || digitalRead(btnOK) == LOW || digitalRead(ir) == LOW)
return true;
}
}
////////////////////////////////////////////////////////////////CLOCK DISPLAY FUCNTION
void clockDisplay() {
lcd.home();
myRTC.updateTime(); //This allows for the update of variables for time.
static uint8_t last_second = 0;
if (last_second != myRTC.seconds) {
last_second = myRTC.seconds;
lcd.write(3);
sensors_event_t event;
dht.humidity().getEvent(&event);
lcd.print(round(floor((event.relative_humidity))));
lcd.print("% ");
//Time
if (myRTC.hours < 10) lcd.print('0');
lcd.print(myRTC.hours); // 00-23
lcd.print(':');
if (myRTC.minutes < 10) lcd.print('0');
lcd.print(myRTC.minutes); // 00-59
lcd.print(' ');
lcd.write(5);
lcd.print(round(floor((bmp.readTemperature()))));
lcd.write(B11011111);
lcd.print("C");
//2nd line
//
lcd.setCursor(0, 1);
if (alrmState == true)
lcd.write(1);
else
lcd.print(' ');
//Day of the week
lcd.print(WeekDays[myRTC.dayofweek - 1]); // 1-7
lcd.print(' ');
lcd.print(myRTC.dayofmonth); // 01-31
switch (myRTC.dayofmonth % 10) {
case 1:
lcd.print("st");
break;
case 2:
lcd.print("nd");
break;
case 3:
lcd.print("rd");
break;
default:
lcd.print("th");
break;
}
lcd.print(' ');
switch (myRTC.month) {
case 1:
lcd.print("Jan");
break;
case 2:
lcd.print("Feb");
break;
case 3:
lcd.print("Mar");
break;
case 4:
lcd.print("Apr");
break;
case 5:
lcd.print("May");
break;
case 6:
lcd.print("Jun");
break;
case 7:
lcd.print("Jul");
break;
case 8:
lcd.print("Aug");
break;
case 9:
lcd.print("Sep");
break;
case 10:
lcd.print("Oct");
break;
case 11:
lcd.print("Nov");
break;
case 12:
lcd.print("Dec");
break;
default:
break;
}
lcd.print(' ');
int avgPrsr = avgPressure();
currentPressure = round(bmp.readPressure() / 100);
int pressureDelta = abs(avgPrsr - currentPressure);
if (myRTC.hours >= 0 && myRTC.hours <= 3 || myRTC.hours > 17 && myRTC.hours <= 23)
lcd.write(0);
else
lcd.write(2);
//low pressure
if (pressureDelta > 2 && avgPrsr > currentPressure || event.relative_humidity > 90)
lcd.write(3);
//high pressure
else if (pressureDelta > 2 && avgPrsr < currentPressure) {
if (myRTC.hours >= 0 && myRTC.hours <= 3 || myRTC.hours > 17 && myRTC.hours <= 23)
lcd.write(0);
else
lcd.write(2);
}
//similar pressure
else if (pressureDelta <= 2 || avgPrsr == currentPressure) {
lcd.setCursor(13, 1);
lcd.write(4);
}
}
}
void weatherMode() {
lcd.home();
myRTC.updateTime();
static uint8_t last_second = 0;
if (last_second != myRTC.seconds) {
last_second = myRTC.seconds;
lcd.write(5);
lcd.print(bmp.readTemperature());
lcd.write(B11011111);
lcd.print("C ");
sensors_event_t event;
dht.humidity().getEvent(&event);
lcd.write(3);
lcd.print(round(event.relative_humidity));
lcd.print("%");
//lcd.print(countH);
lcd.setCursor(0, 1);
lcd.write(6);
lcd.print(round(currentPressure));
lcd.print("mB ");
//lcd.setCursor(8, 1);
lcd.print("A=");
lcd.print(avgPressure());
lcd.print("mB");
}
}
int avgPressure() {
myRTC.updateTime();
static uint8_t last_second = 0;
if (last_second != myRTC.seconds) {
last_second = myRTC.seconds;
if (myRTC.seconds == 0 && flag == false) {
flag = true;
ave = ave * 0.9 + bmp.readPressure() / 100 * 0.1;
}
if (myRTC.seconds == 5)
flag = false;
return ave;
}
}
void timerInterface() {
if (timerActivate == false) {
lcd.setCursor(0, 0);
lcd.write(7);
lcd.setCursor(2, 0);
lcd.print("Set ||");
lcd.setCursor(0, 1);
lcd.print("Timer ||");
lcd.setCursor(8, 1);
//timer hour
if (timerH < 10) {
lcd.print("0");
lcd.setCursor(9, 1);
}
lcd.print(timerH);
//timer minutes
lcd.setCursor(10, 1);
lcd.print(":");
lcd.setCursor(11, 1);
if (timerM < 10) {
lcd.print("0");
lcd.setCursor(12, 1);
}
lcd.print(timerM);
//timer seconds
lcd.print(":");
lcd.setCursor(14, 1);
if (timerS < 10) {
lcd.print("0");
lcd.setCursor(15, 1);
}
lcd.print(timerS);
if (digitalRead(btnOK) == LOW) {
scroll++;
if (scroll > 5)
scroll = 1;
delay(100);
lcd.clear();
}
if (scroll == 1) {
lcd.setCursor(8, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
timerH++;
if (timerH > 24)
timerH = 0;
delay(200);
}
}
if (scroll == 2) {
lcd.setCursor(11, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
timerM++;
if (timerM > 59)
timerH = 0;
delay(200);
}
}
if (scroll == 3) {
lcd.setCursor(14, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
timerS++;
if (timerS > 59)
timerS = 0;
delay(200);
}
}
if (scroll == 4) {
lcd.clear();
lcd.home();
if (timerH == 0 && timerM == 0 && timerS == 0) {
timerH = 23;
timerM = 59;
timerS = 59;
lcd.print("Starting timer....");
//delay(500);
//lcd.clear();
timerActivate = true;
}
}
}
}
void timer() {
if (timerActivate == true) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(7);
myRTC.updateTime();
static uint8_t last_second = 0;
if (last_second != myRTC.seconds) {
last_second = myRTC.seconds;
if (timerS < 0) {
timerS = 59;
timerM--;
}
timerS--;
if (timerM < 0) {
timerM = 59;
timerH--;
}
lcd.setCursor(4, 0);
if (timerH < 10)
lcd.print("0");
lcd.print(timerH);
lcd.print(":");
if (timerM < 10)
lcd.print("0");
lcd.print(timerM);
lcd.print(":");
if (timerS < 10)
lcd.print("0");
lcd.print(timerS);
if (timerH == 0 && timerM == 0 && timerS == 0) {
alarm('t');
timerActivate = false;
}
}
}
}
/////////////////////////////////////////////////////////////////// ALARM FUNCTION ///////////////////////////////////////////
void alarmMode() {
if (submode == 0) {
lcd.setCursor(0, 0);
lcd.write(1);
lcd.setCursor(2, 0);
lcd.print("Select:");
if (digitalRead(btnChange) == LOW) {
slot++;
if (slot > 4)
slot = 0;
delay(100);
}
lcd.setCursor(10, 0);
lcd.print("Slot#");
lcd.print(slot + 1);
lcd.setCursor(0, 1);
if (EEPROM.read(addrH[slot]) > 23)
EEPROM.write(addrH[slot], 0);
if (EEPROM.read(addrM[slot]) > 59)
EEPROM.write(addrM[slot], 0);
if (EEPROM.read(addrActive[slot]) > 1)
EEPROM.write(addrActive[slot], 0);
if ((EEPROM.read(addrH[slot]) > 12 && EEPROM.read(addrH[slot]) < 22) || (EEPROM.read(addrH[slot]) > 0 && EEPROM.read(addrH[slot]) < 10))
lcd.print("0");
if (EEPROM.read(addrH[slot]) == 0) {
lcd.print("12");
alarmHour = 12;
} else if (EEPROM.read(addrH[slot]) <= 12) {
lcd.print(EEPROM.read(addrH[slot]));
alarmHour = EEPROM.read(addrH[slot]);
} else {
lcd.print(EEPROM.read(addrH[slot]) - 12);
alarmHour = EEPROM.read(addrH[slot]) - 12;
}
lcd.print(":");
if (EEPROM.read(addrM[slot]) < 10)
lcd.print("0");
lcd.print(EEPROM.read(addrM[slot]));
alarmMinutes = EEPROM.read(addrM[slot]);
lcd.print(" ");
if (EEPROM.read(addrH[slot]) < 12) {
lcd.print("AM");
hourMode = 0;
} else {
lcd.print("PM");
hourMode = 1;
}
lcd.print(" ");
if (EEPROM.read(addrActive[slot]) == 1)
lcd.print("ON ");
else
lcd.print("OFF");
} else {
lcd.setCursor(0, 0);
lcd.write(1);
lcd.setCursor(2, 0);
lcd.print("Set ||");
lcd.setCursor(0, 1);
lcd.print("Alarm ||");
lcd.setCursor(9, 1);
if (alarmHour < 10) {
lcd.print("0");
lcd.setCursor(10, 1);
}
lcd.print(alarmHour);
lcd.setCursor(11, 1);
lcd.print(":");
lcd.setCursor(12, 1);
if (alarmMinutes < 10) {
lcd.print("0");
lcd.setCursor(13, 1);
}
lcd.print(alarmMinutes);
if (hourMode == 0)
lcd.print("AM");
else
lcd.print("PM");
}
// lcd.print(alarmMinutes);
if (digitalRead(btnOK) == LOW) {
submode++;
if (submode > 4)
submode = 0;
delay(100);
lcd.clear();
}
if (submode == 1) {
lcd.setCursor(9, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
alarmHour++;
if (alarmHour > 12)
alarmHour = 1;
delay(200);
}
}
if (submode == 2) {
lcd.setCursor(12, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
alarmMinutes++;
if (alarmMinutes >= 60)
alarmMinutes = 0;
delay(200);
}
}
if (submode == 3) {
lcd.setCursor(14, 0);
lcd.write(6);
lcd.write(6);
if (digitalRead(btnChange) == LOW) {
hourMode = !hourMode;
delay(200);
}
}
while (submode == 4) {
lcd.setCursor(0, 0);
lcd.print("Activate Alarm?");
lcd.setCursor(0, 1);
lcd.print("Slot #");
lcd.print(slot + 1);
lcd.print(" ");
if (alarmOn == 1)
lcd.print("ON ");
else
lcd.print("OFF");
if (digitalRead(btnChange) == LOW) {
alarmOn = !alarmOn;
delay(200);
}
if (digitalRead(btnOK) == LOW && alarmOn == 1) {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Saving........");
if (hourMode == 1 && alarmHour != 12) {
EEPROM.write(addrH[slot], alarmHour + 12);
} else if (hourMode == 0 && alarmHour == 12) {
EEPROM.write(addrH[slot], 0);
} else {
EEPROM.write(addrH[slot], alarmHour);
}
EEPROM.write(addrM[slot], alarmMinutes);
EEPROM.write(addrActive[slot], 1);
submode = 0;
mode = 1;
lcd.clear();
}
if (digitalRead(btnOK) == LOW && alarmOn == 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Alarm Slot#");
lcd.print(slot + 1);
lcd.setCursor(0, 1);
lcd.print(" OFF ");
EEPROM.write(addrActive[slot], 0);
submode = 0;
mode = 1;
delay(500);
lcd.clear();
}
}
}
/////////////////////////////////////////////////////////////////// SETTING DATE & TIME FUNCTION ///////////////////////////////////////////
void updateRTC() {
lcd.setCursor(0, 0);
if (digitalRead(btnOK) == LOW) {
submode++;
if (submode > 7) {
submode = 0;
}
delay(100);
lcd.clear();
}
if (submode == 0) {
lcd.setCursor(0, 0);
lcd.print(" Set Date/Time?");
lcd.setCursor(0, 1);
lcd.print("Press OK button");
}
if (submode == 1) {
lcd.setCursor(2, 0);
lcd.print("Set Month");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
M++;
if (M == 13) {
M = 1;
}
delay(100);
}
switch (M) {
case 1:
lcd.print("January ");
break;
case 2:
lcd.print("February ");
break;
case 3:
lcd.print("March ");
break;
case 4:
lcd.print("April ");
break;
case 5:
lcd.print("May ");
break;
case 6:
lcd.print("June ");
break;
case 7:
lcd.print("July ");
break;
case 8:
lcd.print("August ");
break;
case 9:
lcd.print("September ");
break;
case 10:
lcd.print("October ");
break;
case 11:
lcd.print("November ");
break;
case 12:
lcd.print("December ");
break;
}
}
if (submode == 2) {
lcd.setCursor(2, 0);
lcd.print("Set Day");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
D++;
if (D == 32) {
D = 1;
}
delay(100);
}
lcd.print(D);
lcd.print(" ");
}
if (submode == 3) {
lcd.setCursor(2, 0);
lcd.print("Set Year");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
Y++;
if (Y == 2099) {
Y = 2000;
}
delay(100);
}
lcd.print(Y);
}
if (submode == 4) {
lcd.setCursor(2, 0);
lcd.print("Set Day of the Week");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
dy++;
if (dy == 8) {
dy = 1;
}
delay(100);
}
switch (dy) {
case 1:
lcd.print("Sunday ");
break;
case 2:
lcd.print("Monday ");
break;
case 3:
lcd.print("Tuesday ");
break;
case 4:
lcd.print("Wednesday ");
break;
case 5:
lcd.print("Thursday ");
break;
case 6:
lcd.print("Friday ");
break;
case 7:
lcd.print("Saturday ");
break;
}
}
if (submode == 5) {
lcd.setCursor(2, 0);
lcd.print("Set Hour");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
h++;
if (h == 24) {
h = 0;
}
delay(100);
}
if (h > 12) {
lcd.print(h - 12);
lcd.print(" ");
} else if (h == 0) {
lcd.print("12");
lcd.print(" ");
} else {
lcd.print(h);
lcd.print(" ");
}
if (h >= 12) {
lcd.setCursor(9, 1);
lcd.print("PM");
} else {
lcd.setCursor(9, 1);
lcd.print("AM");
}
}
if (submode == 6) {
lcd.setCursor(2, 0);
lcd.print("Set Minutes");
lcd.setCursor(0, 1);
lcd.print("--> ");
if (digitalRead(btnChange) == LOW) {
m++;
if (m == 60) {
m = 0;
}
delay(100);
}
lcd.print(m);
lcd.print(" ");
}
if (submode == 7) {
lcd.setCursor(2, 0);
lcd.print("Date & Time");
lcd.setCursor(0, 1);
lcd.print("Updating......");
myRTC.setDS1302Time(00, m, h, dy, D, M, Y);
delay(200);
lcd.clear();
mode = 1;
}
}