Ir al contenido principal

Arduino - MEF - Apertura de puertas automáticas

 

1        Máquina de Estados Finitos – Sistema de Puertas automáticas

1.1     Definición

 

1.2     Estados

1.      Estado Cerrado (totalmente Cerrado)

2.      Estado Abriendo

3.      Estado Abierto (totalmente Abierto)

4.      Estado Cerrando

1.3     Transiciones

a.      De Cerrado a Abriendo: Se solicitó abrir. Puede ser por un botón, por detectar cercanía, por detectar movimiento, o por mensaje de otro dispositivo (serial)

b.     De Abriendo a Abierto: Se llegó hasta el fin, accionamiento del botón “final de carrera”

c.      De Abierto a Cerrando: Se solicita cerrar. Puede ser por un botón, por no detectar cercanía o por no detectar movimiento (y por ende, un tiempo ha transcurrido), o por mensaje de otro dispositivo. Sugiero que deba haber un temporizador.

1.4     Componentes y conexiones

1.      Sensor de Apertura (x1, x2) à Sensor de movimiento (PIR) o de distancia (Ultrasonidos HC-SR04).

2.      Sensor de límite totalmente Abierto (x1) à Botón

3.      Sensor de Cierre (x0) à Temporizador

4.      Sensor de límite totalmente Cerrado (x1) à Botón

5.      Relé para el motor de apertura (x1) à Relé, alternativamente un LED

6.      Relé para el motor de cierre (x1) à Relé, alternativamente un LED

1.5     Implementación

1.5.1    Sensor de un sólo lado

1.      Primero, preparar trucos para programar más fácilmente:

// Trucos de C++

#define ENTER "\n"

 

template<class CualquierTipo> inline Print

&operator << (Print &izq, CualquierTipo der )

{

  izq.print( der ) ;

  return izq ;

}

 

2.      Inicializar librerías. Creo que no necesitamos ninguna, así que saltearemos esta parte.

3.      Generar los pines.

#define PIN_DETECTOR 3

#define PIN_FINAL_ABIERTO 4

#define PIN_FINAL_CERRADO 5

#define PIN_RELE_ABRIR 6

#define PIN_RELE_CERRAR 7

4.      Creación de variables para dispositivos complejos. Como no hay, salteamos.

5.      Creación de variables de medición de sensores

float

  _medicionPersonaCerca = 0

  , _medicionFinalAbierto = 0

  , _medicionFinalCerrado = 0

  ;

6.      Creación de las variables de los estados

float _tiempoEstado = 0.0f ;

int _estado = 0 ;

String _pcDice = "" ;

7.      Definición de los Estados para la máquina

#define ESTADO_CERRADO 0

#define ESTADO_ABRIENDO 1

#define ESTADO_ABIERTO 2

#define ESTADO_CERRANDO 3

8.      Establecemos el setup() básico:

void setup() {

  Serial.begin( 9600 ) ;

  Serial << "arduino:conectado" << ENTER ;

  Serial.setTimeout( 10 ) ;

 

9.      Definimos modos de los pines e inicializamos dispositivos complejos, si los hubiere.

  pinMode( PIN_DETECTOR, INPUT ) ;

  pinMode( PIN_FINAL_CERRADO, INPUT ) ;

  pinMode( PIN_FINAL_ABIERTO, INPUT ) ;

  pinMode( PIN_RELE_ABRIR, OUTPUT ) ;

  pinMode( PIN_RELE_CERRAR, OUTPUT ) ;

10. Habilitamos el primer estado, cerramos la función setup() y comenzamos la loop().

  fnCambiarAEstadoCerrado() ;

}

void loop() {

  _pcDice = "" ;

  if( Serial.available() ) {

    _pcDice = Serial.readString() ;

    _pcDice.trim() ;

  }

11. Armamos la máquina de estados finitos.

  if( _estado == ESTADO_CERRADO )

    fnEstadoCerrado() ;

  else if( _estado == ESTADO_ABRIENDO )

    fnEstadoAbriendo() ;

  else if( _estado == ESTADO_ABIERTO )

    fnEstadoAbierto() ;

  else if( _estado == ESTADO_CERRANDO )

    fnEstadoCerrando() ;

  ;

  delay( 100 ) ;

  _tiempoEstado = _tiempoEstado + 100.00f ;

}

