Programa maquina textil.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
5.6 KiB

enum Reles {
Rele1,
Rele2,
Rele3,
MAX_RELE,
};
/* Configuracion */
// Tiempos de espera antes de emitir senyales de salida de rele.
// Unidades en milisegundos (1s = 1000ms).
const unsigned long TIEMPO_ESPERA_SALIDA_MS[MAX_RELE] = {
5000, // Rele 1.
2000, // Rele 2.
3000, // Rele 3.
};
// Pines reles.
//
// Pines 0 y 1 en Arduino UNO son para comunicacion serie, no usar.
const int Rele_Pin[MAX_RELE] = {
2, // Rele 1.
3, // Rele 2.
4, // Rele 3.
};
// Pin pulsador.
const int Pulsador_Pin = 5;
enum Estado {
Estado_Inicial,
Espera_Rele1,
Salida_Rele1,
Espera_Rele2,
Salida_Rele2,
Espera_Rele3,
Salida_Rele3,
Estado_Final,
MAX_ESTADO,
};
enum Transicion {
Automatica, // Transicion automatica.
Retardada, // Transicion automatica retardada.
Manual, // Transicion al pulsar boton.
};
const Transicion transiciones[MAX_ESTADO] = {
Manual, // Estado_Inicial -> Espera_Rele1
Retardada, // -> Salida_Rele1
Manual, // -> Espera_Rele2
Retardada, // -> Salida_Rele2
Manual, // -> Espera_Rele3
Retardada, // -> Salida_Rele3
Manual, // -> Estado_Final
Automatica, // -> Estado_Inicial
};
constexpr int RELE_ACTIVADO = LOW;
constexpr int RELE_DESACTIVADO = HIGH;
/* Entrada digital con debounce. */
// Tiempo en el que la senyal debe permanecer con un valor constante para
// que se ejecute la lectura logica de la senyal.
const unsigned long DEBOUNCE_DELAY_MS = 25;
// Entrada digital.
struct EntradaDigital {
int pin; // Pin de entrada.
int estado; // Estado logico actual, LOW o HIGH.
int ultima_senyal; // Ultima senyal de entrada, LOW o HIGH.
unsigned long debounce_time_ms; // Tiempo del ultimo cambio de estado en la entrada.
};
// Lee un cambio de estado de la entrada digital.
// Devuelve cierto si se ejecuta un cambio de estado logico, falso en caso contrario.
bool leer_cambio_de_estado(EntradaDigital& entrada, unsigned long tiempo) {
const int senyal_actual = digitalRead(entrada.pin);
bool estado_cambiado = false;
if (senyal_actual != entrada.ultima_senyal) {
entrada.debounce_time_ms = tiempo;
}
else if (
((tiempo - entrada.debounce_time_ms) >= DEBOUNCE_DELAY_MS) &&
(senyal_actual != entrada.estado) ){
entrada.estado = senyal_actual;
estado_cambiado = true;
}
entrada.ultima_senyal = senyal_actual;
return estado_cambiado;
}
/* Programa principal. */
Estado estado_actual;
EntradaDigital pulsador;
unsigned long tiempo_ultima_transicion;
// Ejecuta una transicion de estado y devuelve el nuevo estado.
Estado ejecutar_transicion(Estado estado, unsigned long tiempo) {
tiempo_ultima_transicion = tiempo;
return Estado((estado + 1) % MAX_ESTADO);
}
// Actualiza la salida despues de un cambio de estado.
void actualizar_salida(Estado estado_actual) {
switch (estado_actual) {
case Estado_Inicial:
break;
case Espera_Rele1:
digitalWrite(LED_BUILTIN, HIGH);
break;
case Salida_Rele1:
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(Rele_Pin[Rele1], RELE_ACTIVADO);
break;
case Espera_Rele2:
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(Rele_Pin[Rele1], RELE_DESACTIVADO);
break;
case Salida_Rele2:
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(Rele_Pin[Rele2], RELE_ACTIVADO);
break;
case Espera_Rele3:
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(Rele_Pin[Rele2], RELE_DESACTIVADO);
break;
case Salida_Rele3:
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(Rele_Pin[Rele3], RELE_ACTIVADO);
break;
case Estado_Final:
digitalWrite(Rele_Pin[Rele3], RELE_DESACTIVADO);
break;
default:
break;
}
}
// Devuelve el tiempo de espera para el estado dado.
unsigned long get_tiempo_espera(Estado estado) {
switch (estado) {
case Espera_Rele1:
return TIEMPO_ESPERA_SALIDA_MS[Rele1];
case Espera_Rele2:
return TIEMPO_ESPERA_SALIDA_MS[Rele2];
case Espera_Rele3:
return TIEMPO_ESPERA_SALIDA_MS[Rele3];
default:
return 0;
}
}
// Inicializacion.
void setup() {
const unsigned long tiempo = millis();
for (int i = 0; i < MAX_RELE; ++i) {
pinMode(Rele_Pin[i], OUTPUT);
digitalWrite(Rele_Pin[i], RELE_DESACTIVADO);
}
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
pinMode(Pulsador_Pin, INPUT_PULLUP);
estado_actual = Estado_Inicial;
pulsador = (EntradaDigital) {
.pin = Pulsador_Pin,
.estado = LOW,
.ultima_senyal = LOW,
.debounce_time_ms = tiempo,
};
tiempo_ultima_transicion = tiempo;
}
// Bucle principal.
void loop() {
const unsigned long tiempo = millis();
const Estado estado_original = estado_actual;
switch (transiciones[estado_actual]) {
case Automatica:
estado_actual = ejecutar_transicion(estado_actual, tiempo);
break;
case Retardada: {
const unsigned long tiempo_espera = get_tiempo_espera(estado_actual);
if ( (tiempo - tiempo_ultima_transicion) >= tiempo_espera ) {
estado_actual = ejecutar_transicion(estado_actual, tiempo);
}
break;
}
case Manual: {
// Para una senyal INPUT_PULLUP, se lee LOW, no HIGH, cuando se presiona
// el boton.
const bool pulsador_estado_cambiado = leer_cambio_de_estado(pulsador, tiempo);
if (pulsador_estado_cambiado && pulsador.estado == LOW) {
estado_actual = ejecutar_transicion(estado_actual, tiempo);
}
break;
}
}
if (estado_actual != estado_original) {
actualizar_salida(estado_actual);
}
}