#include <Wire.h>
#include <RTClib.h>
#include <SD.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <EEPROM.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
#define CS_PIN 5
#define TMP_PIN 34
#define TRG_PIN 15
#define SPRK_PIN 14
#define SCL_PIN 32
#define SCA_PIN 33
#define ledRED 4
#define ledGREEN 0
RTC_DS1307 rtc;
String oldDate;
String nowDate;
char *nowTime;
unsigned long tmrTotal, tmrSumTotal;
time_t tmStart, tmStop;
char *logFileName = "/wokwi.txt";
File logFile;
bool rtcInitialized = true;
bool sdcInitialized = true;
bool tmpInitialized = true;
bool initComplete = true;
int tempValue = 30;
const float BETA = 3950; // should match the Beta Coefficient of the thermistor
float tempCelcius;
int i;
int acOnStatus = HIGH;
String acOnDate;
char daysOfTheWeek[7][12] = {
"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"};
const char monthName[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
enum {
ledOFF = 0,
ledON = 1,
ledBLINK = 2,
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
Wire.begin(SCA_PIN, SCL_PIN);
Serial.print("Initializing LCD Monitor... ");
lcd.init();
lcd.backlight();
lcd.noDisplay(); delay(10);
lcd.display(); delay(10);
Serial.println("done."); delay(1000);
Serial.print("Initializing RTC... ");
showLCD("RTC","Initializing RTC... ");
if (! rtc.begin()) {
Serial.println("failed!");
showLCD("RTC","failed!");
rtcInitialized = false;
initComplete = false;
}
else{ Serial.println("successful!"); showLCD("RTC","successful!"); }
delay(1000);
if(rtcInitialized==true){
Serial.print("Date : "); showDateOnSerial(rtc); Serial.println("");
//nowDate = getDate(rtc);
showLCD("DATE",&getDate(rtc)[0]); delay(500);
Serial.print("Time : "); showTimeOnSerial(rtc); Serial.println("");
//showLCD("TIME",&getTime(rtc)[0]); delay(500);
}
Serial.print("Initializing SD card... ");
if (!SD.begin(CS_PIN)) {
Serial.println("failed!");
sdcInitialized = false;
initComplete = false;
}
else{ Serial.println("successful!"); }
delay(1000);
Serial.print("Initializing Temperature Sensor... ");
tempValue = analogRead(TMP_PIN);
//Serial.println(tempValue);
if (tempValue==0) {
Serial.println("failed!");
tmpInitialized = false;
initComplete = false;
}
else{ Serial.println("successful!"); }
delay(1000);
if(tmpInitialized==true){
Serial.print("Temp : "); Serial.print(tempValue); Serial.println("");
}
Serial.print("Initializing Trigger Pin... ");
pinMode(TRG_PIN, INPUT_PULLUP);
Serial.println("successful!");
delay(1000);
Serial.print("Initializing LED pins... ");
pinMode(ledRED, OUTPUT);
pinMode(ledGREEN, OUTPUT);
ledOP(ledRED, ledBLINK);
ledOP(ledGREEN, ledBLINK);
Serial.println("successful!");
delay(1000);
Serial.print("Initializing SPEAKER pin... ");
pinMode(SPRK_PIN, OUTPUT);
//feedBack(1,1, ledGREEN);
Serial.println("successful!");
delay(1000);
if(initComplete == false){
Serial.println("Initialization failed! Suspending system.");
feedBack(2,1,ledGREEN );
while(true);
}
else{
Serial.println("Initialization complete! Starting system...");
feedBack(1,1, ledGREEN);
Serial.println("Lock and loaded."); delay(1000);
}
}
void loop() {
// put your main code here, to run repeatedly:
//if(!digitalRead(TRG_PIN)){
// tempValue = analogRead(TMP_PIN);
// showTempInC(tempValue);
// logRead(); delay(300);
//}
int acOn = digitalRead(TRG_PIN);
if(acOn!=acOnStatus){
acOnStatus=acOn;
if(acOn==LOW) {
logRead();
acOnDate = "Start: ";
acOnDate = acOnDate + getDate(rtc) + " " + getTime(rtc, tmStart) + " ";
}
else {
acOnDate = "End: ";
acOnDate = acOnDate + getDate(rtc) + " " + getTime(rtc, tmStop) + " ";
delay(500);
int32_t upTimeLong = getUpTime(tmStart, tmStop);
String upTime = strUpTime(getUpTime(tmStart, tmStop));
showUpTime(getUpTime(tmStart, tmStop));
long upTotalTime = EEPROMReadlong(0);
upTotalTime = upTotalTime + upTimeLong;
EEPROMWritelong(0, upTotalTime);
Serial.print("Total time: ");
Serial.println(upTotalTime);
// int32_t diff = tmStop - tmStart;
// uint32_t hours = diff / 3600;
// uint8_t minutes = (diff / 60) % 60;
// uint8_t seconds = diff % 60;
// Serial.print( "Total operation: " );
// Serial.print( hours );
// Serial.print( " hour(s), " );
// Serial.print( minutes );
// Serial.print( " minute(s) and " );
// Serial.print( seconds );
// Serial.println( " second(s)." );
}
//acOnDate = acOnDate + getDate(rtc) + " " + getTime(rtc, tmStart) + " ";
appendFile(SD, logFileName, acOnDate);
Serial.println(acOnDate);
delay(100);
//if(acOn==HIGH) acOnStatus=HIGH;
}
//tempCelcius = 1 / (log(1 / (4095. / tempValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
//Serial.print("Temperature Value : "); Serial.println(tempValue);
//Serial.print("Celcius Value : "); Serial.println(tempCelcius);
// if(tmpInitialized==true){
// Serial.print("Temp : "); Serial.print(tempValue); Serial.println("");
//}
delay(100); // this speeds up the simulation
}
//----- SPEAKER Function -----
void feedBack(int numCase, int numBlink, int pinName)
{
//all frequencies in Hz
//#define NOTE_G3 196
//#define NOTE_C4 262
//#define NOTE_G4 392
unsigned int beepFreq = 262; //frequency of initial feedback beep
unsigned int beepHigh = 392; //ascending 2nd beep
unsigned int beepLow = 131; //descending 2nd beep
unsigned int beepTime = 250; //duration of feedback beeps
unsigned int beepDly = 350; //time between feedback beeps
//LED timing
unsigned int ledON = 250; //feedback LED time on
unsigned int ledOFF = 200; //and off
int z;
switch (numCase) {//test for desired feedback
case 1:// success
tone(SPRK_PIN, beepFreq, beepTime); //output tone
delay(beepDly);
noTone(SPRK_PIN);
tone(SPRK_PIN, beepHigh, beepTime);
delay(beepDly);
noTone(SPRK_PIN);
//blink the required number of times
for (z = 0 ; z < numBlink ; z++) {
digitalWrite(pinName, HIGH);
delay(ledON);
digitalWrite(pinName, LOW);
delay(ledOFF);
}
break;
case 2://operation failed - try again
tone(SPRK_PIN, beepHigh, beepTime*2); //high tone
delay(beepDly*2.5);
noTone(SPRK_PIN);
tone(SPRK_PIN, beepLow, beepTime*2);//low tone
delay(beepDly*2.5);
noTone(SPRK_PIN);
tone(SPRK_PIN, beepHigh, beepTime*2); //high tone
delay(beepDly*2.5);
noTone(SPRK_PIN);
for (z = 0 ; z < numBlink ; z++) {
digitalWrite(pinName, HIGH);
delay(ledON);
digitalWrite(pinName, LOW);
delay(ledOFF);
}
break;
// case 3: //audible feedback during pause mode
// if (ms - pauseModeBeep > pauseBeepTime) {
// tone(5, beepLow, beepTime); //output tone
// delay(beepDly);
// noTone(5);
// tone(5, beepLow, beepTime);
// delay(beepDly);
// noTone(5);
// pauseModeBeep = ms; //update
// }
// break;
}//end of switch (numCase)
}//end of feedBack
//----- LED Function -----
void ledOP(int pinNo, int ledStatus){
if(ledStatus==ledOFF) digitalWrite(pinNo, LOW);
if(ledStatus==ledON) digitalWrite(pinNo, HIGH);
if(ledStatus==ledBLINK){
digitalWrite(pinNo, HIGH); delay(500);
digitalWrite(pinNo, LOW); delay(500);
}
}
//----- LCD Functions -----
void showLCD(char *title, char *msg){
lcd.clear();
lcd.setCursor(8-getCenter(title), 0);
lcd.print(title);
lcd.setCursor(8-getCenter(msg), 1);
lcd.print(msg);
}
int getCenter(char *msg){
return strlen(msg)/2;
}
//----- RTC Functions -----
String getDate(RTC_DS1307 sRTC)
{
String dateNow;
DateTime now;
now = sRTC.now();
dateNow = String(now.month(),DEC) + "/";
dateNow = dateNow + String(now.day(),DEC) + "/";
dateNow = dateNow + String(now.year(),DEC);
return dateNow;
}
String getTime(RTC_DS1307 sRTC, time_t &TSec)
{
String timeNow, AmPm;
int hr;
DateTime now;
tmElements_t T1;
now = sRTC.now();
T1.Hour = now.hour();
T1.Minute = now.minute();
T1.Second = now.second();
T1.Day = now.day();
T1.Month = now.month();
T1.Year = now.year() - 1970;
TSec = makeTime( T1 );
hr = now.hour();
AmPm = (hr< 13 ) ? "AM" : "PM";
if(hr%12==0) hr = 12;
//timeNow = String(now.hour(),DEC) + ":";
timeNow = String(hr,DEC) + ":";
timeNow = timeNow + String(now.minute(),DEC) + ":";
timeNow = timeNow + String(now.second(),DEC) + " " + AmPm;
return timeNow;
}
int32_t getUpTime(time_t timeStart, time_t timeStop)
{
return timeStop - timeStart;
}
String strUpTime(int32_t diff)
{
uint32_t hours = diff / 3600;
uint8_t minutes = (diff / 60) % 60;
uint8_t seconds = diff % 60;
String upTime;
upTime = hours + " hour(s), ";
upTime = upTime + minutes + " minute(s) and ";
upTime = upTime + seconds + " second(s).";
return upTime;
}
void showUpTime(int32_t diff)
{ Serial.println( "Total operation: " + strUpTime(diff) ); }
void showDateOnSerial(RTC_DS1307 sRTC)
{
String dateNow;
DateTime now;
now = sRTC.now();
dateNow = String(now.month(),DEC) + "/";
dateNow = dateNow + String(now.day(),DEC) + "/";
dateNow = dateNow + String(now.year(),DEC);
Serial.print(dateNow);
}
void showTimeOnSerial(RTC_DS1307 sRTC)
{
String timeNow, AmPm;
int hr;
DateTime now;
now = sRTC.now();
hr = now.hour();
AmPm = (hr< 13 ) ? "AM" : "PM";
if(hr%12==0) hr = 12;
timeNow = String(hr,DEC) + ":";
timeNow = timeNow + String(now.minute(),DEC) + ":";
timeNow = timeNow + String(now.second(),DEC) + " " + AmPm;
Serial.print(timeNow);
}
//----- Temperature Sensor Functions -----
void showTempInC(int tempReading)
{
Serial.print("Celcius : "); Serial.println(convTempToC(tempReading));
}
float convTempToC(int tempReading)
{
float convTemp;
convTemp = 1 / (log(1 / (4095. / tempReading - 1)) / BETA + 1.0 / 298.15) - 273.15;
return convTemp;
}
//----- SD Card Functions -----
int IsLogFileExist()
{
return SD.exists(logFileName);
};
void logCreateFile()
{
int logFile;
Serial.println("Creating new file log... ");
logFile = SD.open(logFileName, FILE_WRITE);
if (logFile) { Serial.println(" successful. "); }
else { Serial.println("failed!"); }
};
void logWrite(String logText)
{
logFile = SD.open(logFileName, FILE_WRITE);
Serial.print("Writing to file: ");
Serial.println(logFileName);
//logFile.write(logText, sizeof(logText));
//logFile.write("Hello there.");
logFile.println(logText);
logFile.close();
Serial.println("Log write successful...");
Serial.println("");
};
void logRead()
{
logFile = SD.open(logFileName);
Serial.print("Reading file: ");
Serial.println(logFileName);
if(logFile.available()){
while (logFile.available()) {
Serial.write(logFile.read());
}
}
else{
Serial.println("Nothing to read.");
}
Serial.println("");
logFile.close();
};
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void appendFile(fs::FS &fs, const char * path, String message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
//----- EEProm Functions -----
long EEPROMReadlong(long address) {
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
};
void EEPROMWritelong(int address, long value) {
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
EEPROM.commit();
};