#include <LiquidCrystal.h>
#include <Keypad.h>
#include "SevSeg.h"
SevSeg sevseg;
#define LCD_RS 0
#define LCD_E 1
#define LCD_D4 3
#define LCD_D5 4
#define LCD_D6 5
#define LCD_D7 6
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
const byte filas = 3, columnas = 3;
char teclas[filas][columnas] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'}
};
byte pinsFilas[filas] = {28, 27, 26};
byte pinsColumnas[columnas] = {21, 20, 22};
Keypad keypad = Keypad(makeKeymap(teclas), pinsFilas, pinsColumnas, filas, columnas);
#define MOTOR_A_MAS 10
#define MOTOR_A_MENOS 11
#define MOTOR_B_MAS 12
#define MOTOR_B_MENOS 13
#define SWITCH_PUERTA 15
const uint8_t secuencia_pasos[4][4] = {
{1,0,1,0},
{0,1,1,0},
{0,1,0,1},
{1,0,0,1}
};
int pasos_pos = 0;
enum CicloLavado {
INGRESAR_AGUA1,
LAVAR,
DESECHAR_AGUA1,
INGRESAR_AGUA2,
ENJUAGAR,
DESECHAR_AGUA2,
CENTRIFUGAR,
TERMINADO
};
CicloLavado ciclo_actual = INGRESAR_AGUA1;
struct TiemposCiclo {
int ingresar_agua;
int lavar;
int desechar_agua;
int enjuagar;
int centrifugar;
} tiempos;
int peso = 0;
int tiempo_restante = 0;
bool puerta_cerrada = false;
bool pausado = false;
unsigned long previousMillis = 0;
const long interval = 1000;
unsigned long motorMillis = 0;
const long motorInterval = 10;
bool motor_activo = false;
bool secuencia_activa = false;
bool sentido_horario = true;
unsigned long lavar_sentido_cambio_millis = 0;
void motor_step(int i) {
digitalWrite(MOTOR_A_MAS, secuencia_pasos[i][0]);
digitalWrite(MOTOR_A_MENOS, secuencia_pasos[i][1]);
digitalWrite(MOTOR_B_MAS, secuencia_pasos[i][2]);
digitalWrite(MOTOR_B_MENOS, secuencia_pasos[i][3]);
}
void motor_stop() {
digitalWrite(MOTOR_A_MAS, LOW);
digitalWrite(MOTOR_A_MENOS, LOW);
digitalWrite(MOTOR_B_MAS, LOW);
digitalWrite(MOTOR_B_MENOS, LOW);
}
void configurar_pines() {
pinMode(MOTOR_A_MAS, OUTPUT);
pinMode(MOTOR_A_MENOS, OUTPUT);
pinMode(MOTOR_B_MAS, OUTPUT);
pinMode(MOTOR_B_MENOS, OUTPUT);
motor_stop();
pinMode(SWITCH_PUERTA, INPUT_PULLUP);
}
char leer_peso_teclado() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Ing peso (1-9):");
while (true) {
char key = keypad.getKey();
if (key >= '1' && key <= '9') {
lcd.setCursor(0,1);
lcd.print("Peso: ");
lcd.print(key);
delay(700);
return key;
}
}
}
void set_tiempos_por_peso(int p) {
if (p >= 1 && p <= 4) {
tiempos.ingresar_agua = 2;
tiempos.lavar = 25;
tiempos.desechar_agua = 2;
tiempos.enjuagar = 15;
tiempos.centrifugar = 5;
} else {
tiempos.ingresar_agua = 4;
tiempos.lavar = 50;
tiempos.desechar_agua = 4;
tiempos.enjuagar = 25;
tiempos.centrifugar = 8;
}
}
void mostrar_ciclo_y_tiempo(const char* ciclo, int seg) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(ciclo);
sevseg.setNumber(seg, 0);
sevseg.refreshDisplay();
}
void iniciar_etapa(CicloLavado etapa) {
ciclo_actual = etapa;
secuencia_activa = false;
motor_activo = false;
sentido_horario = true;
lavar_sentido_cambio_millis = millis();
switch (etapa) {
case INGRESAR_AGUA1:
tiempo_restante = tiempos.ingresar_agua;
mostrar_ciclo_y_tiempo("Llenando agua", tiempo_restante);
break;
case LAVAR:
tiempo_restante = tiempos.lavar;
secuencia_activa = true;
motor_activo = true;
break;
case DESECHAR_AGUA1:
tiempo_restante = tiempos.desechar_agua;
motor_activo = false;
mostrar_ciclo_y_tiempo("Drenando agua", tiempo_restante);
break;
case INGRESAR_AGUA2:
tiempo_restante = tiempos.ingresar_agua;
motor_activo = false;
mostrar_ciclo_y_tiempo("Llenando agua", tiempo_restante);
break;
case ENJUAGAR:
tiempo_restante = tiempos.enjuagar;
secuencia_activa = true;
motor_activo = true;
sentido_horario = false;
break;
case DESECHAR_AGUA2:
tiempo_restante = tiempos.desechar_agua;
motor_activo = false;
break;
case CENTRIFUGAR:
tiempo_restante = tiempos.centrifugar;
secuencia_activa = true;
motor_activo = true;
break;
case TERMINADO:
tiempo_restante = 0;
motor_activo = false;
motor_stop();
mostrar_ciclo_y_tiempo("Lavado Terminado", 0);
break;
}
motorMillis = millis();
pasos_pos = 0;
}
void avanzar_siguiente() {
switch (ciclo_actual) {
case INGRESAR_AGUA1: iniciar_etapa(LAVAR); break;
case LAVAR: iniciar_etapa(DESECHAR_AGUA1); break;
case DESECHAR_AGUA1: iniciar_etapa(INGRESAR_AGUA2); break;
case INGRESAR_AGUA2: iniciar_etapa(ENJUAGAR); break;
case ENJUAGAR: iniciar_etapa(DESECHAR_AGUA2); break;
case DESECHAR_AGUA2: iniciar_etapa(CENTRIFUGAR); break;
case CENTRIFUGAR: iniciar_etapa(TERMINADO); break;
default: iniciar_etapa(TERMINADO); break;
}
}
void setup() {
configurar_pines();
lcd.begin(16, 2);
byte numDigits = 2;
byte digitPins[] = {18, 19};
bool resistorsOnSegments = false;
byte segmentPins[] = {2, 7, 8, 9, 14, 16, 17};
byte hardwareConfig = COMMON_CATHODE;
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins);
sevseg.setBrightness(90);
char key = leer_peso_teclado();
peso = key - '0';
set_tiempos_por_peso(peso);
puerta_cerrada = digitalRead(SWITCH_PUERTA) == LOW;
lcd.clear();
lcd.print("Cerrar puerta");
while (!puerta_cerrada) {
puerta_cerrada = digitalRead(SWITCH_PUERTA) == LOW;
delay(100);
}
iniciar_etapa(INGRESAR_AGUA1);
previousMillis = millis();
motorMillis = millis();
}
void loop() {
puerta_cerrada = digitalRead(SWITCH_PUERTA) == LOW;
if (!puerta_cerrada) {
if (!pausado) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("PUERTA ABIERTA!");
motor_stop();
pausado = true;
motor_activo = false;
}
delay(200);
return;
} else if (pausado) {
pausado = false;
if (ciclo_actual == LAVAR || ciclo_actual == ENJUAGAR || ciclo_actual == CENTRIFUGAR) {
motor_activo = secuencia_activa;
} else {
motor_activo = false;
}
mostrar_ciclo_y_tiempo(
ciclo_actual == INGRESAR_AGUA1 ? "Llenando agua" :
ciclo_actual == LAVAR ? "Lavando" :
ciclo_actual == DESECHAR_AGUA1 ? "Drenando agua" :
ciclo_actual == INGRESAR_AGUA2 ? "Llenando agua" :
ciclo_actual == ENJUAGAR ? "Enjuagando" :
ciclo_actual == DESECHAR_AGUA2 ? "Drenando agua" :
ciclo_actual == CENTRIFUGAR ? "Centrifugando" : "Terminado",
tiempo_restante
);
}
unsigned long currentMillis = millis();
if (motor_activo && secuencia_activa && (currentMillis - motorMillis) >= motorInterval) {
motorMillis = currentMillis;
pasos_pos = sentido_horario ? (pasos_pos + 1) % 4 : (pasos_pos + 3) % 4;
motor_step(pasos_pos);
unsigned long elapsed = currentMillis - lavar_sentido_cambio_millis;
if (ciclo_actual == LAVAR) {
if ((sentido_horario && elapsed >= 2000) || (!sentido_horario && elapsed >= 1000)) {
sentido_horario = !sentido_horario;
lavar_sentido_cambio_millis = currentMillis;
}
}
else if (ciclo_actual == ENJUAGAR) {
if (elapsed >= 2000) {
sentido_horario = !sentido_horario;
lavar_sentido_cambio_millis = currentMillis;
}
}
else if (ciclo_actual == CENTRIFUGAR) {
sentido_horario = true;
}
}
if (!motor_activo) motor_stop();
if ((currentMillis - previousMillis) >= interval) {
previousMillis = currentMillis;
if (tiempo_restante <= 0) avanzar_siguiente();
else {
tiempo_restante--;
mostrar_ciclo_y_tiempo(
ciclo_actual == INGRESAR_AGUA1 ? "Llenando agua" :
ciclo_actual == LAVAR ? "Lavando" :
ciclo_actual == DESECHAR_AGUA1 ? "Drenando agua" :
ciclo_actual == INGRESAR_AGUA2 ? "Llenando agua" :
ciclo_actual == ENJUAGAR ? "Enjuagando" :
ciclo_actual == DESECHAR_AGUA2 ? "Drenando agua" :
ciclo_actual == CENTRIFUGAR ? "Centrifugando" : "Terminado",
tiempo_restante
);
}
}
sevseg.refreshDisplay();
delay(1);
}