12. Pensemos en cada estado. En el estado cerrado, estaremos esperando a que un usuario se acerque a un lado de la puerta (y/o al otro), o de la computadora venga algún mensaje adecuado.

void fnEstadoCerrado() {

  _medicionPersonaCerca = digitalRead( PIN_DETECTOR ) ;

  if( _medicionPersonaCerca == HIGH ) {

    return fnCambiarAEstadoAbriendo() ;

  }

  if( _pcDice == "abrir" ) {

    return fnCambiarAEstadoAbriendo() ;

  }

}

13. Estado abriendo. Tenemos que esperar a que la puerte llegue a su destino.

void fnEstadoAbriendo() {

  _medicionFinalAbierto = digitalRead(PIN_FINAL_ABIERTO);

  if( _medicionFinalAbierto == HIGH ) {

    return fnCambiarAEstadoAbierto() ;

  }

}

14. Estado abierto. Esperamos a que pase el tiempo, o a que de la computadora venga un mensaje.

void fnEstadoAbierto() {

  if( _tiempoEstado >= 3000 ) {

    return fnCambiarAEstadoCerrando() ;

  }

  if( _pcDice == "cerrar" ) {

    return fnCambiarAEstadoCerrando() ;

  }

}

15. Estado cerrando, como el estado abriendo, deberemos esperar a que llegue a su destino.

void fnEstadoCerrando() {

  _medicionFinalCerrado = digitalRead(PIN_FINAL_CERRADO);

  if( _medicionFinalCerrado == HIGH ) {

    return fnCambiarAEstadoCerrado() ;

  }

}

16. Ahora pensemos en las transiciones. Son todas parecidas, al menos en este proyecto. En las transiciones deberemos:

a.      Cambiar el estado.

b.     Reinicializar el tiempo.

c.      Avisar el cambio a la PC.

d.     Activar o desactivar actuadores

void fnCambiarAEstadoAbriendo() {

  _estado = ESTADO_ABRIENDO ;

  _tiempoEstado = 0.00f ;

  Serial << "estado:" << ESTADO_ABRIENDO << ENTER ;

  Serial << "Abriendo puertas" << ENTER ;

  digitalWrite( PIN_RELE_ABRIR, HIGH ) ;

}

void fnCambiarAEstadoAbierto() {

  _estado = ESTADO_ABIERTO ;

  _tiempoEstado = 0.00f ;

  Serial << "estado:" << ESTADO_ABIERTO << ENTER ;

  Serial << "Puertas abiertas" << ENTER ;

  digitalWrite( PIN_RELE_ABRIR, LOW ) ;

}

void fnCambiarAEstadoCerrando() {

  _estado = ESTADO_CERRANDO ;

  _tiempoEstado = 0.00f ;

  Serial << "estado:" << ESTADO_CERRANDO << ENTER ;

  Serial << "Cerrando puertas" << ENTER ;

  digitalWrite( PIN_RELE_CERRAR, HIGH ) ;

}

void fnCambiarAEstadoCerrado() {

  _estado = ESTADO_CERRADO ;

  _tiempoEstado = 0.00f ;

  Serial << "estado:" << ESTADO_CERRADO << ENTER ;

  Serial << "Puertas cerradas" << ENTER ;

  digitalWrite( PIN_RELE_CERRAR, LOW ) ;

}

 

 

1.5.2    Sensor de 2 lados

Variamos al proyecto para tener 2 detectores de presencia o movimiento.

Del punto 3, agregamos la definición del PIN_DETECTOR2

#define PIN_DETECTOR2 8

Del punto 5, agregamos la variable de su medición, antes del punto y coma.

float

  // …

  , _medicionDetector2 = 0

  ;

Redefinimos al estado cerrado para detectar a la persona con el segundo detector.

