NODE RED - MQTT

 NODE RED-MQTT




FUNCIONAMIENTO

En este proyecto, vamos a controlar el movimiento de un servo y el encendido de un LED utilizando Node Red y MQTT. Este ejercicio se puede dividir en dos partes, una sería la parte que tenemos en una ubicación (en este caso en mi casa) y otra parte la que tenemos en otra ubicación distinta (en este caso en el colegio). El objetivo de la práctica, es el de mover un servomotor que se encuentra en casa, mediante comandos de voz que se indican a través de un micrófono desde el colegio. También se va a poder encender y apagar un LED ubicado en mi casa desde cualquier ubicación mediante una página creada con nodered. En el colegio, tendremos también un sensor de ultrasonidos, con el que podremos medir la distancia de un objeto respecto al sensor. A continuación se indica que elementos componen la parte ubicada en mi casa y los elementos que componen la parte ubicada en el centro.


EN CASA

-Raspberry pi 4 que contendrá MQTT, Node-Red y una web cam.

-Desde Node-Red controlaremos el encendido y el apagado del LED.

-Mediante la webcam podremos ver tanto el servo como el LED.

-Un ESP32 que estará suscrito al TOPIC de posicionamiento del servo y lo controlará.





EN EL COLEGIO

-Raspberry pi 4 con un micrófono, un altavoz y el sensor de ultrasonidos.

-La raspberry pi 4 tendrá un programa escrito en Python que realizará lo siguiente:

    - Un mensaje de voz nos pedirá que digamos los grados en los que deseemos          que se posicione el servo

    - Tras escuchar el mensaje, diremos en voz alta la posición del servo.

    - Con la ayuda de la librería PAHO, publicaremos los grados escuchados.

    - La raspi estará publicando la distancia a un objeto que pondremos delante del       sensor de ultrasonidos HCSR04





 
ABRIR PUERTOS

Para posibilitar la comunicación con el MQTT y con la página creada en Nodered (ambos alojados en la raspberry de casa), deberemos abrir los puertos del router. En este caso, el puerto que deberemos abrir para la comunicación con el MQTT, es el 1883, para Nodered es el 1880.

Además, deberemos de asignar estos puertos a un dispositivo de nuestra red de casa. El dispositivo al que le vamos a asignar estos puertos es la raspberry. Indicamos que va a a ser la raspberry introduciendo su dirección IP . Es importante que en la propia raspberry configuremos una dirección IP estática, para que esta no cambie y se pierda la comunicación.

En resumen, cuando al router le lleguen datos o solicitudes por los puertos 1880 o 1883, él va a saber que dispositivo gestiona esos puertos y le va a enviar los datos recibidos.

Para abrir los puertos deberemos de acceder a la configuración de nuestro router, introduciendo las credenciales.

En primer lugar, estando conectados a nuestra red de casa, introduciremos la dirección IP de nuestro router (esta dirección la podemos encontrar en la parte trasera del router o encontrarla fácilmente buscando en la red). Una vez introducida la dirección IP, se nos pedirá un usuario y una contraseña, los cuales encontraremos también en la parte trasera del router. Una vez dentro de la interfaz del router. A continuación se muestran los pasos para abrir los puertos en un router Vodafone.


Abrir puertos



En primer lugar, introduciremos las credenciales.



Abrir puertos



Para poder acceder a la redirección de puertos, deberemos seleccionar el modo experto.



Abrir puertos



En la pestaña de Internet, tendremos acceso a un submenú llamado Redirección de puertos, clicando sobre el accederemos a la pantalla que se muestra en la imagen superior. En este caso, todavía no había ningún puerto configurado, para configurar uno, deberemos clicar en el símbolo de +.



MAQUINA DE ESTADOS

La gran mayoría del código del útil, se va a escribir en Python, este código va a estar estructurado como una máquina de estados finita, a continuación se expone lo que es una máquina de estados finita.

Una máquina de estados es un modelo de comportamiento de un sistema con entradas y salidas en dónde las salidas no dependen únicamente de las entradas actuales, sino que dependen también de las entradas anteriores. Se llama máquina de estados finita debido a que tiene un número de estados finito.

