Primero que todo tengan un buen dia, vengo a ustedes en busca de ayuda por problema que se me presenta con un proyecto que tengo de la escuela, tengo los siguientes componentes, fuente conmutada de dos salidas 12v y total de 10 A, un rfid 522, una pantalla lcd 20x4, un termometro MLX90614, un rele optoacoplador de 4 canales, 2 bombas sumergibles de 5v y una bomba de diafragma de 12v y un step down dc dc de 12v a 5v, todo esto en una wemos d1 r32 esp32, todo montado como se ve en el esquematico, el proyecto es un sistema de desinfeccion de manos para mi escuela, el cual hace una consulta del alumno en una base de datos remota, el problema que tengo es que en primera instancia el circuito funciona cuando paso la tarjeta identifica al usuario y se conecta a la base de datos y valida, luego procede a hacer el lavado, pero cuando vuelve a la ventana de incio el lector ya no me lee mas tarjetas, estuve buscando solucion y no he encontrado nada, algo curioso es que cuando retiro la bombas del rele, funciona y me lee mas tarjetas, lo se por que el rele tiene unos led que me indican que canal esta activo en el momento, esto pasa cuando retiro las tres bombas del circuito pero cuando las vuelvo a colocar el rfid me reconoce la primera tarjeta y despues ya no me reconoce ninguna otra.
nota: parece ser que la bomba de 12v me esta causando problemas, dado que si dejo las dos bombas de sumergibles de 5v el sistema funciona bien, pero al agregar la bomba de diafragma al rele, el lector de tarjetas ya deja de leer las tarjetas siguientes y me toca reinciar la placa
escribe o pega e#include <Adafruit_MLX90614.h>
#include <infrarrojo.h>
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include<Wire.h>
#include <HTTPClient.h>
#include <WiFi.h>
#include <Arduino.h>
const char* ssid = "mi wifi";
const char* password = "mi clave";
#define RST_PIN 13 // se configuran las constantes de los pines por defecto para el MFRC522
#define SS_PIN 5 // se configuran las constantes de los pines por defecto para el MFRC522
infrarrojo estadoManos(12); //Pin donde esta conectado el sensor para la detencion de las manos
infrarrojo estadoRostro(14); //Pin donde esta conectado el sensor para el acercamiento del rostro usuarios
int iReleAgua = 27; //Pin donde esta conectado la entrada del rele que activa el bombeo de agua
int iReleJabon = 16; // Pin donde esta conectado la entrada del rele que activa el bombeo de jabon
int iReleAntibac = 17; // Pin donde esta conectado la entrada del rele que activa el bombeo de anctibacterial
int iValorManos; //Valor que tomara el estado que mande el sensor de manos
int iValorRostro; //Valor que tomara el estado que mande el sensor que verifica el acercamiento del rostro del usuario
int iSensorManos; //Variable en la que se guarda el estado del sensor de manos
int iSensorRostro; //Variable en la que se guarda el estado del sensor para dectar el acercamiento del rostro del usuario
unsigned long tiempo; //Variable qu guarda el tiempo en diferentes puntos del proceso
MFRC522 mfrc522(SS_PIN, RST_PIN); // Se crea la interface MFRC522
LiquidCrystal_I2C lcd(0x27, 20, 4); // Se establece el tipo de display
Adafruit_MLX90614 mlx = Adafruit_MLX90614(); // se crea el objeto de sensor de temperatura
//Arreglos que guaradan los caracteres que se mostraran en el proceso
byte cara[8] = {
B00000,
B10001,
B00000,
B00000,
B10001,
B01110,
B00000,
};
byte tapaboca[8] = {
0b00000,
0b10001,
0b00000,
0b11111,
0b01110,
0b11111,
0b00000,
0b00000
};
byte carga[] = {
B00000,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B00000
};
byte jabon1[8] = {
0xff,
0xff,
0xff,
0xff,
0xff,
0xfc,
0xf0,
0xe0,
};
byte jabon2[8] = {
0xff,
0xff,
0xff,
0xe7,
0x01,
0x00,
0x00,
0x00,
};
byte jabon3[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0x70,
0x30,
0x30,
};
byte jabon4[8] = {
0xc0,
0xc0,
0xc0,
0xe0,
0xf8,
0xfe,
0xff,
0xff,
};
byte jabon5[8] = {
0x00,
0x00,
0x01,
0x07,
0x1f,
0x7f,
0xff,
0xff,
};
byte jabon6[8] = {
0x30,
0x70,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte agua1[8] = {
0xff,
0xff,
0xff,
0xff,
0xff,
0xfe,
0xfc,
0xfc,
};
byte agua2[8] = {
0xff,
0x9f,
0x9f,
0x0f,
0x0f,
0x07,
0x03,
0x03,
};
byte agua3[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte agua4[8] = {
0xf8,
0xf8,
0xf8,
0xf8,
0xf8,
0xfc,
0xfe,
0xff,
};
byte agua5[8] = {
0x01,
0x01,
0x01,
0x01,
0x01,
0x03,
0x07,
0x0f,
};
byte agua6[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte antibacterial1[8] = {
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xfe,
0xfe,
};
byte antibacterial2[8] = {
0x83,
0x9b,
0x9f,
0x9b,
0x0f,
0x0f,
0x07,
0x07,
};
byte antibacterial3[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte antibacterial4[8] = {
0xfc,
0xfc,
0xfc,
0xfc,
0xfc,
0xfc,
0xfc,
0xfe,
};
byte antibacterial5[8] = {
0x03,
0x03,
0x03,
0x03,
0x03,
0x03,
0x03,
0x07,
};
byte antibacterial6[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte abajo1[8] = {
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
};
byte abajo2[8] = {
0x0f,
0x0f,
0x0f,
0x0f,
0x0f,
0x0f,
0x0f,
0x0f,
};
byte abajo3[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
byte abajo4[8] = {
0xff,
0xff,
0xfc,
0xfe,
0xff,
0xff,
0xff,
0xff,
};
byte abajo5[8] = {
0x0f,
0x0f,
0x03,
0x07,
0x0f,
0x0f,
0x9f,
0xff,
};
byte abajo6[8] = {
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
};
void setup() {
delay(10);
// Se incia la comuniacion serial
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Conectando...");
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(500);
Serial.print(".");
}
Serial.print("Conectado con éxito, mi IP es: ");
Serial.println(WiFi.localIP());
//Se incializa el lcd, la luz de fondo y se limpia la pantalla dejando el cursos en poscion (0,0)
lcd.begin(20, 4);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
//Se crean los arreglos de los caracteres de tapaboca y cara
lcd.createChar (0, tapaboca);
lcd.createChar (1, cara);
lcd.createChar (2, carga);
//Se incializa la libreria Wire
Wire.begin();
//Se incializan los componentes de del lector de tarjetas
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // se incializa el modulo lector MFRC522
//mfrc522.PCD_SetAntennaGain(112); // Aumenta la ganacia y distancia de lectura con un maximo de (00001110)
//Se incia el componente del sensor de temperatura
mlx.begin();
//Se incializan los pines del rele en modo salida
pinMode(iReleAgua, OUTPUT);
pinMode(iReleJabon, OUTPUT);
pinMode(iReleAntibac, OUTPUT);
digitalWrite(iReleJabon, HIGH);
digitalWrite(iReleAgua, HIGH);
digitalWrite(iReleAntibac, HIGH);
//Ciclo para mostrar una pantalla de carga
for (int i = 6 ; i <= 14 ; i ++) {
lcd.setCursor(6, 0);
lcd.print("CARGANDO!");
lcd.setCursor(i, 2);
lcd.write (byte(2));
delay(500);
}
}
void loop() {
//Variable para almacenar la temperatura y el codigo leido de la tarjeta
String respuesta = "";
String nombres = "";
String apellidos = "";
String curso = "";
String grado = "";
String tarjeta = "";
double temp;
String nombrePantalla = "";
String apellidoPantalla = "";
//Se limpia la pantalla
lcd.clear();
//Se llama al metodo bienvenida que muestra la informacion de bienvenida
bienvenida();
//Se crea un ciclo para mover el texto de derecha a izquierda usando lcd.scrollDisplayLeft, si quieramos invertir el movimento lo cambiamos por lcd.scrollDisplayRigh
for (int positionCounter = 0; positionCounter < 40; positionCounter++) {
lcd.scrollDisplayLeft();
delay(150);
// Condicional para validar si hay una tarjeta cerca al lector de lo contrario ejecuta el condicional dado que se niega la condicion y ejecutar el return para volver al loop
if (mfrc522.PICC_IsNewCardPresent()) {
break;
}
}
// si pasa el primer condicional, este valida si la tarjeta se le puede leer la informacion dentro si no ejecuta el return y vuelve al loop
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
//Con este ciclo se utiliza para rrecorrerel valor leido del uid leido por el MFRC522 y almacenarlo en el arreglo LecturaUDI[] y en la variable tarjeta para mostralo en pantalla
for (byte i = 0; i < mfrc522.uid.size; i++) {
tarjeta += mfrc522.uid.uidByte[i];
}
/**
Se llama al metodo para consultar la base de datos y verificar el codigo paratraer los demas datos, nombres, apellidos, grado y curso.
*/
respuesta = consultaDatos(tarjeta);
int longitudRespuesta = respuesta.length();
int pos1 = respuesta.indexOf("$1");
int pos2 = respuesta.indexOf("$2");
int pos3 = respuesta.indexOf("$3");
int pos4 = respuesta.indexOf("$4");
//En este for se analiza la respuesta y para divir el String y obtener los datos que se neceitan, en este caso, nombre, apellido, curso y grado
for (int i = pos1 + 2; i < longitudRespuesta; i++) {
if ( i < pos2 ) {
if (isWhitespace(respuesta[i])) {
nombres += "+";
continue;
}
nombres += respuesta[i];
} else if (i >= pos2 + 2 && i < pos3 ) {
if (isWhitespace(respuesta[i])) {
apellidos += "+";
continue;
}
apellidos += respuesta[i];
} else if (i >= pos3 + 2 && i < pos4 ) {
curso += respuesta[i];
} else if (i >= pos4 + 2 && i <= longitudRespuesta) {
grado += respuesta[i];
}
}
/**
Ambos for se utilizan para obtener el primer nombre y primer apellido para mostralo en pantalla
*/
int tamNombres = nombres.length();
for (int i = 0; i < tamNombres; i++) {
if (nombres[i] == 43) {
break;
}
nombrePantalla += nombres[i];
}
int tamaApellidos = apellidos.length();
for (int i = 0; i < tamaApellidos; i++) {
if (apellidos[i] == 43) {
break;
}
apellidoPantalla += apellidos[i];
}
/**
Se valida la respuesta del metodo get para saber si el usuario existe si no, se termina el proceso
*/
if (!nombres.equals("")) {
lcd.display();
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Bienvenido(a):");
lcd.setCursor(4, 1);
lcd.print(nombrePantalla + " " + apellidoPantalla);
lcd.setCursor(6, 2);
lcd.print("Curso: " + curso);
lcd.setCursor(7, 3);
lcd.print("Grado: " + grado);
delay(6000);
temp = tomaTempratura();
envioBaseDatos(nombres, apellidos, tarjeta, curso, grado.toInt(), temp );
procesoCompleto();
mfrc522.PICC_HaltA();
} else {
lcd.display();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Usuario desconocido");
lcd.setCursor(1, 2);
lcd.print("Proceso terminado");
delay(6000);
mfrc522.PICC_HaltA();
return;
}
mfrc522.PICC_HaltA();
}
/**
Metodo encargado de enviar los datos del usuario a la base de datos para almacenarnos en la tabla de uso de dispositivo
*/
void envioBaseDatos(String nombres, String apellidos, String tarjeta, String curso, int grado, double temp ) {
String url = "";
url += "?nombres_php=";
url += nombres;
url += "&apellidos_php=";
url += apellidos;
url += "&codigo_tarjeta_php=";
url += tarjeta;
url += "&curso_php=";
url += curso;
url += "&grado_php=";
url += grado;
url += "&temperatura_php=";
url += temp;
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http;
http.begin("direccion_servidor + url); //Indicamos el destino
http.addHeader("Content-Type", "plain-text"); //Preparamos el header text/plain si solo vamos a enviar texto plano sin un paradigma llave:valor.
int codigo_respuesta = http.GET(); //Enviamos el get
if (codigo_respuesta > 0) {
Serial.println("Código HTTP ► " + String(codigo_respuesta)); //Print return code
if (codigo_respuesta == 200) {
String cuerpo_respuesta = http.getString();
Serial.println("El servidor respondió ▼ ");
Serial.println(cuerpo_respuesta);
}
} else {
Serial.print("Error enviando GET, código: ");
Serial.println(codigo_respuesta);
}
http.end(); //libero recursos
} else {
Serial.println("Error en la conexión WIFI");
}
}
/**
Metodo con el cual se pasa como parametro el valor UID del llavero o tarjeta para enviarlo por consulta get al servidor y verificar si el usuario esta en la base de datos
*/
String consultaDatos(String tarjeta) {
String cuerpo_respuesta = "";
String url = "";
url += "?codigo_tarjeta_php=";
url += tarjeta;
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http;
http.begin("direccion_servidor" + url); //Indicamos el destino
http.addHeader("Content-Type", "plain-text"); //Preparamos el header text/plain si solo vamos a enviar texto plano sin un paradigma llave:valor.
int codigo_respuesta = http.GET(); //Enviamos el get
if (codigo_respuesta > 0) {
Serial.println("Código HTTP ► " + String(codigo_respuesta)); //Print return code
if (codigo_respuesta == 200) {
cuerpo_respuesta = http.getString();
Serial.println("El servidor respondió ▼ ");
Serial.println(cuerpo_respuesta);
}
} else {
Serial.print("Error enviando GET, código: ");
Serial.println(codigo_respuesta);
}
http.end(); //libero recursos
} else {
Serial.println("Error en la conexión WIFI");
}
return cuerpo_respuesta;
}
/**
Metodo encargado de tomar la temperatura y devolver el valor de esta
*/
float tomaTempratura() {
tiempo = millis();
float temp;
do {
iSensorRostro = estadoRostro.lectura(iValorRostro);
//Se limpia el displey y semestra en panatlla un mensaje para que el usuario se acerque para tomar la temperatura
lcd.display();
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("POR FAVOR ACERCATE");
lcd.setCursor(1, 1);
lcd.print("A LA PANTALLA PARA");
lcd.setCursor(0, 2);
lcd.print("TOMAR LA TEMPERATURA");
delay(6000);
} while ((iSensorRostro == 0) && (millis() < tiempo + 15000));
if (iSensorRostro == 1) {
//Se muestra en pantalla la temperatura y se almacena en la variable temp
temp = mlx.readObjectTempC();
lcd.display();
lcd.clear();
lcd.setCursor(4, 1);
lcd.print("Temp: ");
lcd.print(temp);
lcd.print((char)223);
lcd.print("C");
delay(6000);
} else {
despedida();
loop();
}
return temp;
}
/**
Metodo encargado del proceso de lavado total, ene sta parte se hacen el llamdo a los demas metodos y se estructura parte del proceso
*/
void procesoCompleto() {
do {
iSensorManos = estadoManos.lectura(iValorManos);
lcd.createChar (0, abajo1);
lcd.createChar (1, abajo2);
lcd.createChar (2, abajo3);
lcd.createChar (3, abajo4);
lcd.createChar (4, abajo5);
lcd.createChar (5, abajo6);
lcd.setCursor(17, 1);
lcd.write (byte(0));
lcd.setCursor(18, 1);
lcd.write (byte(1));
lcd.setCursor(19, 1);
lcd.write (byte(2));
lcd.setCursor(17, 2);
lcd.write (byte(3));
lcd.setCursor(18, 2);
lcd.write (byte(4));
lcd.setCursor(19, 2);
lcd.write (byte(5));
lcd.setCursor(0, 0);
lcd.print("POR FAVOR, COLOQUE");
lcd.setCursor(0, 1);
lcd.print("LAS MANOS DEBAJO");
lcd.setCursor(0, 2);
lcd.print("PARA INCIAR EL");
lcd.setCursor(0, 3);
lcd.print("PROCESO DE LAVADO");
lcd.display();
delay(1000);
lcd.noDisplay();
delay(1000);
}
while ((iSensorManos == 0) && (millis() < tiempo + 15000));
if (iSensorManos == 1) {
lcd.display();
lcd.clear();
lcd.setCursor(2, 1);
lcd.print("!NO LAS RETIRE!");
delay(5000);
lcd.clear();
lcd.display();
lcd.setCursor(3, 0);
lcd.print("A CONTINUACION");
lcd.setCursor(4, 1);
lcd.print("DISPENSAREMOS");
lcd.setCursor(3, 2);
lcd.print("JABON LIQUIDO!");
delay(4000);
lcd.clear();
dispensadorJabon(); // SE LLAMA AL METODO ENCARGADO DE DISPENSAR EL JABON
lcd.display();
lcd.clear();
lcd.setCursor(5, 1);
lcd.print("!RESTREGUE");
lcd.setCursor(3, 2);
lcd.print("LAS MANOS BIEN!");
delay(10000);
tiempo = millis();
do {
iSensorManos = estadoManos.lectura(iValorManos);
lcd.clear();
lcd.setCursor(2, 1);
lcd.print("!NO LAS RETIRE!");
delay(5000);
}
while ((iSensorManos == 0) && (millis() < tiempo + 5000));
if (iSensorManos == 1) {
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("A CONTINUACION");
lcd.setCursor(4, 1);
lcd.print("DISPENSAREMOS");
lcd.setCursor(7, 2);
lcd.print("AGUA!");
delay(4000);
lcd.clear();
dispensadorAgua(); // SE LLAMA AL METODO ENCARGADO DE DISPENSAR EL AGUA
lcd.display();
lcd.clear();
lcd.setCursor(2, 1);
lcd.print("ESCURRA LAS MANOS");
lcd.setCursor(1, 2);
lcd.print("LO MEJOR QUE PUEDA!");
delay(10000);
tiempo = millis();
do {
iSensorManos = estadoManos.lectura(iValorManos);
lcd.clear();
lcd.setCursor(2, 1);
lcd.print("!NO LAS RETIRE!");
delay(5000);
}
while ((iSensorManos == 0) && (millis() < tiempo + 5000));
if (iSensorManos == 1) {
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("A CONTINUACION");
lcd.setCursor(4, 1);
lcd.print("DISPENSAREMOS");
lcd.setCursor(3, 2);
lcd.print("ANTIBACTERIAL!");
delay(4000);
lcd.clear();
dispensadorAntibacterial(); // SE LLAMA AL METODO ENCARGADO DE DISPENSAR EL ANTIBACTERIAL
lcd.display();
lcd.clear();
lcd.setCursor(1, 1);
lcd.print("!PROCESO TERMINADO!");
delay(6000);
lcd.clear();
despedida();
} else {
despedida();
}
} else {
despedida();
}
} else {
despedida();
}
}
/**
Metodo para mostrar mensaje de despedida
*/
void despedida() {
lcd.display();
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("MUCHAS GRACIAS");
lcd.setCursor(5, 1);
lcd.print("POR USAR EL");
lcd.setCursor(6, 2);
lcd.print("SERVICIO!");
delay(6000);
}
/**
Muncion para comprar los valor del UID leido con los de los usuarios almacenados internamente en los arreglos
*/
boolean comparaUID(byte lectura[], byte usuarios[]) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (lectura[i] != usuarios[i]) {
return (false);
}
}
return (true);
}
/**
Metodo para mostrar la informacion de bienvenida
*/
void bienvenida() {
lcd.createChar (0, tapaboca);
lcd.createChar (1, cara);
lcd.setCursor(3, 0);
lcd.write (byte(0));
lcd.print(" ");
lcd.write (byte(1));
lcd.print("BIENVENIDO");
lcd.write (byte(1));
lcd.print(" ");
lcd.write (byte(0));
lcd.setCursor(9, 2);
lcd.print("PUNTO");
lcd.setCursor(4, 3);
lcd.print("DE DESINFECCION");
}
/**
Metodo que activa el rele del dispensador de jabon y muestra indicacion en pantalla
*/
void dispensadorJabon() { // METODO QUE ACTIVA EL RELE DEL DISPENSADOR DE JABON Y MUESTRA EN PANTALLA "DISPENSANDO JABON" CCON UN RETRASO DE 1 SEGUNDO
tiempo = millis();
while (millis() < tiempo + 6000 ) {
digitalWrite(iReleJabon, LOW);
lcd.createChar (0, jabon1);
lcd.createChar (1, jabon2);
lcd.createChar (2, jabon3);
lcd.createChar (3, jabon4);
lcd.createChar (4, jabon5);
lcd.createChar (5, jabon6);
lcd.setCursor(1, 1);
lcd.write (byte(0));
lcd.setCursor(2, 1);
lcd.write (byte(1));
lcd.setCursor(3, 1);
lcd.write (byte(2));
lcd.setCursor(1, 2);
lcd.write (byte(3));
lcd.setCursor(2, 2);
lcd.write (byte(4));
lcd.setCursor(3, 2);
lcd.write (byte(5));
lcd.setCursor(6, 1);
lcd.print("DISPENSANDO");
lcd.setCursor(6, 2);
lcd.print("JABON!");
lcd.display();
delay(1000);
lcd.noDisplay();
delay(1000);
}
digitalWrite(iReleJabon, HIGH);
}
/**
Metodo que activa el rele del dispensador de agua y muestra indicacion en pantalla
*/
void dispensadorAgua() {
tiempo = millis();
while (millis() < tiempo + 10000 ) {
digitalWrite(iReleAgua, LOW);
lcd.createChar (0, agua1);
lcd.createChar (1, agua2);
lcd.createChar (2, agua3);
lcd.createChar (3, agua4);
lcd.createChar (4, agua5);
lcd.createChar (5, agua6);
lcd.setCursor(1, 1);
lcd.write (byte(0));
lcd.setCursor(2, 1);
lcd.write (byte(1));
lcd.setCursor(3, 1);
lcd.write (byte(2));
lcd.setCursor(1, 2);
lcd.write (byte(3));
lcd.setCursor(2, 2);
lcd.write (byte(4));
lcd.setCursor(3, 2);
lcd.write (byte(5));
lcd.setCursor(6, 1);
lcd.print("DISPENSANDO");
lcd.setCursor(6, 2);
lcd.print("AGUA!");
lcd.display();
delay(1000);
lcd.noDisplay();
delay(1000);
}
digitalWrite(iReleAgua, HIGH);
}
/**
Metodo que activa el rele del dispensador de antibacterial y muestra indicacion en pantalla
*/
void dispensadorAntibacterial() {
tiempo = millis();
while (millis() < tiempo + 8000 ) {
digitalWrite(iReleAntibac, LOW);
lcd.createChar (0, antibacterial1);
lcd.createChar (1, antibacterial2);
lcd.createChar (2, antibacterial3);
lcd.createChar (3, antibacterial4);
lcd.createChar (4, antibacterial5);
lcd.createChar (5, antibacterial6);
lcd.setCursor(1, 1);
lcd.write (byte(0));
lcd.setCursor(2, 1);
lcd.write (byte(1));
lcd.setCursor(3, 1);
lcd.write (byte(2));
lcd.setCursor(1, 2);
lcd.write (byte(3));
lcd.setCursor(2, 2);
lcd.write (byte(4));
lcd.setCursor(3, 2);
lcd.write (byte(5));
lcd.setCursor(6, 1);
lcd.print("DISPENSANDO");
lcd.setCursor(6, 2);
lcd.print("ANTIBACTERIAL!");
lcd.display();
delay(1000);
lcd.noDisplay();
delay(1000);
}
digitalWrite(iReleAntibac, HIGH);
}l código aquí

