Help storing timeIn and timeOut and EEPROM

I am trying to store the timeIn and timeOut for each user every day. They need to have two timeIn and timeOut entries per day. I have tried to do this, but my Arduino keeps restarting for some reason.

Full Code:

#include <Adafruit_Fingerprint.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include "OneButton.h"
#include "uRTCLib.h"

LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial fingerSerial(2, 3);
uRTCLib rtc(0x68);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&fingerSerial);
OneButton pushButton = OneButton(A3, true, true);

int count = 1;
bool regMode = false;

String currentTime;
String currentDate;

uint8_t id;

struct FingerprintData {
  int fingerprintIds[128];
};

void (*resetFunc)(void) = 0;

void setup() {
  // put your setup code here, to run once:
  // Initialize the modules
  Serial.begin(9600);
  // Initialize the lcd
  lcd.init();
  lcd.backlight();

  displayText(false, 0, 0, F("Initializing"));
  displayText(false, 0, 1, F("Data"));

  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }

  // Initialize the fingeprint if not found then reboot the arduino

  finger.begin(57600);

  if (finger.verifyPassword()) {
    displayText(true, 0, 0, F("Fingerprint"));
    displayText(false, 1000, 1, F("Initialize"));
  } else {
    displayText(true, 0, 0, F("Fingerprint"));
    displayText(false, 1000, 1, F("Not Initialize"));
    displayText(false, 0, 0, F("Rebooting"));
    displayText(false, 1000, 1, F("System"));
    delay(1000);
    resetFunc();
    while (1) { delay(1); }
  }

  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    displayText(true, 0, 0, F("No Finger"));
    displayText(false, 2000, 1, F("Enrolled"));
  } else {
    displayText(true, 0, 0, String(finger.templateCount) + F(" Fingerprints"));
    displayText(false, 2000, 1, F("Enrolled"));
  }

  displayText(true, 0, 0, F("Attendance"));
  displayText(false, 0, 1, F("System"));

  // Button Events
  pushButton.attachClick(onSingleClick);
  pushButton.attachDoubleClick(onDoubleClick);
  pushButton.attachMultiClick(onMultiClick);
}

void loop() {
  // put your main code here, to run repeatedly:

  int result = getFingerprintIDez();

  if (result > 0) {
    displayText(true, 0, 0, F("Attendance"));
    displayText(false, 1000, 1, F("Recorded"));

    getTime();

    String studentName = getNameFromID(result);
    Serial.print(studentName.length());
    displayText(true, 0, 0, F("Welcome"));

    if (studentName.length() > 16) {
      for (int i = 0; i <= studentName.length() - 16; i++) {
        lcd.setCursor(0, 1);
        lcd.print(studentName.substring(i, i + 16));
        delay(400);  
      }
    } else {
      displayText(false, 2000, 1, studentName);
    }

    displayText(true, 0, 0, F("Attendance"));
    displayText(false, 0, 1, F("System"));
    return;
  } else if (result == -2) {
    displayText(true, 0, 0, F("Fingerprint"));
    displayText(false, 1000, 1, F("Not Enrolled"));
    displayText(true, 0, 0, F("Attendance"));
    displayText(false, 0, 1, F("System"));
    return;
  }

  pushButton.tick();
}

void storeFingerprint(int fingerprint) {
  FingerprintData data;
  int eeAddress = 0;

  EEPROM.get(eeAddress, data);

  for (int i = 0; i < 128; ++i) {
    if (data.fingerprintIds[i] == fingerprint) {
      Serial.println(F("Error: Fingerprint ID already exists!"));
      return;
    }
  }

  int i;
  for (i = 0; i < 128; ++i) {
    if (data.fingerprintIds[i] == 0) {
      data.fingerprintIds[i] = fingerprint;
      break;
    }
  }

  if (i == 128) {
    Serial.println(F("Error: No available slots to store the fingerprint ID!"));
    return;
  }

  EEPROM.put(eeAddress, data);
}

