/*
  Demo 1 – Data Logging Events With A Time Stamp
  For Instructable: Arduino Data Logging Shield With Real Time Clock Timestamp ... and Telemetry, Sensor Network
  Link: https://www.instructables.com/Arduino-Data-Logging-Shield-With-Real-Time-Clock-T/
  Youtube video demonstration: https://youtu.be/peNmbWZICIo
  By JD_K April 2023

  Uses ARduino, DS1307, microSD card reader module, digitalHall effect sensor, etc.
*/


#include <Wire.h> // the SD1307 uses I2C
#include "uRTCLib.h" // the library used for the RTC
uRTCLib rtc; // creating an instance of the RTC in the programming, something used to refer to the RTC

// For the microSD Reader
#include <SPI.h>
#include <SD.h>
int CSpin = 9;

int HallPin = 2; // the output pin from Hall Effect Sensor
volatile bool doorOpenFlag; //Hall effect sensor is HIGH/True when door open(magnet removed), so doorOpenFlag is LOW (=0) when door closed, HIGH (=1) when openned
bool prevFlag; // this flag is used to track when the doorOpenFlag changes
String doorState[2] = {"Closed", "Openned"}; // the terms of this array will be written with the time stamp using the doorOpenFlag as the index


void setup() {
  Serial.begin(9600);
  Serial.println("Ready");

  URTCLIB_WIRE.begin();
  //  rtc.set(0, 26, 1, 1, 7, 2, 21); // Uncomment and use to set the RTC time, otherwise keep this commented out so it does not reset
  //  RTCLib::set(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) // Keep this uncommented, used for reference when setting time


  // ************************************ Setup: Initiallizing the SD card Reader
  Serial.println("Initializing Card");
  pinMode(CSpin, OUTPUT);

  //Check if card is ready
  if (!SD.begin(CSpin))
  {
    Serial.println("Card Failed");
    return; //this command will end the whole sketch
  }

  Serial.println("Card Ready");

  //Write Log File Header - use a short file name otherwise it may not work
  File logFile = SD.open("datalog.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , ,"); // Just a leading blank line, in case there was previous data
    logFile.println("Month,Day,Hour,Minutes,Seconds,Door"); // Headers for the columns of data
    logFile.close();
    Serial.println("Month,Day,Hour,Minutes,Seconds,Door"); // Printing for confirmation in the Serial Monitor
  }
  else
  {
    Serial.println("Could not open command file to print header.");
    return;
  }
  // ******************************  End the SD card reader code in the setup


  // Setting up the sensor, its starting state, and attaching the correct interrupt function:
  pinMode(HallPin, INPUT);

  // Determine if the door is starting openned or closed
  if (digitalRead(HallPin) == HIGH) {
    doorOpenFlag = 1; // Open
  } else {
    doorOpenFlag = 0; // Closed
  }
  prevFlag = doorOpenFlag; // prevFlag starts the same as doorOpenFlag
  attachInterrupt(digitalPinToInterrupt(HallPin), interruptFunction, CHANGE);
}

void loop()
{

  if (doorOpenFlag != prevFlag) {
    detachInterrupt(digitalPinToInterrupt(HallPin));

    // if the sensor ever missed an openning/closing we are correcting the flag here
    if (digitalRead(HallPin) == HIGH) {
      doorOpenFlag = 1; // Open
    } else {
      doorOpenFlag = 0; // Closed
    }

    //Update time and date from RTC:
    rtc.refresh();

    //Prepare a string in CSV format so that it can then be uplaoded to the log file
    String dataString = String(rtc.month()) + "," + String(rtc.day()) + "," + String(rtc.hour()) + "," + String(rtc.minute()) + "," + String(rtc.second()) + "," + doorState[doorOpenFlag];

    //Open a file to write to. Note only one file can be open at a time
    Serial.println("Recording...");
    File logFile = SD.open("datalog.csv", FILE_WRITE); //this will open a new file if this does not exist already, or open the existing file of the same name
    if (logFile)
    {
      logFile.println(dataString);
      logFile.close();
      Serial.println(dataString);
    }
    else
    {
      Serial.println("Could not open log file to record date");
    }

    Serial.flush(); //empty the serial monitor buffer before ending
    prevFlag = doorOpenFlag; 
    attachInterrupt(digitalPinToInterrupt(HallPin), interruptFunction, CHANGE);
  } // end of the data logging


}
// End of the Loop


void interruptFunction() {
  doorOpenFlag = !doorOpenFlag;
}
