RFID deja de leer después de un tiempo

Como muchos soy nuevo en el tema de los micro controladores uso un ESP32 con RFID522, LCD 16x2 I2C, cuando inicio lee perfectamente las tarjetas tanto validas como invalidas si lee seguido funciona bien pero si dejo de leer un min deja de leer hasta que descnonecto de la energía y vuelvo a conectar después de un rato y así es repetidamente

#include <WiFi.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define SS_PIN 5
#define RST_PIN 22
#define LED_VERDE 14
#define LED_ROJO 12
#define BUZZER 27

const char* ssid = "xxxxxx";
const char* password = "xxxxxxxx";
const String serverUrl = "http://xxxxxxxxx/control_acceso/validar_rfid.php";

MFRC522 rfid(SS_PIN, RST_PIN);
LiquidCrystal_I2C lcd(0x27, 16, 2);

// 🕒 Control de inactividad
unsigned long ultimoTiempoLectura = 0;
const unsigned long TIEMPO_MAX_INACTIVIDAD = 30000; // 30 segundos

void setup() {
  Serial.begin(115200);
  SPI.begin();
  rfid.PCD_Init();

  Wire.begin(25, 26);  // Pines SDA, SCL
  lcd.init();
  lcd.backlight();

  pinMode(LED_VERDE, OUTPUT);
  pinMode(LED_ROJO, OUTPUT);
  pinMode(BUZZER, OUTPUT);

  lcd.setCursor(0, 0);
  lcd.print("Conectando WiFi");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("WiFi conectado");
  delay(1000);
  lcd.clear();
  lcd.print("Acerque tarjeta");

  ultimoTiempoLectura = millis(); // iniciar contador
}

void loop() {
  // 🛜 Reconexión WiFi cada 10s si se perdió
  if (millis() % 10000 < 50 && WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
  }

  // 🕒 Reinicio RFID si lleva mucho tiempo sin leer
  if (millis() - ultimoTiempoLectura > TIEMPO_MAX_INACTIVIDAD) {
    Serial.println("Reiniciando lector RFID por inactividad...");
    rfid.PCD_Init();
    ultimoTiempoLectura = millis();
  }

  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;

  ultimoTiempoLectura = millis(); // reiniciar contador al leer

  String uid = getUID(rfid.uid.uidByte, rfid.uid.size);
  Serial.println("UID detectado: " + uid);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("UID:");
  lcd.setCursor(0, 1);
  lcd.print(uid);
  delay(1000);

  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverUrl);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    String postData = "uid=" + uid;
    http.setTimeout(3000); // 3s timeout

    int httpResponseCode = http.POST(postData);
    String payload = http.getString();

    lcd.clear();
    String nombre = "";

    if (httpResponseCode == 200) {
      if (payload.startsWith("VAL:")) {
        nombre = payload.substring(4);
        nombre = limpiarAcentos(nombre);

        lcd.setCursor(0, 0);
        lcd.print("ACCESO PERMITIDO");
        digitalWrite(LED_VERDE, HIGH);
        tone(BUZZER, 1000, 200);
        mostrarNombreScroll(nombre);
      } else {
        lcd.setCursor(0, 0);
        lcd.print("NO REGISTRADA");
        digitalWrite(LED_ROJO, HIGH);
        tone(BUZZER, 300, 400);
        lcd.setCursor(0, 1);
        lcd.print("UID: " + uid);
      }
    } else {
      lcd.print("ERROR HTTP");
      Serial.println("Error HTTP: " + String(httpResponseCode));
    }

    delay(300);
    digitalWrite(LED_VERDE, LOW);
    digitalWrite(LED_ROJO, LOW);
    noTone(BUZZER);
    lcd.clear();
    lcd.print("Acerque tarjeta");

    http.end();
  }

  rfid.PICC_HaltA();
 // rfid.PCD_StopCrypto1(); // Detener el cifrado en PCD
}

String getUID(byte *buffer, byte bufferSize) {
  unsigned long uidDecimal = 0;
  for (byte i = 0; i < bufferSize; i++) {
    uidDecimal = (uidDecimal << 8) | buffer[i];
  }
  char uidStr[11];
  sprintf(uidStr, "%010lu", uidDecimal);  // Siempre 10 dígitos
  return String(uidStr);
}

void mostrarNombreScroll(String texto) {
  int len = texto.length();
  if (len <= 16) {
    lcd.setCursor(0, 1);
    lcd.print(texto);
  } else {
    for (int i = 0; i <= len - 16; i++) {
      lcd.setCursor(0, 1);
      lcd.print(texto.substring(i, i + 16));
      delay(300);
    }
    delay(800); // pausa final
  }
}

String limpiarAcentos(String texto) {
  texto.replace("á", "a");
  texto.replace("é", "e");
  texto.replace("í", "i");
  texto.replace("ó", "o");
  texto.replace("ú", "u");
  texto.replace("Á", "A");
  texto.replace("É", "E");
  texto.replace("Í", "I");
  texto.replace("Ó", "O");
  texto.replace("Ú", "U");
  texto.replace("ñ", "n");
  texto.replace("Ñ", "N");
  return texto;
}

Ese contador ultimoTiempoLectura no puede refrezcarse con cada loop porque inhibe tu detector de inactividad que inicia con el
asi que coméntalo.

// ultimoTiempoLectura = millis(); // reiniciar contador al leer

No uses delay() tan restrictivos como este

  lcd.print(uid);
  delay(1000);

Maneja todo usando millis(), el código debe ser fluido, si vá muy rápido enconces agrega otro millis() y una variable que controlen la ejecucción de otra porción de código.

Y otro mas

    for (int i = 0; i <= len - 16; i++) {
      lcd.setCursor(0, 1);
      lcd.print(texto.substring(i, i + 16));
      delay(300);
    }

y luego otro delay(800)
Ese delay(300) x 16 equivale a 4800 mseg o sea casi 5 segundos
Claramente las cosas pueden funcionar con esos tiempos pero todo se pone PESADO!!