FingerprintData readFingerprints() {
  FingerprintData data;
  int eeAddress = 0;

  EEPROM.get(eeAddress, data);

  Serial.println(F("Stored Fingerprint IDs:"));
  for (int i = 0; i < 128; ++i) {
    if (data.fingerprintIds[i] != 0) {
      Serial.println(data.fingerprintIds[i]);
    }
  }

  return data;
}

String getNameFromID(int fingerprintID) {
  String studentName = "";

  if (fingerprintID == 1) {
    studentName = F("");
  } else if (fingerprintID == 2) {
    studentName = F("");
  } else if (fingerprintID == 3) {
    studentName = F("");
  } else if (fingerprintID == 4) {
    studentName = F("");
  } else if (fingerprintID == 5) {
    studentName = F("");
  } else if (fingerprintID == 6) {
    studentName = F("");
  } else if (fingerprintID == 7) {
    studentName = F("");
  } else if (fingerprintID == 8) {
    studentName = F("");
  } else if (fingerprintID == 9) {
    studentName = F("");
  } else if (fingerprintID == 10) {
    studentName = F("");
  }

  return studentName;
}

void getTime() {
  rtc.refresh();

  lcd.setCursor(0, 0);

  lcd.print(F("Time: "));

  int hour12 = rtc.hour() % 12;
  if (hour12 == 0) {
    hour12 = 12;
  }

  currentTime = String(hour12);
  currentTime += ":";

  if (rtc.minute() < 10) {
    currentTime += "0";
  }
  currentTime += String(rtc.minute());

  if (rtc.hour() < 12) {
    currentTime += " AM";
  } else {
    currentTime += " PM";
  }

  lcd.print(currentTime);

  lcd.setCursor(0, 1);
  lcd.print(F("Date: "));
  currentDate = String(rtc.month()) + "/" + rtc.day() + "/" + rtc.year();
  lcd.print(currentDate);

  delay(2000);
}


void incrementID() {
  if (regMode) {
    count++;
    if (count > 128) {
      count = 1;
    }
  }
}

void decrementID() {
  if (regMode) {
    count--;
    if (count < 1) {
      count = 1;
    }
  }
}

void centerText(int row, String text) {
  int totalColumns = 16;
  int textLength = text.length();
  int startingColumn = (totalColumns - textLength) / 2;
  lcd.setCursor(startingColumn, row);
  lcd.print(text);
}

void displayText(bool clearScreen, int duration, int row, String text) {
  if (clearScreen) {
    lcd.clear();
  }

  centerText(row, text);

  if (duration != 0) {
    delay(duration);
    lcd.clear();
  }
}

void enroll() {
  regMode = true;

  displayText(true, 0, 0, F("Enter your ID:"));

  while (regMode) {
    displayText(false, 0, 1, String(count));
    pushButton.tick();
  }
}

void confirm() {
  id = count;

  FingerprintData data = readFingerprints();

  bool idFound = false;
  for (int i = 0; i < 128; ++i) {
    if (data.fingerprintIds[i] == id) {
      idFound = true;
      break;
    }
  }

  if (idFound) {
    displayText(true, 0, 0, F("Fingerprint ID"));
    displayText(false, 2000, 1, F("Already Used"));
    displayText(true, 0, 0, F("Select Another"));
    displayText(false, 2000, 1, F("ID"));
    home();
  } else {
    displayText(true, 0, 0, F("Registering New"));
    displayText(false, 2000, 1, F("ID Fingerprint"));
    getFingerprintEnroll();
  }

  regMode = false;
}

void home() {
  regMode = false;
  count = 1;
  displayText(true, 0, 0, F("Attendance"));
  displayText(false, 0, 1, F("System"));
}

void onSingleClick() {
  incrementID();
}

void onDoubleClick() {
  decrementID();
}