Esta máquina de estados, va a tener dos estados, un estado en el cual posicionaremos el servo, y otro estado en el que leeremos distancia. En estos estados, se realizan mas tareas, como reconocimiento de voz, salida de audio, publicación en los Topics del MQTT.


CODIGO

El código correspondiente a esta máquina de estados, se divide en dos partes, una primera en la que se definen todas las funciones del programa, y una segunda que se puede decir que es la máquina de estados en sí, en esta segunda parte: Se crean los estados, se establecen las transiciones de un estado a otro, se llaman a las distintas funciones, etc. A continuación se expone la parte del código que contiene las funciones.


Funciones (estados) FSM

En primer lugar, se importan todas las librerías que se van a utilizar en la máquina de estados, estas librerías, solamente será necesario importarlas en el sketch que contiene las funciones de la máquina de estados.


Estados fsm


Las librerías que se importan son para distintas aplicaciones, como la representación de tiempos, el reconocimiento de voz, el control de los GPIO, salida de audio, publicación en MQTT, interactuar con el sistema operativo.



Estado 0 -  Lectura sensor de ultrasonidos


Estado 0



En primer lugar, se configuran los GPIO que vamos a utilizar, en este caso, para este sensor, dos pines, el pin de trigger o disparo, y el pin de echo. El pin de trigger va a ser una salida, ya que será por donde se emita el pulso. El pin de echo, será una entrada ya que será por donde se reciba el rebote del pulso emitido por el trigger.

Dentro de un While true (bucle infinito), encontramos las líneas de código correspondientes a la lectura de distancia mediante el sensor de ultrasonidos. El funcionamiento de este sensor es bastante sencillo, por un lado se emite un pulso de ultrasonidos y se guarda el tiempo en el que se ha emitido el pulso. Por otro lado, recibe el rebote del pulso emitido y guarda el tiempo en el momento en el que se ha recibido el pulso, resta los dos tiempos y se obtiene el tiempo que ha tardado en ir, rebotar y volver. Sabiendo que la señal viaja a la velocidad del sonido, podemos saber la distancia aplicando al fórmula de distancia = (velocidad*tiempo)/2, se divide entre dos porque al medir el tiempo de ida y el de vuelta, se obtiene una lectura del doble de la distancia real.



Estado 0



La primera línea del código de la imagen superior, es la correspondiente a la publicación de la distancia en el MQTT. Por un lado, indicamos el topic en el que vamos a publicar, que en este caso es ('MQTT_DISTANCIA'), por otro lado indicamos el payload o carga, que es el valor de la variable distancia. Finalmente indicamos la IP donde se encuentra el MQTT, es la IP pública del router al que esta conectada la raspi con el servidor MQTT.

La función de este estado, devuelve un argumento, este argumento es el valor de la variable salida. Una vez publicamos un valor, se pone la variable salida a True y se sale del bucle, devolviendo el valor de la variable salida. 


Estado 1- Posicionamiento del servo


Estado 1



En las líneas de código de la imagen superior, se muestra la función de posicionamiento del servo, en primer lugar, se llama a un archivo mp3, el cual solicita que se indique un numero entre 0 y 180. A continuación se abre el recurso que permite captar voz por medio del micrófono y almacenarla como texto, indicamos la posición y la almacena como tipo entero. En función del valor obtenido del reconocimiento de voz hace una cosa u otra, por ejemplo, si no te ha entendido, indica que ha ocurrido un error de lectura y te pide que lo intentes otra vez, en el caso de que se indique un valor superior a los límites del servo, lo indicara también, diciendo que posiciones el servo entre 0 u 180 grados. En el caso favorable de que te entienda y además el valor este entre 0 y 180 grados, se publicara en el topic 'MQTT_GRADOS_SERV' , el valor de la variable grados. Una vez publicado el valor de grados, se pondrá la variable salida en true y saldremos del bucle.


Sketch máquina de estados


A continuación se va a exponer el sketch de la máquina de estados finita.



Máquina de estados



