This project uses an MC522 RFID, RTC DS1302, sd reader/writer, buzzer, button and lcd i2c.
#include <MFRC522.h>
#include <Wire.h>
#include <ThreeWire.h>
#include <LiquidCrystal_I2C.h>
#include <RtcDS1302.h>
#include <SD.h>
// Definiciones de pines
#define RST_PIN 9
#define SS_PIN 10
#define button 2
#define buzzerPin 3
#define cspin 4
// Variables globales
byte valueButton = 1;
byte minutoA, minuto, mesA, mes, diaA, dia, horaA, hora;
int aA, a;
byte stateButton = 0;
unsigned long tx = 0;
unsigned long timepassed;
bool cardRead = false;
String cardValue;
char uidBuffer[4];
byte lengthU;
int toRun;
String copy = "";
// Objetos para periféricos
LiquidCrystal_I2C lcd(0x27, 16, 2);
ThreeWire myWire(6, 5, 7);
RtcDS1302<ThreeWire> Rtc(myWire);
MFRC522 mfrc522(SS_PIN, RST_PIN);
// Archivos
File usuarios, registro, entraron, file;
String fileF = "FILE.TXT";
String entraronF = "ENTRARON.TXT";
String usuariosF = "USUARIOS.TXT";
String registroF = "REGISTRO.TXT";
void setup() {
Serial.begin(9600);
pinMode(cspin, OUTPUT);
digitalWrite(cspin, HIGH);
pinMode(buzzerPin, OUTPUT);
pinMode(button, INPUT_PULLUP);
lcd.begin(16, 2);
lcd.backlight();
Rtc.Begin();
//Config for RTC
/*RtcDateTime currentTime = RtcDateTime(__DATE__ , __TIME__);
Rtc.SetDateTime(currentTime);
*/
SPI.begin();
mfrc522.PCD_Init();
// Inicializar la tarjeta SD
if (!SD.begin(cspin)) {
Serial.println(F("Error initializing SD card."));
displayMessage("Error iniciando", "tarjeta SD");
while(1){}
}
Serial.println(F("SD card initialized successfully."));
// Esperar para iniciar la comunicación Serial
while (!Serial);
mfrc522.PCD_DumpVersionToSerial();
Serial.println(F("Comunicaión Serial iniciada"));
if (!SD.exists(usuariosF)) {
usuarios = SD.open(usuariosF, FILE_WRITE);
usuarios.close();
Serial.println(F("usuariosF ha sido creado"));
} else {
Serial.println(F("usuariosF ya existe"));
}
// Verificar si el archivo "registroF" existe y crearlo si no existe
if (!SD.exists(registroF)) {
registro = SD.open(registroF, FILE_WRITE);
registro.close();
Serial.println(F("registroF ha sido creado"));
} else {
Serial.println(F("registroF ya existe"));
}
// Verificar si el archivo "entraronF" existe y crearlo si no existe
if (!SD.exists(entraronF)) {
entraron = SD.open(entraronF, FILE_WRITE);
entraron.close();
Serial.println(F("entraronF ha sido creado"));
} else {
Serial.println(F("entraronF ya existe"));
}
}
void loop() {
timepassed = millis();
registerButton();
clock();
mainProcess();
}
void clock() {
// Obtener la fecha y hora actual del RTC
RtcDateTime now = Rtc.GetDateTime();
// Obtener los componentes de fecha y hora
aA = now.Year();
mesA = now.Month();
diaA = now.Day();
horaA = now.Hour();
minutoA = now.Minute();
setMillis(100);
// Actualizar los componentes de fecha y hora
a = now.Year();
mes = now.Month();
dia = now.Day();
hora = now.Hour();
minuto = now.Minute();
// Mostrar "Colocar tarjeta" en la primera línea del LCD
lcd.setCursor(0, 0);
lcd.print("Colocar tarjeta");
// Mostrar la fecha y hora en la segunda línea del LCD
lcd.setCursor(0, 1);
printDoubleDigit(dia);
lcd.print("/");
printDoubleDigit(mes);
lcd.print("/");
lcd.print(a);
lcd.print("|");
printDoubleDigit(hora);
lcd.print(":");
printDoubleDigit(minuto);
// Actualizar la pantalla solo si hay cambios en la fecha o hora
if ((minutoA != minuto) || (horaA != hora) || (diaA != dia) || (mesA != mes) || (aA != a)) {
lcd.setCursor(0, 1);
printDoubleDigit(dia);
lcd.print("/");
printDoubleDigit(mes);
lcd.print("/");
lcd.print(a);
lcd.print("|");
printDoubleDigit(hora);
lcd.print(":");
printDoubleDigit(minuto);
}
}
// Función para imprimir un número de dos dígitos
void printDoubleDigit(int number) {
if (number < 10) {
lcd.print("0");
}
lcd.print(number);
}
void mainProcess() {
// Verificar si hay una nueva tarjeta presente en el lector
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Leer el serial de la tarjeta
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Inicializar la variable cardValue para almacenar el UID
cardValue = "";
// Leer el UID de la tarjeta y almacenarlo en cardValue
for (byte i = 0; i < mfrc522.uid.size; i++) {
// Formatear el valor hexadecimal y almacenarlo en el búfer
sprintf(uidBuffer, "%02X", mfrc522.uid.uidByte[i]);
// Concatenar el valor del búfer en la variable cardValue
cardValue += uidBuffer;
}
// Imprimir el valor del UID en el Serial Plotter
serialP(cardValue);
// Verificar si la tarjeta está registrada
if (ifIsRegister(cardValue)) {
ifIsAlreadyIn(cardValue); // Verificar si el usuario ya está adentro
// Mostrar mensajes en la pantalla y hacer sonidos apropiados
entryRegis(cardValue);
} else {
// Mostrar mensajes en la pantalla y hacer sonidos apropiados
lcd.noDisplay();
lcd.clear();
setMillis(100);
lcd.display();
displayMessage("No registrado", "");
buzzerTone(250, 1000, 0);
lcd.noDisplay();
lcd.clear();
lcd.display();
displayMessage("Para registrarte", "Apreta el boton");
setMillis(1000);
lcd.noDisplay();
lcd.clear();
setMillis(100);
lcd.display();
clock();
}
// Limpiar el valor de la tarjeta para la siguiente lectura
cardValue = "";
mfrc522.PICC_HaltA(); // Finalizar la comunicación con la tarjeta
}
void registerButton() {
valueButton = digitalRead(button); // Leer si el botón está pulsado
// Si el botón está presionado
if (valueButton == LOW) {
stateButton = 1;
cardRead = false;
// Mostrar mensaje en la pantalla para colocar la tarjeta
displayMessage("Colocar tarjeta", "Para registrarse");
tx = millis(); // Guardar el tiempo actual en 'tx'
// Esperar hasta que se cumpla el tiempo de registro o se lea una tarjeta
while (millis() - tx < 10000) {
toRegis();
// Si se leyó una tarjeta, actualizar la hora en la pantalla y salir del bucle
if (cardRead == true) {
clock();
break;
}
}
}
}
void toRegis() {
if (cardRead) {
return;
}
// Verificar si hay una nueva tarjeta presente en el lector
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Leer el serial de la tarjeta
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Inicializar la variable cardValue para almacenar el UID
cardValue = "";
// Leer el UID de la tarjeta y almacenarlo en cardValue
for (byte i = 0; i < mfrc522.uid.size; i++) {
// Formatear el valor hexadecimal y almacenarlo en el búfer
sprintf(uidBuffer, "%02X", mfrc522.uid.uidByte[i]);
// Concatenar el valor del búfer en la variable cardValue
cardValue += uidBuffer;
}
// Imprimir el valor del UID en el Serial Plotter
serialP(cardValue);
// Verificar si la tarjeta está registrada
if (ifIsRegister(cardValue)) {
displayMessage("Ya estás", "registrado");
setMillis(1000);
displayMessage("Inténtalo", "nuevamente");
buzzerTone(250, 250, 0);
cardRead = false;
return; // Salir de la función si la tarjeta ya está registrada
}
// Mostrar mensaje en la pantalla y hacer sonidos apropiados
displayMessage("Registrando", "...");
toRegister(cardValue);
setMillis(1000);
displayMessage("Has sido", "registrado");
buzzerTone(500, 1000, 1);
cardRead = true;
cardValue = "";
}
void setMillis(int wantedTime) {
tx = millis(); // Guardar el tiempo actual en 'tx'
// Esperar hasta que haya pasado el tiempo deseado
while (millis() - tx < wantedTime) {
// No se hace nada, simplemente se espera
}
}
void buzzerTone(int t1, int t2, int mode){
digitalWrite(buzzerPin, HIGH);
setMillis(t1);
digitalWrite(buzzerPin, LOW);
if (mode == 0) {
setMillis(t1);
digitalWrite(buzzerPin, HIGH);
setMillis(t1);
digitalWrite(buzzerPin, LOW);
}
setMillis(t2);
}
void displayMessage(const char* line1, const char* line2) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
}
void toRegister(String uid) {
// Cerrar el archivo antes de abrirlo nuevamente
usuarios.close();
setMillis(100);
// Abre el archivo en modo escritura
usuarios = SD.open(usuariosF, FILE_WRITE);
setMillis(100);
if (usuarios) {
usuarios.print(uid); // Escribe el UID en el archivo
usuarios.print(",");
usuarios.flush(); // Verificar que ningún dato quedó a medio camino
usuarios.close(); // Cierra el archivo después de escribirlo
Serial.println(F("Datos escritos en el archivo correctamente."));
} else {
Serial.println(F("Error al abrir el archivo para escritura."));
}
}
bool ifIsRegister(String user) {
usuarios.close();
setMillis(100);
// Abre el archivo en modo lectura
usuarios = SD.open(usuariosF, FILE_READ);
setMillis(100);
if (usuarios) {
String verifyUser;
char nextCharacter;
while (usuarios.available()) {
nextCharacter = usuarios.read();
if (nextCharacter == ',') {
if (verifyUser == user) {
usuarios.close();
return true;
}
verifyUser = ""; // Limpiar la cadena para el siguiente UID
} else {
verifyUser += nextCharacter; // Agregar el caracter leído al UID temporal
}
}
// Verificar el último UID al final del archivo
if (verifyUser == user) {
usuarios.close();
return true;
}
usuarios.close();
}
return false; // El archivo no se pudo abrir o el usuario no está registrado
}
void serialP(String message){
Serial.println(message);
}
void entryRegis(String uid) {
RtcDateTime now = Rtc.GetDateTime();
a = now.Year();
mes = now.Month();
dia = now.Day();
hora = now.Hour();
minuto = now.Minute();
String completeTime = String(hora) + ":" + String(minuto) + " " + String(dia) + "|" + String(mes) + "|" + String(a);
Serial.println(completeTime);
registro.close();
setMillis(100);
registro = SD.open(registroF, FILE_WRITE);
setMillis(100);
if (registro) {
registro.print(uid); // Escribe el UID en el archivo
registro.print(" ");
registro.print(completeTime); // Agrega la fecha y hora al registro
registro.print(","); // Agrega una coma para separar los UID
registro.flush(); // Verificar que ningún dato quedó a medio camino
registro.close(); // Cierra el archivo después de escribirlo
Serial.println(F("Datos escritos en el archivo correctamente."));
} else {
Serial.println(F("Error al abrir el archivo para escritura."));
}
}
void ifIsAlreadyIn(String user) {
entraron.close();
setMillis(100);
entraron = SD.open(entraronF, FILE_READ);
setMillis(100);
if (entraron) {
String verifyUser;
char nextCharacter;
lengthU = user.length()-1;
while (entraron.available()) {
nextCharacter = entraron.read();
toRun = lengthU + entraron.position();
if (nextCharacter == ',') {
if (verifyUser == user) {
entraron.flush();
entraron.close();
setMillis(100);
removeText(lengthU, toRun);
displayMessage("Hasta luego,", "nos vemos!!");
buzzerTone(350, 750, 0);
entraron.flush();
entraron.close();
}
verifyUser = "";
} else {
verifyUser += nextCharacter;
}
}
// Verificar el último UID al final del archivo
if (verifyUser == user) {
entraron.close();
removeText(lengthU, toRun);
displayMessage("Hasta luego,", "nos vemos!!");
buzzerTone(350, 750, 0);
}
entraron.close();
}
addUser(cardValue);
displayMessage("Bienvenido!!", "de vuelta");
buzzerTone(500, 1000, 1);
}
void removeText(int num, int lenghtNum){
if (!SD.exists(fileF)) {
file = SD.open(fileF, FILE_WRITE);
file.close();
Serial.println(F("fileF ha sido creado"));
} else {
Serial.println(F("fileF ya existe"));
}
entraron.close();
setMillis(100);
entraron = SD.open(entraronF, FILE_READ);
file = SD.open(fileF, FILE_WRITE);
setMillis(100);
entraron.seek(0);
while (entraron.available()){
int actualPos = entraron.position();
entraron.seek(actualPos);
if(actualPos < num || actualPos > lenghtNum+1){
copy = entraron.read();
file.print(copy);
} else if(copy == " ") {
return;
} else {
actualPos++;
}
}
entraron.flush();
entraron.close();
file.flush();
file.close();
entraron = SD.open(entraronF, FILE_WRITE);
file = SD.open(fileF, FILE_READ);
while(file.available()){
copy = file.read();
entraron.print(copy);
if(copy == " ") {
return;
}
}
entraron.flush();
entraron.close();
file.flush();
file.close();
SD.remove("FILE.TXT");
Serial.print(F("Text removed"));
}
void addUser(String user){
entraron.close();
setMillis(100);
entraron = SD.open(entraronF, FILE_WRITE);
setMillis(100);
entraron.print(user);
entraron.print(",");
entraron.flush();
entraron.close();
Serial.println(user);
Serial.print(F("User added"));
}
The code appears to be flawless, but it consumes too many resources. Can you give me a hand, to improve its structure or optimization? I know that i can use an arduino mega, but as you note if i writing this i dont have one of this. Thanks a lot, if you need another thing please say it to me.