void onMultiClick() {
  int n = pushButton.getNumberClicks();

  if (n == 3 && regMode) {
    // Set back to home
    home();
  }

  else if (n == 4 && !regMode) {
    // Set to regMode
    enroll();
  }

  else if (n == 5 && regMode) {
    // Enroll the user
    confirm();
  }

  else if (n == 10) {
    displayText(true, 0, 0, F("Rebooting"));
    displayText(false, 2000, 1, F("System"));
    resetFunc();
  }
}

uint8_t getFingerprintEnroll() {
  int p = -1;
  String flashString = F("Your ID: ");
  String idString = String(id);
  String combinedString = flashString + idString;
  displayText(true, 1000, 0, combinedString);
  displayText(false, 0, 0, F("Place your"));
  displayText(false, 2000, 1, F("finger"));
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        displayText(true, 0, 0, F("Image taken"));
        break;
      case FINGERPRINT_NOFINGER:
        displayText(true, 0, 0, F("No Finger"));
        displayText(false, 0, 1, F("Found"));
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        displayText(true, 0, 0, F("Communication"));
        displayText(false, 0, 1, F("Error"));
        break;
      case FINGERPRINT_IMAGEFAIL:
        displayText(true, 0, 0, F("Imaging"));
        displayText(false, 0, 1, F("Error"));
        break;
      default:
        displayText(true, 0, 0, F("Unknown"));
        displayText(false, 0, 1, F("Error"));
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      displayText(true, 0, 0, F("Image"));
      displayText(false, 0, 1, F("Converted"));
      break;
    case FINGERPRINT_IMAGEMESS:
      displayText(true, 0, 0, F("Image"));
      displayText(false, 0, 1, F("Too Messy"));
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      displayText(true, 0, 0, F("Communication"));
      displayText(false, 0, 1, F("Error"));
      return p;
    case FINGERPRINT_FEATUREFAIL:
      displayText(true, 0, 0, F("Feature"));
      displayText(false, 0, 1, F("Not Found"));
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      displayText(true, 0, 0, F("Feature"));
      displayText(false, 0, 1, F("Not Found"));
      return p;
    default:
      displayText(true, 0, 0, F("Unknown"));
      displayText(false, 0, 1, F("Error"));
      return p;
  }

  displayText(true, 0, 0, F("Remove your"));
  displayText(false, 2000, 1, F("finger"));
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  p = -1;
  displayText(true, 0, 0, F("Place your"));
  displayText(false, 0, 1, F("Finger Again"));
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println(F("Image taken"));
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(F("."));
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println(F("Communication error"));
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println(F("Imaging error"));
        break;
      default:
        Serial.println(F("Unknown error"));
        return;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println(F("Image converted"));
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println(F("Image too messy"));
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println(F("Communication error"));
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println(F("Could not find fingerprint features"));
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println(F("Could not find fingerprint features"));
      return p;
    default:
      Serial.println(F("Unknown error"));
      return p;
  }

  // OK converted!
  Serial.print(F("Creating model for #"));
  Serial.println(id);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println(F("Prints matched!"));
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println(F("Communication error"));
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println(F("Fingerprints did not match"));
    return p;
  } else {
    Serial.println(F("Unknown error"));
    return p;
  }

  Serial.print(F("ID "));
  Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    storeFingerprint(id);
    displayText(true, 0, 0, F("Your Fingerprint"));
    displayText(false, 2000, 1, F("ID is Stored"));
    id = 1;
    count = 1;
    displayText(false, 0, 0, F("Registering"));
    displayText(false, 1000, 1, F("Data"));
    resetFunc();
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println(F("Communication error"));
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println(F("Could not store in that location"));
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println(F("Error writing to flash"));
    return p;
  } else {
    Serial.println(F("Unknown error"));
    return p;
  }
}

uint8_t getimg_data[] = { FINGERPRINT_GETIMAGE };
#define FINGERPRINT_COMMANDPACKET 0x1  //!< Command packet
Adafruit_Fingerprint_Packet packet(FINGERPRINT_COMMANDPACKET, sizeof(getimg_data), getimg_data);
const Adafruit_Fingerprint_Packet startPacket(FINGERPRINT_COMMANDPACKET, sizeof(getimg_data), getimg_data);
bool is_waiting_for_response = false;

