En esta entrada voy a tratar de sistematizar una forma de hacer los programas de Arduino basada en la teoría de autómatas finitos. Lo haré aplicándolo a la puerta de garaje y en concreto para la siguiente secuencia:
La puerta está cerrada, tocamos el pulsador y se va abriendo cuando toca el final de carrera de puerta abierta, la puerta se detiene.
Con la puerta abierta, tocamos el pulsador y se va cerrando, cuando toca el final de carrera de puerta cerrada, la puerta se detiene.
Para esa secuencia tenemos las siguientes entradas, salidas y estados:
Entradas: Pulsador, final de carrera de puerta cerrada (FCC) y final de carrera de puerta abierta(FCA).
Salidas: Motor parado, motor abriendo, motor cerrando.
Estados: Puerta cerrada, puerta abriéndose, puerta abierta, puerta cerrándose.
DIAGRAMA DE TRANSICIÓN DE ESTADOS.
Los estados los represento con círculos y junto a las flechas de las transiciones he dibujado un rectángulo dividido en dos celdas. En la superior he escrito la entrada que produce ese cambio de estado y en la inferior la salida correspondiente
PROGRAMA DE ARDUINO.
A partir del diagrama de transición se pasa al programa de Arduino con el selector SWITCH. Los CASE son los estados. Las transiciones se hacen con el selector IF en el que la condición es la entrada y en el bloque se incluye la salida y el cambio de estado/CASE.
Con la sentencia ENUM, se pone nombre a los estados. Para las salidas he usado funciones.
#define PinAv 9
#define PinRe 6
#define FCA 4 //Final de carrera puerta abierta
#define Pulsador 11 //Para iniciar las maniobras
#define FCC 2 //Final de carrera puerta cerrada
int antirrebotes = 200;
void setup()
{
pinMode(PinAv, OUTPUT);
pinMode(PinRe, OUTPUT);
pinMode(FCA, INPUT_PULLUP);
pinMode(Pulsador, INPUT_PULLUP);
pinMode(FCC, INPUT_PULLUP);
}
//MANIOBRAS DEL MOTOR
void motor_abriendo(){
digitalWrite(PinAv, HIGH);
digitalWrite(PinRe, LOW);}
void motor_cerrando(){
digitalWrite(PinAv, LOW);
digitalWrite(PinRe, HIGH);}
void motor_parado(){
digitalWrite(PinAv, LOW);
digitalWrite(PinRe, LOW);}
enum {puertaCerrada, puertaAbriendose, puertaAbierta, puertaCerrandose};
int estado = puertaCerrada; //El programa empieza con la puerta //cerrada
void loop(){
switch (estado){
case puertaCerrada:
if (digitalRead(Pulsador) == 0 ){
delay(antirrebotes);
motor_abriendo();
estado= puertaAbriendose;}
break;
case puertaAbriendose:
if (digitalRead(FCA) == 0){
delay(antirrebotes);
motor_parado();
estado= puertaAbierta;}
break;
case puertaAbierta:
if (digitalRead(Pulsador) == 0)
{delay(antirrebotes);
motor_cerrando();
estado= puertaCerrandose;}
break;
case puertaCerrandose:
if (digitalRead(FCC)==0){
motor_parado();
delay(antirrebotes);
estado= puertaCerrada;}
break;
}}
DETALLE DE LAS CONEXIONES ELÉCTRICAS
Conexiones eléctricas
Hay algún ligero cambio entre los cableados de la foto y del plano.
MÁS DIAGRAMAS DE ESTADOS QUE CORRESPONDEN A OTRAS FUNCIONALIDADES DE LA PUERTA.
OBSERVACIONES
El motor que aparece en la foto y el video es distinto al de la entrada anterior. Lo he tenido que sustituir porque con el otro se producía un fenómeno denominado ruido eléctrico que afectaba al Arduino evitando que funcionara correctamente.