// ===== CONFIGURACIÓN DE PINES =====
const int SENSOR_TOLVA = 2; // Pin 2: Detección material en tolva (INPUT_PULLUP)
const int SENSOR_BANDA = 3; // Pin 3: Detección material en banda (INPUT_PULLUP)
const int SENSOR_DOBLADO = 4; // Pin 4: Inicio secuencia doblado (INPUT_PULLUP)
const int PARO_EMERGENCIA = 5; // Pin 5: Paro de emergencia (INPUT_PULLUP)
const int BOTON_INICIO = 6; // Pin 6: Iniciar ciclo (INPUT_PULLUP)
const int BOTON_RESET = 7; // Pin 7: Reset sistema (INPUT_PULLUP)
// El potenciómetro de velocidad ya no es necesario ni está cableado.
// Actuadores (Salidas digitales)
// const int VALVULA_ALIMENTADOR = 8; // ELIMINADA: Pin 8: Electroválvula alimentador
const int VALVULA_PESTANA_CHICA = 9; // Pin 9: Electroválvula pestaña pequeña
const int VALVULA_PESTANA_GRANDE_INT = 10; // Pin 10: Pestaña grande interior
const int VALVULA_MOVIMIENTO = 11; // Pin 11: Electroválvula movimiento
const int VALVULA_PESTANA_GRANDE_EXT = 12; // Pin 12: Pestaña grande exterior
const int PISTON_TOLVA = 13; // Pin 13: Pistón tolva
// Control Motor AC (a través de Módulo de Relé)
const int CONTROL_MOTOR_AC = 53; // Pin 53: Control del módulo de relé
// LEDs Indicadores
const int LED_TOLVA = 45; // Pin 45: Indicador material en tolva
const int LED_CICLO = 44; // Pin 44: Indicador ciclo activo
const int LED_EMERGENCIA = 43; // Pin 43: Indicador paro emergencia
// ===== VARIABLES DE ESTADO =====
enum EstadoSistema {
ESPERA,
CICLO_CONTINUO,
PROCESANDO,
DOBLANDO,
EMERGENCIA
};
EstadoSistema estadoActual = ESPERA;
// Temporizadores
unsigned long tiempoInicioPiston = 0;
const unsigned long DURACION_PISTON = 2000; // 2 segundos
unsigned long tiempoDeteccionBanda = 0;
const unsigned long RETARDO_DETENCION_MOTOR = 2000; // 2 segundos
// Variables para la secuencia de doblado no bloqueante
unsigned long tiempoInicioDoblez = 0;
int pasoDoblez = 0;
bool dobladoActivado = false; // Bandera para indicar si el doblado se ha activado
// Control de emergencia y sensores
bool materialPerdido = false;
bool sensorDobladoDetectado = false; // Variable para la detección temporal del sensor de doblado
unsigned long tiempoSensorDobladoActivado = 0; // Tiempo en que el sensor de doblado se activó
// ===== FUNCIONES PRINCIPALES =====
// Función para controlar el motor AC a través del módulo de relé (solo ON/OFF)
// NOTA: Muchos módulos de relé para Arduino se activan con una señal LOW.
// Sin embargo, por tu descripción, tu módulo parece activarse con HIGH.
void controlMotor(bool activar) {
if (activar) {
digitalWrite(CONTROL_MOTOR_AC, HIGH); // Activa el relé (enciende el motor)
} else {
digitalWrite(CONTROL_MOTOR_AC, LOW); // Desactiva el relé (apaga el motor)
}
}
// Función que gestiona la secuencia de doblado de forma no bloqueante
bool secuenciaDobladoNoBloqueante() {
switch (pasoDoblez) {
case 0:
// digitalWrite(VALVULA_ALIMENTADOR, HIGH); // ELIMINADO
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
case 1:
if (millis() - tiempoInicioDoblez >= 50) {
// digitalWrite(VALVULA_ALIMENTADOR, LOW); // ELIMINADO
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 2: // Antes era paso 2, ahora es paso 0 efectivo para la primera valvula
if (millis() - tiempoInicioDoblez >= 500) { // El retardo inicial de 500ms se mantiene si se desea
digitalWrite(VALVULA_PESTANA_CHICA, HIGH);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 3: // Antes era paso 3, ahora es paso 1 efectivo
if (millis() - tiempoInicioDoblez >= 500) {
digitalWrite(VALVULA_PESTANA_CHICA, LOW);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 4: // Antes era paso 4, ahora es paso 2 efectivo
if (millis() - tiempoInicioDoblez >= 200) {
digitalWrite(VALVULA_PESTANA_GRANDE_INT, HIGH);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 5: // Antes era paso 5, ahora es paso 3 efectivo
if (millis() - tiempoInicioDoblez >= 500) {
digitalWrite(VALVULA_MOVIMIENTO, HIGH);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 6: // Antes era paso 6, ahora es paso 4 efectivo
if (millis() - tiempoInicioDoblez >= 800) {
digitalWrite(VALVULA_PESTANA_GRANDE_EXT, HIGH);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 7: // Antes era paso 7, ahora es paso 5 efectivo
if (millis() - tiempoInicioDoblez >= 400) {
digitalWrite(VALVULA_PESTANA_GRANDE_EXT, LOW);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 8: // Antes era paso 8, ahora es paso 6 efectivo
if (millis() - tiempoInicioDoblez >= 100) {
digitalWrite(VALVULA_PESTANA_GRANDE_INT, LOW);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 9: // Antes era paso 9, ahora es paso 7 efectivo
if (millis() - tiempoInicioDoblez >= 400) {
digitalWrite(VALVULA_PESTANA_GRANDE_INT, HIGH);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 10: // Antes era paso 10, ahora es paso 8 efectivo
if (millis() - tiempoInicioDoblez >= 100) {
digitalWrite(VALVULA_MOVIMIENTO, LOW);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 11: // Antes era paso 11, ahora es paso 9 efectivo
if (millis() - tiempoInicioDoblez >= 900) {
digitalWrite(VALVULA_PESTANA_GRANDE_INT, LOW);
tiempoInicioDoblez = millis();
pasoDoblez++;
return false;
}
return false;
case 12: // Antes era paso 12, ahora es paso 10 efectivo
if (millis() - tiempoInicioDoblez >= 500) {
pasoDoblez = 0; // Reiniciar la secuencia
dobladoActivado = false; // Resetear la bandera de activación
return true; // Doblado completado
}
return false;
default:
pasoDoblez = 0;
dobladoActivado = false;
return true;
}
}
// Función para activar el paro de emergencia y detener todo el sistema
void activarParoEmergencia() {
// Detener todos los componentes inmediatamente
controlMotor(false); // Apagar motor AC
digitalWrite(PISTON_TOLVA, LOW); // Desactivar pistón
// Apagar todas las electroválvulas
const int actuadores[] = {
// VALVULA_ALIMENTADOR, // ELIMINADA
VALVULA_PESTANA_CHICA,
VALVULA_PESTANA_GRANDE_INT, VALVULA_MOVIMIENTO,
VALVULA_PESTANA_GRANDE_EXT};
for(int pin : actuadores) {
digitalWrite(pin, LOW);
}
// Actualizar estados y LEDs
estadoActual = EMERGENCIA;
digitalWrite(LED_EMERGENCIA, HIGH); // Encender LED de emergencia
digitalWrite(LED_CICLO, LOW); // Apagar LED de ciclo activo
dobladoActivado = false; // Asegurar que el doblado se detenga
pasoDoblez = 0; // Reiniciar el paso del doblado
sensorDobladoDetectado = false; // Resetear la detección del sensor
tiempoSensorDobladoActivado = 0;
Serial.println("PARO DE EMERGENCIA ACTIVADO - Requiere reset manual");
}
// Función para restablecer completamente el sistema a su estado inicial
void resetSistemaCompleto() {
// Reiniciar todos los componentes y estados
controlMotor(false); // Asegurar que el motor AC esté apagado
digitalWrite(PISTON_TOLVA, LOW);
digitalWrite(LED_EMERGENCIA, LOW); // Apagar LED de emergencia
// Apagar todas las salidas relacionadas con el ciclo
const int salidasCiclo[] = {
// VALVULA_ALIMENTADOR, // ELIMINADA
VALVULA_PESTANA_CHICA,
VALVULA_PESTANA_GRANDE_INT, VALVULA_MOVIMIENTO,
VALVULA_PESTANA_GRANDE_EXT, LED_CICLO};
for(int pin : salidasCiclo) {
digitalWrite(pin, LOW);
}
// Reiniciar variables de estado
materialPerdido = false;
tiempoInicioPiston = 0;
tiempoDeteccionBanda = 0;
pasoDoblez = 0;
dobladoActivado = false;
sensorDobladoDetectado = false; // Resetear la detección del sensor
tiempoSensorDobladoActivado = 0;
Serial.println("Sistema reseteado");
}
// ===== CONFIGURACIÓN INICIAL (SETUP) =====
void setup() {
// Configurar pines de entrada
pinMode(SENSOR_TOLVA, INPUT_PULLUP);
pinMode(SENSOR_BANDA, INPUT_PULLUP);
pinMode(SENSOR_DOBLADO, INPUT_PULLUP);
pinMode(PARO_EMERGENCIA, INPUT_PULLUP);
pinMode(BOTON_INICIO, INPUT_PULLUP);
pinMode(BOTON_RESET, INPUT_PULLUP);
// Configurar pines de salida e inicializarlos a LOW (apagados)
const int salidas[] = {
// VALVULA_ALIMENTADOR, // ELIMINADA
VALVULA_PESTANA_CHICA,
VALVULA_PESTANA_GRANDE_INT, VALVULA_MOVIMIENTO,
VALVULA_PESTANA_GRANDE_EXT, PISTON_TOLVA,
CONTROL_MOTOR_AC, // Pin de control del relé del motor AC
LED_TOLVA, LED_CICLO, LED_EMERGENCIA};
for(int pin : salidas) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW); // Asegura que todas las salidas estén apagadas al inicio
}
// Corregido: Si tu módulo de relé activa con HIGH, esta línea lo apaga al inicio.
// Si tu módulo se activa con LOW, deberías cambiarla a HIGH para apagarlo.
// Dada tu descripción, asumimos que se activa con HIGH y ponemos LOW para apagar.
digitalWrite(CONTROL_MOTOR_AC, LOW);
Serial.begin(9600); // Iniciar comunicación serial para depuración
Serial.println("Sistema de doblado inicializado. Esperando inicio.");
}
// ===== BUCLE PRINCIPAL (LOOP) =====
void loop() {
// --- Lectura de Entradas (sensores y botones) ---
// Los !digitalRead() son porque usamos INPUT_PULLUP, que da LOW cuando el botón/sensor está activo.
bool paroEmergenciaActivo = !digitalRead(PARO_EMERGENCIA);
bool resetSistema = !digitalRead(BOTON_RESET);
bool inicioDobladoActivo = !digitalRead(SENSOR_DOBLADO); // Sensor que activa la secuencia de doblado
bool inicioCiclo = !digitalRead(BOTON_INICIO); // Botón para iniciar el ciclo
bool materialEnTolva = !digitalRead(SENSOR_TOLVA); // Sensor de material en la tolva
bool materialEnBanda = !digitalRead(SENSOR_BANDA); // Sensor de material en la banda
// --- Comprobación de Reset (Alta Prioridad) ---
// Permite resetear el sistema en cualquier momento, incluso durante una emergencia.
if (resetSistema) {
resetSistemaCompleto();
estadoActual = ESPERA; // Vuelve al estado de espera
Serial.println("Reset activado - Volviendo a estado ESPERA");
delay(500); // Pequeño retardo para debouncing del botón de reset
return; // Sale del loop actual para comenzar uno nuevo desde el principio
}
// --- Comprobación de Paro de Emergencia (Máxima Prioridad) ---
// Si la emergencia está activa, se llama a la función de paro y el loop se reinicia.
if (paroEmergenciaActivo) {
activarParoEmergencia();
return; // Sale del loop actual; el sistema permanecerá en emergencia hasta un reset.
}
// --- Actualización de LEDs Indicadores ---
digitalWrite(LED_TOLVA, materialEnTolva);
digitalWrite(LED_CICLO, estadoActual != ESPERA && estadoActual != EMERGENCIA); // Ciclo activo si no está en espera o emergencia
digitalWrite(LED_EMERGENCIA, estadoActual == EMERGENCIA); // LED de emergencia solo en estado de emergencia
// --- Máquina de Estados Principal ---
// La lógica principal del sistema se ejecuta según el estado actual.
switch(estadoActual) {
case ESPERA:
// Espera a que se presione el botón de inicio y haya material en la tolva.
if(inicioCiclo && materialEnTolva) {
estadoActual = CICLO_CONTINUO;
controlMotor(true); // Enciende el motor AC
Serial.println("Ciclo iniciado. Motor encendido.");
}
break;
case CICLO_CONTINUO:
// Mantiene el motor encendido mientras el material se mueve por la banda.
controlMotor(true); // Mantener el motor AC encendido
// Verifica si se agotó el material en la tolva durante el ciclo.
if(!materialEnTolva && !materialPerdido) {
materialPerdido = true; // Marca que el material se agotó
Serial.println("Advertencia: Material en tolva agotado. El ciclo terminará al finalizar el doblado actual.");
}
// Si el material es detectado por el sensor de banda, pasa al estado PROCESANDO.
if(materialEnBanda) {
estadoActual = PROCESANDO;
tiempoInicioPiston = millis(); // Guarda el tiempo para el pistón
tiempoDeteccionBanda = millis(); // Guarda el tiempo de detección en banda
digitalWrite(PISTON_TOLVA, HIGH); // Activa el pistón de la tolva
Serial.println("Material detectado en banda. Pistón activado.");
}
break;
case PROCESANDO:
// El motor sigue encendido mientras el pistón actúa y se espera el retardo.
controlMotor(true); // Mantener el motor AC encendido
// Desactiva el pistón después de su duración.
if(millis() - tiempoInicioPiston >= DURACION_PISTON) {
digitalWrite(PISTON_TOLVA, LOW); // Desactivar pistón de tolva
}
// Espera un retardo adicional después de la detección en banda antes de detener el motor.
if(millis() - tiempoDeteccionBanda >= RETARDO_DETENCION_MOTOR) {
controlMotor(false); // Detener motor AC
estadoActual = DOBLANDO; // Pasa al estado de doblado
Serial.println("Motor detenido. Listo para doblado.");
}
break;
case DOBLANDO:
// Gestiona la activación y ejecución de la secuencia de doblado.
// Lógica para detectar y temporizar el sensor de doblado (SENSOR_DOBLADO).
if (inicioDobladoActivo) {
if (!sensorDobladoDetectado) { // Si es la primera vez que se detecta
sensorDobladoDetectado = true;
tiempoSensorDobladoActivado = millis();
Serial.println("Sensor de doblado detectado.");
} else {
// Si el sensor sigue activo y ha pasado el retardo, activa la secuencia de doblado.
if (millis() - tiempoSensorDobladoActivado >= 400 && !dobladoActivado) {
dobladoActivado = true; // Activa la bandera para iniciar la secuencia
Serial.println("Inicio de la secuencia de doblado.");
}
}
} else {
// Si el sensor ya no está activo, reinicia las variables de detección.
sensorDobladoDetectado = false;
tiempoSensorDobladoActivado = 0;
}
// Ejecuta la secuencia de doblado si la bandera `dobladoActivado` está en true.
if (dobladoActivado) {
if (secuenciaDobladoNoBloqueante()) { // Si la secuencia de doblado ha terminado
if(materialPerdido) {
estadoActual = ESPERA; // Si no hay más material, vuelve a ESPERA
materialPerdido = false; // Resetear la bandera
Serial.println("Ciclo finalizado por falta de material. Volviendo a ESPERA.");
} else {
estadoActual = CICLO_CONTINUO; // Si hay más material, reinicia el ciclo
controlMotor(true); // Reinicia el motor AC
Serial.println("Doblado completado. Reiniciando ciclo.");
}
}
} else {
pasoDoblez = 0; // Asegura que la secuencia se reinicie si no se ha activado aún
}
break;
case EMERGENCIA:
// El sistema permanece en este estado hasta que se presione el botón de RESET.
// La lógica para salir de este estado ya está en la comprobación de reset al inicio del loop.
break;
}
delay(50); // Pequeño retardo para estabilidad. Considera implementar debouncing no bloqueante.
}