int better_get_image() {
  // Serial.println("Get better image()");
  if (!is_waiting_for_response) {
    packet = startPacket;
    finger.writeStructuredPacket(packet);
    is_waiting_for_response = true;
    // Serial.println("Send command packet");
    return -2;  // nothing yet! :)
  } else {
    /* check if there is any serial data at all */
    if (fingerSerial.available() == 0) {
      /* FAST EXIT TO MAKE BUTTON WORK */
      return -2;
    }
    // Serial.println("Got response");
    // we definitely have some amount of data now, read it
    if (finger.getStructuredPacket(&packet) != FINGERPRINT_OK) {
      is_waiting_for_response = false;
      return FINGERPRINT_PACKETRECIEVEERR;
    }
    // we have received something, so evaluate the result in all cases
    is_waiting_for_response = false;
    if (packet.type != FINGERPRINT_ACKPACKET)
      return FINGERPRINT_PACKETRECIEVEERR;
    return packet.data[0];
  }
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = better_get_image();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    return finger.fingerID;
  } else if (p == FINGERPRINT_NOTFOUND) {
    return -2;
  } else {
    return -1;
  }
}

The code that keeps resetting the arduino when the function is called

struct FingerprintData {
  int fingerprintIds[128];
  String timeIn[128];
  String timeOut[128];
};

String getTimeIn(int fingerprint) {
  Serial.print(String(fingerprint));
  
  delay(2000);
  FingerprintData data;
  int eeAddress = 0;
  EEPROM.get(eeAddress, data);
  for (int i = 0; i < 128; ++i) {
    if (data.fingerprintIds[i] == fingerprint) {
      Serial.print(String(data.timeIn[i]));
      return data.timeIn[i];
    }
  }
  return "";
}

When called in loop and setup it resets the Arduino
getTimeIn(1);

Welcome to the forum, and congratulations on posting your code correctly.

I notice that you are confused about the break command.

This is a function that is declared as returning a bool type variable, where as in fact it doesn't return anything.
Not sure if you want to actually want / need just a found flag. Would it not be more useful to return the number where you found the id? Then your code could look at the number and if it was 128 then you could assume no match?

Also you can't return anything from a switch statement, each case must end in a break, otherwise the code will go in to do the next case.

Why are you trying to use Strings to store this information?

what method should I use?

Break the time into a number of bytes and store each byte in EEPROM.

Can you provide an example of how to do it? Should I store it like I do with fingerprint IDs?

We need to know what is providing you with a time signal and what resolution you want the time to be kept at. For example are you requiring what second or something more coarse.

I just need to store the time in the format of hour and minute, for example, 7:48 which means 7 hours and 48 minutes. However, I plan to clear the stored data after 6 pm and then send the data through SMS. The SMS format should be as follows:

Morning
Time In:
Time Out:
Afternoon
Time In:
Time Out:

Hours of time in is one byte.
Minutes of time in is one byte.
Hours of time out is one byte.
Minutes of time out is one byte.
That is 4 bytes total for one pair of in/out times.
For 2 pairs of in/out times (which is what you say you want), that will be 8 bytes total.

int fingerprintIds[128];
That is a lot of IDs.
Do you really have 128 IDs to deal with?
Each ID will need 10 bytes of EEPROM: 2 bytes for the ID data, plus 8 bytes for the time in/out data as we have seen.
128 IDs times 10 bytes of EEPROM per ID is 1280 bytes.
Do you have 1280 bytes of EEPROM available? If you don't, then you have a problem.

Instead of saving the time I thought about just sending it through sms when they do attendance but how do I make it so they can only time in and time out once only in the morning and in the afternoon?

The class has only 40 students it's not 128 I'm going to change once I've deployed it

To that I can only say:

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