En el fragmento de código que se muestra en la imagen superior, se importan las librerías necesarias para el funcionamiento de la máquina de estados, como se puede ver no es necesario importar las librerías utilizadas en el sketch de los estados. La librería fysom es la necesaria para la creación de la máquina de estados, el sketch realizado previamente llamado 'estados_fsm', se importa en este programa como una librería mas. La variable salida, la inicializamos a False.



Máquina de estados



En el fragmento de código que se muestra en la imagen superior, se definen todos los parámetros de la máquina de estados, como el estado inicial, el nombre de los estados, y la fuente y el destino de cada uno de los estados.



Máquina de estados



El fragmento de código que se muestra en la imagen superior, es el correspondiente al estado uno de la máquina de estados, es decir, a la lectura de distancia por medio del sensor de ultrasonidos. 

En primer lugar, mostramos en que estado se encuentra la máquina, a continuación llamamos a la función uno_dos, que si recordamos, se encuentra en el sketch 'estados_fsm' y es la correspondiente a la lectura de distancia por medio del sensor de ultrasonidos. El parámetro que devuelve esta función, lo guardamos en la variable salida y va a ser el valor de esta variable el que determine si se permanece en el estado o si se sale del mismo y se transiciona la siguiente. En caso de que la variable salida sea True, transicionamos al estado dos mediante la función UNO_DOS() de la máquina de estados.



Máquina de estados


El código que se muestra en la imagen superior es el correspondiente a el estado dos, es decir al posicionamiento del servo, como se puede ver es igual que el estado anterior. En las últimas líneas, podemos ver las instrucciones de salida, estas líneas son necesarias para cerrar correctamente el programa, cerrando los recursos correctamente.


Sketch ESP-32

A continuación se muestra el código correspondiente a la subscripción al topic 'MQTT_GRADOS_SERV' de MQTT en el cual se publicaba la posición en grados del servo. En este caso y con este sketch, nos vamos a subscribir para obtener la posición en la que se desea posicionar el servo para después posicionarlo.



Sketch ESP



Como se muestra en las líneas de código de la imagen superior, se van a importar las librerías correspondientes para conectar el ESP 32 a la red wifi, para controlar el servo y para subscribirnos al topic. Vamos también a introducir las credenciales wifi de la red a la que nos vamos a conectar así como la dirección IP del dispositivo en el que se encuentra el MQTT. Si nos encontramos dentro de la misma red que el dispositivo, pondremos la IP local del mismo, si estamos conectados a una red distinta, lo que haremos será indicar la IP pública del router al que esta conectado el dispositivo, y como  hemos visto anteriormente, el router gestiona a que dispositivo envía la orden que le enviemos. También en estas líneas, podemos ver la función de conexión a la red wifi (setup_wifi()).



Sketch ESP



En la función callback() vemos si ha llegado algún mensaje, si el topic al que llega el mensaje es igual a 'MQTT_GRADOS_SERV' entonces guardamos el contenido de este mensaje como tipo int en la variable pos. Después con la función  Write() de la librería Esp32Servo, enviaremos el servo a una posición igual al valor que se ha recogido en la variable pos.




Sketch ESP



Finalmente en estas últimas líneas de código, lo que hacemos es llamar a las funciones definidas previamente como setup_wifi() o callback. Además, definimos el servidor al que vamos nos vamos a conectar. Para conectarnos debemos indicar el socket, es decir, la dirección IP más el puerto. El puerto para MQTT como se ha indicado anteriormente es el 1883.



MONTAJE

A continuación, se muestran imágenes del montaje de la práctica.



Raspberry colegio- ultrasonidos



En la imagen superior, se muestra la raspberry ubicada en el aula del colegio, con el sensor de ultrasonidos conectado.



Raspberry casa



En la imagen superior, podemos ver la raspberry ubicada en casa, podemos ver también el ESP-32 con el que controlaremos el servo, el LED que controlaremos desde Node Red, y el propio servomotor.


ENLACES DE DESCARGA

A continuación se añadirán enlaces de descarga para poder descargar el código expuesto en esta entrada del blog.








Comentarios

Entradas populares de este blog

ESCRITURA/LECTURA PT100 LABVIEW

ADQUISICION DE DATOS LABVIEW (DAQ)

MEDIDOR DE CO2