void fnEstadoCerrado() {

  _medicionPersonaCerca =

    digitalRead( PIN_DETECTOR )

    + digitalRead( PIN_DETECTOR2 )

  ;

  if( _medicionPersonaCerca ) {

    return fnCambiarAEstadoAbriendo() ;

  }

  if( _pcDice == "abrir" ) {

    return fnCambiarAEstadoAbriendo() ;

  }

}

 

1.6     Mejoras

Como en muchos estados las condiciones dispararían al mismo cambio de estado, podríamos juntarlas todas en mi mismo IF() con el operador lógico || (or), cuestión que si ocurre una posibilidad o la otra, igual se cumpliría. Incluso, ni hace falta utilizar la expresión return; esto se utilizaría en contextos en que no queremos que continuara otra regla.

void fnEstadoCerrado() {

  _medicionPersonaCerca =

    digitalRead( PIN_DETECTOR )

    + digitalRead( PIN_DETECTOR2 )

  ;

  if(

    _medicionPersonaCerca

    || _pcDice == "abrir"

  ) {

    fnCambiarAEstadoAbriendo() ;

  }

}

 

 

n   

Comentarios

Entradas populares de este blog

Arduino - MEF - Sistema detector Rayos UV

  Propuesta de mejora de código sin MEF proyecto Sensor UV Código para el Arduino La siguiente tabla es el código de Arduino que propongo, sin Máquina de Estados Finitos, explicado paso a paso. En principio podrían copiar cada parte en orden y probarlo en el Arduino. Primero propongo unos truquitos del lenguaje C++ // Trucos de C++ #define ENTER "\n"   template<class CualquierTipo> inline Print &operator << (Print &izq, CualquierTipo der ) {   izq.print( der ) ;   return izq ; }   A continuación, incluir las librerías necesarias. Hasta el momento, incluyeron ustedes el de DHT (Detector de Humedad y Temperatura Relativa DHT22) y la pantallita LCD 16x2 mediante Protocolo I2C. Para “conversar” en dicho protocolo se necesita la librería Wire.h nativa de Arduino C++.   // Incluir librerías   #include <DHT.h> ...

Probando ChatGPT - Mapa conceptual con Mermaid

 Había conversado con ChatGPT acerca de cuidado de las plantas e hidroponía. Luego de unos días me di cuenta que quizás también podría saber acerca de crear Mapas conceptuales. Salió lo siguiente; le falta un concepto para crear correctamente mapas conceptuales (la relación entre los conceptos), pero podría ser algo para ayudarnos a corregir mejor. El texto original era el que cito a continuación, pero le agregué explícitamente que me armara un "mapa conceptual" utilizando el lenguaje Mermaid, un lenguaje descriptivo que permite construir gráficos diversos, entre ellos Mapas conceptuales, generando un archivo SVG. ``` Hacé un mapa conceptual en lenguaje Mermaid con el siguiente texto, redactado anteriormente: "La hidroponía es un método de cultivo que se utiliza para cultivar plantas sin suelo utilizando una solución nutriente y agua. Algunas plantas pueden cultivarse con éxito mediante hidroponía, mientras que otras necesitan el suelo para crecer y prosperar. De las pl...

Implementar LiteRT-LM

LiteRT-LM 1       Algoritmo de LiteRT-LM En un SCRIPT de tipo Módulo, extraeremos el objeto Engine de la librería LiteRT-LM: JavaScript de tipo Módulo, luego de creado el BODY import { Engine } from "https://cdn.jsdelivr.net/npm/@litert-lm/core/+esm"; // Objeto window.MecanismoLiteRT = Engine ; // Objeto   Ahora vamos a crear el mecanismo de chat (chat engine) pero antes tenemos que descargar el cerebro computado (modelo de IA). JavaScript, continuación de lo anterior u otro SCRIPT con top-await const _URL_CEREBRO = "https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it-web.litertlm"; // Frase/String   // Tarda lo que tenga que tardar descargando 1915 MB de información let _cerebroDescargado = await fnDescargarCerebro( _URL_CEREBRO ) ; // Objeto URL // Listo, ahora compilará el Cerebro; en PCs con 4 GB de RAM esto ...