Archivo de la etiqueta: Librerías Arduino

Uso de Librerías Arduino

La instalación, actualización y manejo librerías en Arduino es un aspecto importante a la hora de usar Arduino, veamos unos ejemplos. Para aprender a instalar librerías lo mejor es practicar, veamos unos ejemplos de instalación de algunas librerías muy útiles.

Cuando se va a instalar una librería, la primera tarea es leer la documentación y aprender a usarla, ya sea leyendo el código, viendo los ejemplos o revisando la documentación si está disponible.

Pasos para realizar los ejemplos propuestos:

  • Leer la documentación y entender que hace la librería.
  • Buscar e instalar la librería desde el gestor de librerías, si está disponible.
  • Descargar el .zip del repositorio de github si no está en el gestor de librerías. Botón Download zip
  • Abrir alguno de los ejemplo suministrados por las librerías, leer el código, entender que hace y ejecutarlo en Arduino.

Desinstalar librerías: Para desinstalar una librería simplemente borrar el directorio de la librería situado en la ruta configurada en las preferencias de Arduino y reiniciar el IDE.

Librería MsTimer2

MsTimer2 nos ofrece muchas utilidades de temporización muy útiles en el trabajo diario con Arduino.

Instalar la librería MsTimer2 desde el gestor de librerías. Ejecutar el programa de ejemplo incluido en la librería para hacer blink (FlashLed) en el led integrado sin necesidad de usar la instrucción delay().

Esquema de conexiones:

Documentación de la librería: http://playground.arduino.cc/Main/MsTimer2

Nueva versión de la librería: http://www.pjrc.com/teensy/td_libs_MsTimer2.html

Repositorio: https://github.com/PaulStoffregen/MsTimer2 

Librería Timer

La librería Timer es otra de librería de muy interesante de temporización más flexible pero menos exacta de MsTimer2. Esta librería no está disponible en el gestor de librerías.

Documentación de la librería: http://www.doctormonk.com/2012/01/arduino-timer-library.html

Repositorio: https://github.com/JChristensen/Timer 

Instalar la librería timer y ejecutar los ejemplos blink2 y read_A0_flashLED.

Esquema conexión blink2 (prestar atención al código y poner los leds a los pines correctos):

Esquema conexión read_A0_flashLED (prestar atención al código y poner el led al pin correcto o cambiar el código):

Comparación comportamiento librería msTimer2 y Timer: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Otros/compara_timers 

Librería Time

La librería Time que añade funcionalidades de mantenimiento de fecha y hora en Arduino sin necesidad de un hardware externo. También permite obtener fecha y hora como segundo, minuto, hora, día, mes y año.

Librería: http://playground.arduino.cc/Code/Time

Documentación: http://www.pjrc.com/teensy/td_libs_Time.html

Repositorio: https://github.com/PaulStoffregen/Time 

Instalar la librería Time desde el gestor de librerías y ejecutar el ejemplo TimeSerial. Para ver la hora que debemos mandar a Arduino en el ejemplo ver https://www.epochconverter.com/ 

Librería para sonda temperatura/humedad DHT.

Librería para manejar un elemento HW como la sonda de temperatura y humedad DHT22.

Señal de comunicación:

Web del sensor: http://www.seeedstudio.com/depot/grove-temperaturehumidity-sensor-pro-p-838.html 

Documentación: http://www.seeedstudio.com/wiki/Grove_-_Temperature_and_Humidity_Sensor_Pro

Datasheet: https://arduino-info.wikispaces.com/file/view/DHT22.pdf/556588503/DHT22.pdf 

Repositorio: https://github.com/Seeed-Studio/Grove_Temperature_And_Humidity_Sensor

En este caso en el gestor de librerías tenemos dos librerías disponibles:

Pero la tienda donde lo compro me recomienda usar la librería https://github.com/Seeed-Studio/Grove_Temperature_And_Humidity_Sensor

Además de estas tres librerías, existen muchas más. Cualquiera de las librerías para la sonda DHT22 vale para usarla, pero cada una de ellas funciona diferente y cada una de ellas tiene sus ventajas e inconvenientes.

Mi recomendación es la librería DHTstable de Rob Tillaart: https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTstable 

Versión modificada de la librería: https://github.com/jecrespo/DHTlib 

Probar varias librerías y comparar su uso.

Librería Pantalla LCD I2C

Ver este ejemplo: https://aprendiendoarduino.wordpress.com/2018/10/17/pantalla-lcd-i2c-en-arduino/

Instalar la librería LiquidCrystal_I2C del gestor de librerías. Más información https://github.com/marcoschwartz/LiquidCrystal_I2C

En función de la pantalla que compremos TFT, LCD, OLED, etc… hay que buscar que chip disponen y seleccionar la librería adecuada:

Anuncios

Sonda DS18B20 con Arduino

Un sonda de temperatura muy usada con Arduino es la DS18B20, esta usa un bus de comunicación multipunto llamado one wire, lo que nos permite leer muchas sondas con una sola i/o digital.

Sonda: http://www.seeedstudio.com/depot/One-Wire-Temperature-Sensor-p-1235.html

Datasheet sensor: http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf

Librería: http://playground.arduino.cc/Learning/OneWire

Última versión de la librería OneWire:

Existen librerías para la sonda DS18B20 que facilita el trabajo:

Protocolo one-wire:

Esquema de montaje. El bus 1-Wire necesita una resistencia de pull-up de 4K7, y que podemos alimentar el sensor directamente a través del pin Vdd o usar el modo “parásito” y alimentarlo con la propia línea de datos.

Para poder usar las sonda DS18B20 necesitaremos las librerías OneWire y DallasTemperature. Solo hay que buscar e instalar la librería a través del Gestor de Librerías.

Leer la sonda conectada al pin 2:

Código: https://github.com/jecrespo/Arduino-Kit-China-Guide/blob/master/12-DS18B20/12-DS18B20.ino

Más información:

MQTT

MQTT son las siglas de Message Queue Telemetry Transport y tras ellas se encuentra un protocolo ideado por IBM y liberado para que cualquiera podamos usarlo enfocado a la conectividad Machine-to-Machine (M2M).

MQTT fue creado por el Dr. Andy Stanford-Clark de IBM y Arlen Nipper de Arcom — ahora Eurotech — en 1999 como una forma rentable y confiable de conectar los dispositivos de monitoreo utilizados en las industrias del petróleo y el gas a servidores empresariales remotos. Cuando se les planteó el reto de encontrar la manera de enviar los datos de los sensores de los oleoductos en el desierto a sistemas SCADA externos (control de supervisión y adquisición de datos), decidieron utilizar una topología de publicación/suscripción basada en TCP/IP que se basaría en los eventos para mantener bajos los costos de transmisión de los enlaces satelitales.

Aunque MQTTT todavía está estrechamente asociado con IBM, ahora es un protocolo abierto que es supervisado por la Organización para el Avance de los Estándares de Información Estructurada (OASIS).

Web: http://mqtt.org/

Está enfocado al envío de datos en aplicaciones donde se requiere muy poco ancho de banda. Además, sus características le permiten presumir de tener un consumo realmente bajo así como precisar de muy pocos recursos para su funcionamiento.

Estas características han hecho que rápidamente se convierta en un protocolo muy empleado en la comunicación de sensores y, consecuentemente, dentro del Internet de las Cosas.

MQTT es un protocolo pensado para IoT que está al mismo nivel que HTTP o CoAP:

Comparativa MQTT y CoAP:

Un aspecto importante a tener en cuenta de los dispositivos IoT no es solamente el poder enviar datos al Cloud/Servidor, sino también el poder comunicarse con el dispositivo, en definitiva la bidireccionalidad. Este es uno de los beneficios de MQTT: es un modelo brokered, el cliente abre una conexión de salida al bróker, aunque el dispositivo esté actuando como Publisher o subscriber. Esto normalmente evita los problemas con los firewalls porque funciona detrás de ellos o vía NAT.

En el caso de que la comunicación principal se base en HTTP, la solución tradicional para enviar información al dispositivo sería HTTP Polling. Esto es ineficiente y tiene un coste elevado en aspectos de tráfico y/o energía. Una manera más novedosa de hacerlo sería con el protocolo WebSocket, que permite crear una conexión HTTP completa bidireccional. Esto actúa de canal socket (parecido al canal típico TCP) entre el servidor y el cliente. Una vez establecido, ya es trabajo del sistema escoger un protocolo para hacer un túnel sobre la conexión.

El Transporte de telemetría de cola de mensajes (MQTT) es un protocolo de código abierto que se desarrolló y optimizó para dispositivos restringidos y redes de bajo ancho de banda, alta latencia o poco confiables. Es un transporte de mensajería de publicación/suscripción que es extremadamente ligero e ideal para conectar dispositivos pequeños a redes con ancho de banda mínimo. El MQTT es eficiente en términos de ancho de banda, independiente de los datos y tiene reconocimiento de sesión continua, porque usa TCP. Tiene la finalidad de minimizar los requerimientos de recursos del dispositivo y, a la vez, tratar de asegurar la confiabilidad y cierto grado de seguridad de entrega con calidad del servicio.

El MQTT se orienta a grandes redes de dispositivos pequeños que necesitan la supervisión o el control de un servidor de back-end en Internet. No está diseñado para la transferencia de dispositivo a dispositivo. Tampoco está diseñado para realizar “multidifusión” de datos a muchos receptores. El MQTT es simple y ofrece pocas opciones de control. Las aplicaciones que usan MQTT, por lo general, son lentas en el sentido de que la definición de “tiempo real” en este caso se mide habitualmente en segundos.

Más información:

MQTT también es un protocolo que está cobrando mucha importancia en la industria (IIoT). MQTT (Message Queuing Telemetry Transport, ‘Cola de mensajes telemetría y transporte’) es un protocolo publicar/suscribir diseñado para SCADA. Se centra en un mínimo encabezado (dos bytes de cabeza) y comunicaciones confiables. También es muy simple. Tal como HTTP, la carga MQTT es específica para la aplicación, y la mayoría de las implementaciones usan un formato JSON personalizado o binario.

MQTT en PLCs: https://www.youtube.com/watch?v=aX20J-sLyKU

Comparativa MQTT y Modbus: http://inubo.es/noticia/comparativa-entre-mqtt-y-modbus-como-protocolos-iot

MQTT es interesante usarlo cuando el ancho de banda bajo y no conozca su infraestructura. Asegúrese de que su proveedor tenga un broker MQTT a quien le pueda publicar información, y siempre asegure la comunicación con TLS (Transport Layer Security, ‘seguridad en la capa de transporte’).

Por ejemplo, MQTT sería una buena opción para monitorizar y controlar los paneles solares. MQTT es un protocolo de publicación/suscripción con brokers de mensajes centrales. Cada panel solar puede contener un nodo IoT que publique mensajes de tensión, corriente y temperatura.

MQTT está diseñado para minimizar el ancho de banda, lo que lo convierte en una buena opción para el monitoreo satelital de la línea de transmisión, pero hay una trampa. La ausencia de metadatos en las cabeceras de los mensajes significa que la interpretación de los mensajes depende completamente del diseñador del sistema.

Para compensar las redes poco fiables, MQTT soporta tres niveles de Calidad de Servicio (QoS):

  • Disparar y olvidar (0) – Fire and Forget – At most once
  • Al menos una vez (1) – At least once
  • Exactamente una vez (2) – Exactly once

Si se solicita el nivel de calidad de servicio 1 ó 2, el protocolo gestiona la retransmisión de mensajes para garantizar la entrega. La calidad de servicio puede ser especificada por los clientes de publicación (cubre la transmisión del publicador al broker) y por los clientes suscriptores (cubre la transmisión de un broker a un suscriptor).

MQTT QoS 2 aumentará la latencia porque cada mensaje requiere dos handshake completos de ida y vuelta del remitente al receptor (cuatro en total del publicador al suscriptor).

En un patrón de publicación/suscripción es difícil saber la diferencia entre “Ha pasado mucho tiempo desde que supe de mi publicador” y “Mi publicador murió”. Ahí es donde entra en juego la Última Voluntad y el Testamento (LWT) de MQTT. Los clientes pueden publicar mensajes sobre temas específicos (por ejemplo, aisle15/rack20/panel5/FalloSensor) para que se entreguen si se desconectan sin enviar un mensaje de “desconexión”. Los mensajes se almacenan en el broker y se envían a cualquier persona que se haya suscrito al tema.

MQTT de un vistazo

  • Ancho de banda muy bajo
  • TCP/IP
  • Publicar/suscribir transferencia de mensajes
  • Topología de muchos a muchos a través de un broker central
  • Sin metadatos
  • Tres niveles de QoS
  • Última Voluntad y Testamento revela nodos desconectados

Las ventajas de usar el protocolo MQTT son:

  • Es asíncrono con diferentes niveles múltiples de calidad del servicio, lo que resulta ser importante en los casos donde las conexiones de Internet son poco confiables.
  • Envía mensajes cortos que se vuelven adecuados para las situaciones de un bajo ancho de banda.
  • No se requiere de mucho software para implementar a un cliente, lo cual lo vuelve fantástico para los dispositivos como Arduino con una memoria limitada.
  • Podemos cifrar los datos enviados y usar usuario y password para proteger nuestros envíos.

Si quisiera grabar en una BBDD con MQTT, un suscriptor a una serie de topis se encarga de grabar los datos cada vez que cambia un valor o cada cierto tiempo, por ejemplo con un script de python o ejecutando Node-RED en una máquina virtual o en el propio servidor (o Raspberry Pi) donde corre el briker (Mosquitto):

NodeRed no es más que un software que se instala en un nodo aunque se instale en el mismo servidor que el broker.

Cinco cosas a saber de MQTT: https://www.ibm.com/developerworks/community/blogs/5things/entry/5_things_to_know_about_mqtt_the_protocol_for_internet_of_things?lang=en

Buen artículo sobre MQTT: https://internetofthingsagenda.techtarget.com/definition/MQTT-MQ-Telemetry-Transport

Recursos MQTT:

Para ampliar información de MQTT en Arduino y Raspberry Pi:

Buenos artículos de MQTT en español:

Arquitectura MQTT

MQTT (Message Queue Telemetry Transport), un protocolo usado para la comunicación machine-to-machine (M2M) en el “Internet of Things”. Este protocolo está orientado a la comunicación de sensores, debido a que consume muy poco ancho de banda y puede ser utilizado en la mayoría de los dispositivos empotrados con pocos recursos (CPU, RAM, …).

Un ejemplo de uso de este protocolo es la aplicación de Facebook Messenger tanto para android y Iphone. La arquitectura de MQTT sigue una topología de estrella, con un nodo central que hace de servidor o “broker”. El broker es el encargado de gestionar la red y de transmitir los mensajes, para mantener activo el canal, los clientes mandan periódicamente un paquete (PINGREQ) y esperan la respuesta del broker (PINGRESP). La comunicación puede ser cifrada entre otras muchas opciones.

En esta forma de comunicación se desacoplan los clientes que publican (Publisher) de los que consumen los datos (Suscribers). Eso significa que los clientes no se conocen entre ellos unos publican la información y otros simplemente la consumen, simplemente todos tienen que conocer al message broker.

El desacoplamiento se produce en tres dimensiones:

  • En el espacio: El publicador y el suscriptor no tienen porqué conocerse.
  • En el tiempo: El publicador y el suscriptor no tienen porqué estar conectados en el mismo momento.
  • En la sincronización: las operaciones en cualquiera de los dos componentes no quedan interrumpidas mientras se publican o se reciben mensajes.

Es precisamente el broker el elemento encargado de gestionar la red y transmitir los mensajes.

Una característica interesante es la capacidad de MQTT para establecer comunicaciones cifradas lo que aporta a nuestra red una capa extra de seguridad.

La comunicación se basa en unos “topics” (temas), que el cliente que publica el mensaje crea y los nodos que deseen recibirlo deben subscribirse a él. La comunicación puede ser de uno a uno, o de uno a muchos.

Dentro de la arquitectura de MQTT, es muy importante el concepto “topic” o “tema” en español ya que a través de estos “topics” se articula la comunicación puesto que emisores y receptores deben estar suscritos a un “topic” común para poder entablar la comunicación. Este concepto es prácticamente el mismo que se emplea en colas, donde existen un publicadores (que publican o emiten información) y unos suscriptores (que reciben dicha información) siempre que ambas partes estén suscritas a la misma cola.

Este tipo de arquitecturas, lleva asociada otra interesante característica: la comunicación puede ser de uno a uno o de uno a muchos.

Un “topic” se representa mediante una cadena y tiene una estructura jerárquica. Cada jerarquía se separa con ‘/’.

Por ejemplo, “edificio1/planta5/sala1/raspberry2/temperatura” o “/edificio3/planta0/sala3/arduino4/ruido“. De esta forma se pueden crear jerarquías de clientes que publican y reciben datos, como podemos ver en la imagen:

De esta forma un nodo puede subscribirse a un “topic” concreto (“edificio1/planta2/sala0/arduino0/temperatura”)  o a varios (“edificio1/planta2/#”).

Existen dos comodines en MQTT para suscribirse a varios topics:

  • Multi-level Wildcard: # (se suscribe a todos los hijos bajo esa cola)
  • Single Level Wildcard: + (se suscribe solo a ese nivel)

Un carácter de tema especial, el carácter dólar ($), excluye un tema de cualquier suscripción de root wildcard. Normalmente, el $ se utiliza para transportar mensajes específicos del servidor o del sistema.

Ejemplos de Topics MQTT Válidos:

  • casa/prueba/topic
  • casa/+/topic
  • casa/#
  • casa/+/+
  • +/#
  • #

Explicación del comodín de single level:

Escalado MQTT

MQTT me permite gran escalabilidad. Añadir un nuevo Arduino o un suscriptor es muy sencillo dentro de la jerarquía vista

Con escalable me refiero a la capacidad que tiene un sistema para ser ampliado. Los sistemas de sensores en general, particularmente en nuestro caso hablamos del mundillo del Internet de las Cosas, se caracterizan por enviar muchos datos de pequeño tamaño en tiempo real ya que hay muchos sensores transmitiendo simultáneamente y cada breves periodos de tiempo, cuya información necesita ser consumida por otros elementos en tiempo real.

En una Arquitectura basada en Broker es fundamental evitar el SPOF (punto único de fallo).

En el contexto MQTT hay 2 estrategias principales:

  • Bridging: hace forward de mensajes a otro bróker MQTT. Es la solución de HiveMQ, Mosquitto, IBM MQ
  • Clustering: soportando añadido dinámico de nodos al cluster. Lo usa ActiveMQ, HiveMQ o RabbitMQ.

Cuando un sistema de estas características se empieza a saturar se bloquean las comunicaciones y se pierde la característica de “tiempo real”.

Hasta ahora, todos los sistemas que habíamos visto se basaban en un cliente que se comunicaba con un servidor. Si cualquier cliente se intenta comunicar con un servidor que está procesando tanta información que, en ese momento, no es capaz de trabajar con más contenido, el sistema entero fallará, o bien porque se satura y bloquea a nivel global o porque empieza a descartar aquella información que no puede procesar (lo que es inadmisible en muchos caso, imagina una alarma de Riesgo de Explosión en tu cocina porque se ha detectado una fuga de gas…).

Existen varias formas de abordar esta problemática pero, a día de hoy, una de las más empleadas es usar sistemas de colas donde se deja toda la información y el encargado de procesarla va “sacando” de esta cola la información. De esta manera, si ponemos más “encargados de procesamiento” son capaces de vaciar más rápido la cola si viésemos que está se está empezando a llenar y, de cara a los sensores, no sería necesario hacer ningún cambio, ya que ellos siempre envían al mismo sitio.

MQTT no hace exactamente lo mismo ya que, para empezar, no hay colas sino “topics” pero la filosofía es muy parecida, permitiendo a grandes sistemas operar con total fluidez y, junto con sus optimizaciones que buscan entre otras cosas reducir consumos y tamaños de trama para poder operar en elementos embebidos, es el motivo por el que es un protocolo tan empleado en comunicaciones M2M.

Además, nos permite una gestión de la seguridad razonablemente sencilla que facilita que nuestros sistemas se comporten de una forma más robusta.

MQTT será el nexo entre hardware (sensor) y todos los elementos típicos del mundo software (servidores, bases de datos, Big Data). En esta capa nos preocupamos de que la información llegue a un sistema que posteriormente se ocupa de distribuirlo entre las demás partes y nos da igual lo que haya a partir de ese momento y su tamaño. Puede que no tengamos nada más que una web de visualización o puede que tengamos un complejo sistema de Machine Learning y Big Data. Puede que seamos un particular enviando un dato de temperatura a un panel de visualización en su Raspberry o puede que seamos una multinacional que controla en tiempo real su producción de amoniaco a nivel global bajando y subiendo la carga de producción en sus diferentes fábricas según los costes de transporte y el consumo de sus diferentes centros de distribución. Nos es lo mismo a este nivel porque nosotros hacemos sólo una cosa y la hacemos bien: enviar datos de un dispositivo hardware a un sistema mucho mayor. Es lo que se llama microservicios que ha popularizado netflix (http://enmilocalfunciona.io/arquitectura-microservicios-1/)

MQTT Sobre Websockets

MQTTT es una arquitectura de publicación/suscripción que se desarrolla principalmente para conectar dispositivos con ancho de banda y potencia limitada a través de redes inalámbricas. Es un protocolo simple y ligero que corre sobre sockets TCP/IP o WebSockets.

MQTT sobre WebSockets puede ser asegurado con SSL. La arquitectura de publicación/suscripción se basa en eventos que permiten enviar mensajes a los dispositivos cliente. El broker MQTT es el punto central de comunicación, y se encarga de despachar todos los mensajes entre los remitentes y los destinatarios legítimos. Un cliente es cualquier dispositivo que se conecta al corredor y puede publicar o suscribirse a temas para acceder a la información.

Un tema contiene la información de enrutamiento para el broker. Cada cliente que quiere enviar mensajes publica sobre un tema determinado, y cada cliente que quiere recibir mensajes se suscribe a un tema determinado. El corredor entrega todos los mensajes con el tema correspondiente a los clientes apropiados.

Sólo necesitará ejecutar MQTTT en sockets web si desea publicar/suscribirse a mensajes directamente desde webapps.

Buena web para estar al día de MQTT: https://www.hivemq.com/blog/

Más información:

Para saber más sobre MQTT leer esta serie de Artículos:

Protocolo MQTT

MQTT está diseñado para requerir una sobrecarga mínima del protocolo para cada paquete con el fin de preservar el ancho de banda para los dispositivos embebidos con recursos limitados. Es un marco de trabajo realmente sencillo para la gestión de redes mesh de dispositivos habilitados para TCP.

Los mensajes MQTT se entregan asincrónicamente (“push”) a través de la arquitectura publish subscribe. El protocolo MQTTT funciona intercambiando una serie de paquetes de control MQTT de una manera definida. Cada paquete de control tiene un propósito específico y cada bit del paquete se crea cuidadosamente para reducir los datos transmitidos a través de la red.

Publish and subscribe:

MQTT specificaction: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

Una sesión MQTT se divide en cuatro etapas: conexión, autenticación, comunicación y terminación. Un cliente comienza creando una conexión TCP/IP con el broker utilizando un puerto estándar o un puerto personalizado definido por los operadores del broker. Al crear la conexión, es importante reconocer que el servidor puede continuar una sesión antigua si se le proporciona una identidad de cliente reutilizada.

Los puertos estándar son el 1883 para la comunicación no cifrada y el 8883 para la comunicación cifrada mediante SSL/TLS. Durante el handshake SSL/TLS, el cliente valida el certificado del servidor para autenticar el servidor.

MQTT es llamado un protocolo ligero porque todos sus mensajes tienen una pequeña huella de código. Cada mensaje consta de una cabecera fija, una cabecera variable opcional, una carga útil de mensaje limitada a 256 MB de información y un nivel de calidad de servicio (QoS).

MQTTT soporta BLOBS (Binary Large Object) de mensajes de hasta 256 MB de tamaño. El formato del contenido es específico de la aplicación. Las suscripciones de temas se realizan utilizando un par de paquetes SUBSCRIBE/SUBACK. La anulación de la suscripción se realiza de forma similar utilizando un par de paquetes UNSUBSCRIBE/UNSUBACK.

Durante la fase de comunicación, el cliente puede realizar operaciones de publicación, suscripción, cancelación (unsuscribe) y ping. La operación de publicación envía un bloque binario de datos, el contenido, a un topic  definido por el publisher.

La operación de ping al servidor del broker usando una secuencia de paquetes PINGREQ/PINGRESP, que se usa para saber si está viva la conexión. Esta operación no tiene otra función que la de mantener una conexión en vivo y asegurar que la conexión TCP no ha sido apagada por una pasarela o un router.

Cuando un publicador o suscriptor desea finalizar una sesión MQTT, envía un mensaje DISCONNECT al briker y, a continuación, cierra la conexión. Esto se denomina “graceful shutdown” porque le da al cliente la posibilidad de volver a conectarse fácilmente al proporcionarle su identidad de cliente y reanudar el proceso donde lo dejó.

Si la desconexión ocurre repentinamente sin tiempo para que un publisher envíe un mensaje DISCONNECT, el broker puede enviar a los suscriptores un mensaje del publisher que el broker ha almacenado previamente en caché. El mensaje, que se llama testamento, proporciona a los suscriptores instrucciones sobre qué hacer si el editor muere inesperadamente.

MQTT tiene 14 tipos de mensajes, normalmente un usuario sólo usa los mensajes de CONNECT, PUBLISH, SUBSCRIBE Y UNSUBSCRIBE. Si quereis conocer los tipos de mensajes podéis consultarlos en: https://dzone.com/refcardz/getting-started-with-mqtt

Más información: https://internetofthingsagenda.techtarget.com/definition/MQTT-MQ-Telemetry-Transport

Para saber más sobre el protocolo MQTT y aplicaciones:

Calidad de Servicio MQTT (QoS)

Al enviar mensajes MQTT existe la posibilidad que los mensajes no lleguen al destinatario.

El envío de mensajes sin saber con seguridad que fueron recibidos se llama “QoS 0” (cero).

Es posible que también desee QoS 1, que le permite saber que el mensaje fue recibido. Básicamente, después de cada publicación, el suscriptor dice “OK”. En el lenguaje MQTT se llama “PUBACK” (Reconocimiento de publicación).

También está QoS 2, que no sólo garantiza que su mensaje fue recibido, sino que sólo fue recibido una vez. Esto es un poco más complejo porque necesitas empezar a rastrear los IDs de los paquetes, así que lo dejaremos para más adelante.

Los niveles de calidad de servicio (QoS) determinan cómo se entrega cada mensaje MQTT y deben especificarse para cada mensaje enviado a través de MQTT. Es importante elegir el valor de QoS adecuado para cada mensaje, ya que este valor determina la forma en que el cliente y el servidor se comunican para entregar el mensaje. Con el uso de MQTT se podrían lograr tres niveles de calidad de servicio para la entrega de mensajes:

  • QoS 0 (A lo sumo una vez – at most once) – donde los mensajes se entregan de acuerdo con los mejores esfuerzos del entorno operativo. Puede haber pérdida de mensajes. Confía en la fiabilidad del TCP. No se hacen retransmisiones.
  • QoS 1 (Al menos una vez – at least once) – donde se asegura que los mensajes lleguen, pero se pueden producir duplicados. El Receiver recibe el mensaje por lo menos una vez. Si el receiver no confirma la recepción del mensaje o se pierde en el camino el Sender reenvía el mensaje hasta que recibe por lo menos una confirmación. Pueden duplicarse mensajes.
  • QoS 2 (Exactamente una vez – exactly once) – donde se asegura que el mensaje llegue exactamente una vez. Eso incrementa la sobrecarga en la comunicación pero es la mejor opción cuando la duplicación de un mensaje no es aceptable.

Existe una regla simple cuando se considera el impacto del rendimiento de la QoS. Es “Cuanto mayor sea la QoS, menor será el rendimiento“. MQTT proporciona flexibilidad a los dispositivos de IoT para elegir la calidad de servicio apropiada que necesitarían para sus requisitos funcionales y ambientales.

Último deseo y Testamento (MQTT LWT)

Un cliente puede establecer un mensaje Last Will and Testament (LWT) en el momento en el que conecta conecta con el Broker MQTT. Si el cliente no desconecta correctamente el Broker envía el mensaje LWT.

Cuando un cliente MQTT se conecta al servidor MQTT puede definir un tema y un mensaje que necesita ser publicado automáticamente sobre ese tema cuando se desconecta inesperadamente. Esto también se llama “Ultima voluntad y testamento” (LWT). Cuando el cliente se desconecta inesperadamente, el temporizador keep alive del lado del servidor detecta que el cliente no ha enviado ningún mensaje o el PINGREQ keep alive. Por lo tanto, el servidor publica inmediatamente el mensaje Will en el tema Will especificado por el cliente.

La función LWT puede ser útil en algunos escenarios. Por ejemplo, para un cliente MQTT remoto, esta función se puede utilizar para detectar cuando los dispositivos IoT salen de la red. La función LWT se puede utilizar para crear notificaciones para una aplicación que esté supervisando la actividad del cliente.

Paquete:

Ver explicación completa en: https://learn.adafruit.com/mqtt-adafruit-io-and-you/qos-and-wills

Más información: https://www.ibm.com/developerworks/community/blogs/5things/entry/5_things_to_know_about_mqtt_the_protocol_for_internet_of_things?lang=en

Otros Conceptos MQTT

  • Cada mensaje MQTT puede ser enviado como un mensaje con retención (retained), en este caso cada nuevo cliente que conecta a un topic recibirá el último mensaje retenido de ese tópico.
  • Cuando un cliente conecta con el Broker puede solicitar que la sesión sea persistente, en ese caso el Broker almacena todas las suscripciones del cliente, todos los mensajes QoS 1 y 2 no procesados o perdidos por el cliente
  • Un mensaje MQTT CONNECT contiene un valor keepAlive en segundos donde el cliente establece el máximo tiempo de espera entre intercambio de mensajes

Seguridad MQTT

Ya sabemos lo importante que es la seguridad, y más en escenarios IoT en el que comunican objetos entre sí.  MQTT confía en tecnologías estándares para esto:

  • Autenticación usuario/Password
  • Seguridad SSL/TLS

Los puertos estándar son el 1883 para la comunicación no cifrada y el 8883 para la comunicación cifrada mediante SSL/TLS. Durante el handshake SSL/TLS, el cliente valida el certificado del servidor para autenticar el servidor. El cliente también puede proporcionar un certificado de cliente al broker durante el handshake, que el broker puede utilizar para autenticar al cliente. Aunque no forma parte específica de la especificación MQTT, se ha convertido en habitual que los broker admitan la autenticación de clientes con certificados SSL/TLS del lado del cliente.

Dado que el protocolo MQTTT pretende ser un protocolo para dispositivos con recursos limitados y de IoT, el SSL/TLS puede no ser siempre una opción y, en algunos casos, puede no ser deseable. En estos casos, la autenticación se presenta como un nombre de usuario y contraseña de texto claro que el cliente envía al servidor como parte de la secuencia de paquetes CONNECT/CONNNACK. Algunos brokers, especialmente los brokers abiertos publicados en Internet, aceptan clientes anónimos. En tales casos, el nombre de usuario y la contraseña simplemente se dejan en blanco.

Reto MQTT: Seguridad, Interoperabilidad y Autenticación

Debido a que el protocolo MQTT no fue diseñado con la seguridad en mente, el protocolo ha sido tradicionalmente utilizado en redes back-end seguras para propósitos específicos de la aplicación. La estructura temática de MQTT puede fácilmente formar un árbol enorme, y no hay una manera clara de dividir un árbol en dominios lógicos más pequeños que puedan ser federados. Esto dificulta la creación de una red MQTT globalmente escalable porque, a medida que crece el tamaño del árbol temático, aumenta la complejidad.

Otro aspecto negativo de MQTT es su falta de interoperabilidad. Debido a que las cargas útiles de mensajes son binarias, sin información sobre cómo están codificadas (sin metadatos), pueden surgir problemas, especialmente en arquitecturas abiertas en las que se supone que las diferentes aplicaciones de los diferentes fabricantes funcionan a la perfección entre sí.

MQTT tiene características de autenticación mínimas incorporadas en el protocolo. El nombre de usuario y las contraseñas se envían en texto claro y cualquier forma de uso seguro de MQTT debe emplear SSL/TLS, que, lamentablemente, no es un protocolo ligero.

Autenticar clientes con certificados del lado del cliente no es un proceso simple, y no hay manera en MQTT, excepto el uso de medios propietarios fuera de banda, para controlar quién posee un topic y quién puede publicar información sobre él. Esto hace que sea muy fácil inyectar mensajes dañinos, ya sea intencionadamente o por error, en la red.

Además, no hay forma de que el receptor del mensaje sepa quién envió el mensaje original a menos que esa información esté contenida en el mensaje real. Las características de seguridad que tienen que ser implementadas sobre MQTT de forma propietaria aumentan la huella de código (footprint) y hacen que las implementaciones sean más difíciles.

MQTT vs HTTP (REST API)

La diferencia entre una REST API y MQTT es que MQTT mantiene una conexión hacia el servicio abierta y puede responder mucho más rápido a los cambios en el feed. La REST API solo conecta al servicio cuando se hace una petición (request) y es más apropiada para proyecto donde el dispositivo permanece en modo sleep (para reducir el consumo) y despierta solo para mandar o recibir datos. (Push vs pull)

Push = websocket

Pull = REST API

HTTP no tiene estado (stateless), por lo que debe tener una conexión por cada transferencia de datos: una conexión cada vez que desee escribir datos, una conexión para la lectura. HTTP es ideal para grandes cantidades de datos, como los que se utilizan para sitios web, y se puede utilizar para conexiones IoT. Pero no es ligero y no es muy rápido. Otro problema con HTTP es que es sólo pull.

MQTTT es un gran protocolo. Es extremadamente sencillo y ligero. La conexión a un servidor sólo tarda unos 80 bytes. Usted permanece conectado todo el tiempo, cada dato ‘publicación’ (datos push de un dispositivo a otro) y cada dato ‘suscripción’ (datos push de un servidor a otro) es de unos 20 bytes. Ambos ocurren casi instantáneamente.

MQTT puede funcionar sobre cualquier tipo de red, ya sea una red mesh, TCP/IP, Bluetooth, etc.

Si se usa MQTT usando Bluetooth, XBee, Bluetooth LE, LoRA u otro protocolo y dispositivo no conectado a Internet, ¡necesitarás una pasarela!

Ejemplo de gatewaty: https://learn.adafruit.com/datalogging-hat-with-flora-ble/

Clientes MQTT

Existen muchos clientes y librerías para MQTT, puesto que se trata de un protocolo libre sencillo de implementar.

Una aplicación de cliente MQTT se encarga de recopilar información del dispositivo de telemetría, conectar con el servidor y publicar la información en el servidor. También puede suscribirse a temas, recibir publicaciones y controlar el dispositivo de telemetría.

Cliente online: http://www.hivemq.com/demos/websocket-client/

Los mejores clientes MQTT: https://www.hivemq.com/blog/seven-best-mqtt-client-tools

Tres herramientas MQTT y como simular MQTT: https://dzone.com/articles/top-3-online-tools-to-simulate-an-mqtt-client

Herramientas MQTT: https://www.hivemq.com/blog/overview-of-mqtt-client-tools

MQTT.fx

Uno de los clientes MQTT más populares para instalar en ordenador es MQTT.fx hecho en java y basado en Eclipse Paho http://www.eclipse.org/paho/

Está disponible para Windows, Linux y MAC

Web: https://mqttfx.jensd.de/

Descarga: http://www.jensd.de/apps/mqttfx/1.7.1/

Referencias: http://mqttfx.jensd.de/index.php/references

Más información:

MQTT-Spy

MQTT-spy es una utilidad de código abierto destinada a ayudarle a monitorear la actividad sobre temas de MQTTT. Ha sido diseñado para tratar con grandes volúmenes de mensajes, así como con publicaciones ocasionales.

mqtt-spy es probablemente una de las utilidades de código abierto más avanzadas para publicar y monitorear actividades sobre temas de MQTT. Está dirigido a dos grupos de usuarios:

  • Innovadores que necesitan una herramienta para crear prototipos de IO o proyectos de integración
  • Usuarios avanzados que necesitan una utilidad avanzada para sus entornos de trabajo

Web: https://kamilfb.github.io/mqtt-spy/

Wiki: https://github.com/eclipse/paho.mqtt-spy/wiki

Descarga: https://github.com/eclipse/paho.mqtt-spy/wiki/Downloads

Getting Started: https://github.com/eclipse/paho.mqtt-spy/wiki/GettingStarted

Ver mqtt-spy como aplicación para probar un mosquitto: https://github.com/kamilfb/mqtt-spy/wiki/Overview

Resumen: https://github.com/kamilfb/mqtt-spy/wiki/Overview

Más información:

MQTT Lens

MQTT se puede instalar fácilmente a través de Google Chrome App Store. La herramienta tiene una interfaz bastante limpia y soporta todas las opciones de conexión disponibles desde la especificación MQTT, excepto las sesiones persistentes. Acepta conexiones a más de un broker al mismo tiempo y los colorea de manera diferente para facilitar su asociación.

La interfaz para suscribirse, publicar y ver todos los mensajes recibidos es simple y fácil de entender. Lamentablemente no hay posibilidad de publicar mensajes retenidos. Pero aunque esta aplicación se instala a través de Chrome, se ejecuta como una aplicación independiente.

Usando MQTT Lens:

Uso de MQTT lens: http://www.hivemq.com/blog/mqtt-toolbox-mqtt-lens

Descarga: https://chrome.google.com/webstore/detail/mqttlens/hemojaaeigabkbcookmlgmdigohjobjm

Clientes MQTT para móvil

Eclipse Paho Android Service: https://www.eclipse.org/paho/clients/android/

Algunos clientes Android (por orden de descargas):

IOS:

Clientes MQTT en Dispositivos embebidos

MQTT se puede usar desde diversos dispositivos como cliente mediante el uso de librerías:

  • Arduino
  • Python
  • Clientes MQTT
  • Raspberry Pi
  • Autómatas (ver PLC de Unitronics y otros)
  • Otros sistemas embebidos

MQTT y Arduino

MQTT ha surgido como un protocolo de mensajería estándar para la IoT. Se puede utilizar en redes TCP/IP y es muy ligero. La norma sigue un modelo de publicación-suscripción (“pub/sub”).

Como habrás imaginado, para conseguir una comunicación MQTT, emplearemos una librería. Existen muchas disponibles gracias a la gran (tanto en tamaño como en calidad) comunidad que existe alrededor de Arduino.

Una de las librerías más conocidas y la más estable y flexible es Arduino Client for MQTT http://pubsubclient.knolleary.net/ que nos provee de un sencillo cliente que nos permite tanto subscribirnos como publicar contenido usando MQTT. Internamente, usa la API de Arduino Ethernet Client lo que lo hace compatible con un gran número de shields y placas.

Web: https://pubsubclient.knolleary.net/

Repositorio: https://github.com/knolleary/pubsubclient

Esta librería está disponible en el gestor de librerías.

Documentación: https://pubsubclient.knolleary.net/api.html

Hardware compatible:

  • Arduino Ethernet
  • Arduino Ethernet Shield
  • Arduino YUN – use the included YunClient in place of EthernetClient, and be sure to do a Bridge.begin() first
  • Arduino WiFi Shield – if you want to send packets greater than 90 bytes with this shield, enable the MQTT_MAX_TRANSFER_SIZE option in PubSubClient.h.
  • Sparkfun WiFly Shield – when used with this library
  • Intel Galileo/Edison
  • ESP8266
  • ESP32

Getting started con esa librería: https://ricveal.com/blog/arduino-mqtt/

Más info de esta librería: https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/

Tutorial con esta librería MQTT, Arduino y bluemix:: https://www.ibm.com/developerworks/ssa/cloud/library/cl-bluemix-arduino-iot2/index.html

Otras Librerías MQTT para Arduino

A la hora de elegir una librería MQTT, debemos comprobar que funciona con el dispositivo HW Arduino y el HW de comunicación.

Otras librerías MQTT para Arduino:

Más información de uso librería Adafruit:

Seguridad MQTT con ESP 8266: https://io.adafruit.com/blog/security/2016/07/05/adafruit-io-security-esp8266/

Arduino en IoT

Arduino se ha convertido una figura destacada e incluso uno de los impulsores del IoT y no por casualidad, sino que  por sus características es un HW con gran capacidad para usar en proyectos de IoT.

Características de Arduino para IoT

  • Barato y rápido prototipado.
  • HW libre y por lo tanto es modificable para que consuma menos y para hacer un HW final de características industriales.
  • Disponibilidad de HW de comunicaciones de todo tipo para conectar con Arduino. Nuevas tecnologías de comunicación llegan antes que para elementos comerciales
  • Librerías y SW público para su reutilización o adaptación.
  • Flexibilidad en la programación.
  • Apoyo de la comunidad.

No en vano cuando se busca IoT (Internet de las cosas) enseguida aparece Arduino.

Arduino sirve para recoger datos no solo del entorno sino de máquinas o elementos externos y comunicarnos con Internet, mediante su consumo eléctrico, contactos de alertas externas, su temperatura, su posición, etc…

Arduino nos permite de una forma sencilla y barata poder conectar entre sí elementos cotidianos para manejarlos y añadir sensores a cualquier elemento y en cualquier ubicación.

Qué es Arduino: https://aprendiendoarduino.wordpress.com/2018/04/02/que-es-arduino-7/

Hardware Arduino:

Hardware Arduino IoT

La familia de Arduino MKR son una serie de placas con un factor de forma diferente al de Arduino mucho más pequeño y basados todos en el microcontrolador de 32 bits de Atmel SAMD21. Estas placas están pensadas principalmente para IoT.

MKR Family: https://store.arduino.cc/arduino-genuino/arduino-genuino-mkr-family

Arduino MKRZero

Producto: https://store.arduino.cc/arduino-mkrzero

Primero modelo de la familia MKR y heredero del Arduino Zero.

Arduino MKR1000 WIFI

Producto: https://store.arduino.cc/arduino-mkr1000

Versión para IoT con procesador Atmel ARM Cortex M0+ de 32bits ATSAMW25 que es el mismo procesador que Genuino Zero pero con wifi integrado, chip de cifrado y antena integrada.

El ATSAMW25 está compuesto por tres principales bloques:

  • SAMD21 Cortex-M0+ 32bit low power ARM MCU
  • WINC1500 low power 2.4GHz IEEE® 802.11 b/g/n Wi-Fi (mismo que el wifi 101 shield)
  • ECC508 CryptoAuthentication

Arduino MKR WiFi 1010

Producto: https://store.arduino.cc/arduino-mkr-wifi-1010

El MKR WIFI 1010 es una mejora significativa del MKR 1000 WIFI. Está equipado con un módulo ESP32 fabricado por U-BLOX. Esta placa tiene como objetivo acelerar y simplificar la creación de prototipos de aplicaciones de IO basadas en WiFi gracias a la flexibilidad del módulo ESP32 y su bajo consumo de energía.

La placa tienes estos 3 bloques principales:

  • SAMD21 Cortex-M0+ 32bit Low Power ARM MCU;
  • U-BLOX NINA-W10 Series Low Power 2.4GHz IEEE® 802.11 b/g/n Wi-Fi; and Bluetooth
  • ECC508 Crypto Authentication.

Arduino MKR FOX 1200

Producto: https://store.arduino.cc/arduino-mkrfox1200

Arduino anunciado en abril de 2017. En una placa de desarrollo pensada para el IoT con conectividad Sigfox. Comparte muchas características con otras placas de la familia MKR como em microcontrolador SAM D21 32-bit Cortex-M0+.

Incluye un módulo ATA8520 con conectividad sigfox de amplia cobertura y bajo consumo capaz de funcionar durante 6 meses con dos pilas AA. También incluye una suscripción por dos años a la red Sigfox: http://www.sigfox.com/en

Web: https://blog.arduino.cc/2017/04/18/introducing-the-arduino-mkrfox1200/

Más información sobre el Arduino MKRFOX1200 en el artículo: https://www.aprendiendoarduino.com/2018/03/05/arduino-mkrfox1200/

Arduino MKR WAN 1300

Producto: https://store.arduino.cc/mkr-wan-1300

Presentado el 25 de septiembre de 2017 en la maker faire de NY: https://blog.arduino.cc/2017/09/25/introducing-the-arduino-mkr-wan-1300-and-mkr-gsm-1400/

Arduino + LoRa:

Arduino MKR GSM 1400

Producto: https://store.arduino.cc/mkr-gsm-1400

Presentado el 25 de septiembre de 2017 en la maker faire de NY: https://blog.arduino.cc/2017/09/25/introducing-the-arduino-mkr-wan-1300-and-mkr-gsm-1400/

Arduino + GSM:

Arduino MKR NB 1500

Producto: https://store.arduino.cc/arduino-mkr-nb-1500

El nuevo estándar Narrow Band IoT, con el ecosistema Arduino fácil de usar. Totalmente compatible con las clases Narrow Band IoT NB y las redes LTE CAT M1.

Arduino MKR Vidor 4000

Producto: https://store.arduino.cc/arduino-vidor-4000 :

El MKR VIDOR 4000 es altamente configurable y potente, y puede realizar procesamiento digital de audio y video de alta velocidad.

El MKR VIDOR 4000 puede configurarlo de la manera que desee; esencialmente puede crear su propia tarjeta controladora.

Viene cargado de hardware y potencial:

  • un SRAM de 8 MB
  • un chip Flash QSPI de 2 MB – 1 MB asignado para aplicaciones de usuario
  • un conector Micro HDMI
  • un conector para cámara MIPI
  • Wifi & BLE alimentado por U-BLOX NINA Serie W10.

También incluye la clásica interfaz MKR en la que todos los pines son accionados tanto por SAMD21 como por FPGA.

Además, tiene un conector Mini PCI Express con hasta 25 pines programables por el usuario.

La FPGA contiene 16K Logic Elements, 504 KB de RAM embebida y 56 multiplicadores de 18×18 bit HW para DSP de alta velocidad. Cada pin puede conmutar a más de 150 MHz y puede ser configurado para funciones tales como UARTs, (Q)SPI, PWM de alta resolución/alta frecuencia, codificador de cuadratura, I2C, I2S, Sigma Delta DAC, etc.

La FPGA integrada también se puede utilizar para operaciones DSP de alta velocidad para el procesamiento de audio y vídeo. Esta tarjeta también incluye un Microchip SAMD21. La comunicación entre la FPGA y el SAMD21 es directa.

Accesorios para Arduinos MKR

Y los IoT Bundles:

Configuración Arduino

Puesta en marcha y comprobación del entorno de programación de Arduino para utilizar en el curso.

Instalación del IDE y blink para comprobar que funciona:

Programación Arduino

Librerías

Mandar Datos a un Servidor con Arduino

Vamos a conectar Arduino a un servidor y mandar datos para que los muestre en una gráfica. Mandar datos a https://www.aprendiendoarduino.com/servicios/datos/graficas.html

Conexión:

Poner este código en Arduino: https://github.com/jecrespo/aprendiendoarduino-servicios/blob/master/arduino_code/data_logger_temperatura_DHCP/data_logger_temperatura_DHCP.ino

Ver los datos en:

Crear Librerias Arduino

Las librerías son trozos de código hechos por terceros que usamos en nuestro sketch. Esto nos facilita mucho la programación y permite la abstracción haciendo que nuestro programa sea más sencillo de hacer y de entender. En este apartado veremos cómo escribir o modificar librerías.

Librerías Arduino: https://www.arduino.cc/en/Main/Libraries

El IDE de Arduino incluye una serie de librerías ya instaladas: https://www.arduino.cc/en/Reference/Libraries

Listado de librerías del playground de Arduino: http://playground.arduino.cc/Main/LibraryList, pero existen otras muchas librerías creadas por usuarios o por los fabricantes de HW para facilitar el uso de esos dispositivos con Arduino.

Este tutorial explica como crear una librería: http://arduino.cc/en/Hacking/LibraryTutorial. Explica cómo convertir la función morse en en una librería.

Ejemplo ‘morse.ino’:

 
int pin = 13;

void setup()
{
  pinMode(pin, OUTPUT);
}

void loop()
{
  dot(); dot(); dot();
  dash(); dash(); dash();
  dot(); dot(); dot();
  delay(3000);
}

void dot()
{
  digitalWrite(pin, HIGH);
  delay(250);
  digitalWrite(pin, LOW);
  delay(250);
}

void dash()
{
  digitalWrite(pin, HIGH);
  delay(1000);
  digitalWrite(pin, LOW);
  delay(250);
}

Para convertir en una librería de código morse, vemos que hay dos funciones dot() y dash() para iluminar un led durante 250 ms y 1 segundo y  una variable que es ledPin que determina que pin usar. Este es un estilo de programación clásico usando funciones en lugar de objetos.

Para una librería se necesitan al menos dos ficheros:

  • Un fichero de cabecera con la extensión .h. Este fichero tiene las definiciones de la librería, básicamente un listado de todo lo que hay dentro de la librería
  • Un fichero fuente con la extensión .cpp. Este fichero el que contiene el código

En este caso la librería se va a llamar morse y generamos un fichero de cabecera llamado morse.h.

Veamos el código de morse.h donde se define la clase Morse donde tiene una línea por cada función o método y también una línea por cada variable o propiedad de la clase.

 
class Morse
{
  public:
    Morse(int pin);	//constructor
    void dot();
    void dash();
  private:
    int _pin;
};

Una clase es una colección de funciones (métodos) y variables (propiedades) que se guardan todas juntas en un solo lugar. Las funciones pueden ser públicas (public), es decir, pueden llamarse por quien usa la librería o privadas (private), es decir, que solo pueden llamarse desde dentro de la propia clase. Todas las clases tienen una función llamada constructor, que es usada para crear una instancia de la clase. El constructor tiene el mismo nombre que la clase y no tiene tipo de variable de devolución.

En el fichero de cabecera de una librería es necesario la declaración #include que de acceso a los tipos y constantes estándar del lenguaje de Arduino (esto se añade automáticamente en los sketches pero no a las librerías). Esta declaración debe ponerse antes de la definición de la clase. La declaración debe ser:

  • Versión IDE 1.x: #include “Arduino.h”
  • Versión IDE 0.x: #include “WProgram.h”

También es común poner todo el fichero de cabecera entre estas instrucciones:

 
#ifndef Morse_h
#define Morse_h

// the #include statment and code go here...

#endif

Esto evita problemas si alguien accidentalmente incluye dos veces la librería, lo que provocaría un error de compilación. A esto se llama guardián de inclusión múltiple o include guard.

 
// Guardián de inclusión múltiple
#ifndef FICHERO_YA_INCLUIDO
#define FICHERO_YA_INCLUIDO

Así se evita que un compilador poco sofisticado abra otra vez el mismo conjunto de ficheros cuando se incluye un fichero de cabecera dos o más veces. Puede darse el caso de no poner las inclusiones en el inicio de un fichero.

La directiva #include existe en dos versiones. En una se pone el nombre de fichero entre comillas, en la otra entre paréntesis angulares (el signo menor y mayor como “comillas”).

 
#include "fichero_con_comillas.h"
#include <fichero_entre_menor_y_mayor.h>

La versión con los paréntesis angulares busca los ficheros en todos los directorios que se han especificado en la llamada al compilador – normalmente con la opción “-I”. Estos directorios se suelen rastrear por el fichero incluido en el orden en que aparecen en la línea de comando.

Cuando se incluye un fichero entre comillas, entonces el compilador busca este fichero primero en el mismo directorio que el fichero actualmente compilado y después en los demás directorios. Es decir, la versión con comillas se diferencia de la versión con paréntesis angulares únicamente por buscar primero en el directorio del fichero compilado. Tras no encontrarlo ahí actua igual.

Cuando se crea una librería se debe documentar poniendo un comentario al comienzo de la librerías con el nombre, breve descripción, quien la ha escrito, fecha, licencia, etc…

El fichero de cabecera ‘Morse.h’ queda:

 
/*
  Morse.h - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/
#ifndef Morse_h
#define Morse_h

#include "Arduino.h"

class Morse
{
  public:
    Morse(int pin);
    void dot();
    void dash();
  private:
    int _pin;
};

#endif

Una vez hecho el fichero de cabecera hay que codificar el fichero fuente ‘Morse.cpp’.

Primero deben ponerse las declaraciones, esto da al resto de código acceso a las funciones estándar de Arduino y a las definiciones del fichero de cabecera:

 
#include "Arduino.h"
#include "Morse.h"

Lo siguiente es poner el constructor de la clase. Esto define que ocurre cuando se crea una instancia de la clase. En este caso el usuario debe especificar cual es el pin que se va a usar. Configuramos el pin como salida y los guardamos en una variable privada para usarlo desde otras funciones.

 
Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

El código “Morse::” antes del nombre de la función indica que la función es parte de la clase Morse. Esto se ve en todas las funciones de la clase. La variable llamada “_pin” es una variable privada tal y como se ha definido en el fichero de cabecera y se pone el simbolo “_” delante por convención para indicar que es privada y para diferenciarlo del argumento de la función, pero puede llamarse de cualquier forma mientras coincida con la definición en el fichero de cabecera.

Después de definir el constructor, se deben definir las funciones o métodos de la clase. Son las funciones que se habían definido anteriormente en el sketch:

 
void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250);  
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}

También es habitual añadir el comentario del fichero al principio del fichero. El fichero ‘Morse.cpp’ queda de la siguiente forma:

 
/*
  Morse.cpp - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/

#include "Arduino.h"
#include "Morse.h"

Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250);  
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}

De esta forma ya tenemos una librería completa. Ahora para incluirla en nuestro IDE debemos crear un directorio Morse dentro del subdirectorio “libraries” del directorio de nuestro entorno de trabajo definido en las propiedades del IDE. Copiar Morse.h y Morse.cpp dentro del directorio Morse y abrir o reiniciar el IDE de Arduino. A partir de este momento veremos nuestra librería disponible en el IDE y podremos incluirla en los sketches con la declaración #include <Morse.h>. La librería será compilada por los sketches que la usen.

El anterior sketch quedaría ahora sustituido por:

 
#include <Morse.h>

Morse morse(13);

void setup()
{
}

void loop()
{
  morse.dot(); morse.dot(); morse.dot();
  morse.dash(); morse.dash(); morse.dash();
  morse.dot(); morse.dot(); morse.dot();
  delay(3000);
}

Podemos ver que primero se llama a la declaración de la librería Morse. Esto hace que la librería esté disponible en el sketch y lo incluye en el código enviado a la placa Arduino, lo que hace que si la librería es muy pesada, ocupe mucha más memoria nuestro sketch y si no voy a usar una librería es mejor no incluirla para ahorrar espacio.

También observamos que creamos una instancia de la clase Morse llamada “morse”. Al ejecutar esta línea el constructor de la clase es llamado pasando un argumento, creando así el objeto “morse” en nuestro sketch. Luego podemos llamar a los métodos dot() y dash() precedidos del prefijo morse del nombre del objeto.

Es posible tener múltiples instancias de la clase Morse, cada una un pin diferente guardado en la variable privada “_pin”.

Si creamos una librería es conveniente crear el fichero keywords.txt dentro del directorio Morse. De esta forma conseguiremos resaltar las palabras clave que definamos en el fichero keywords. En cada línea del fichero keywords.txt se indica el nombre de la palabra clave y seguido por un tabulador, el tipo de keyword.

  • Las clases deben ser del tipo KEYWORD1 que se resaltan en naranja.
  • Las funciones deben ser del tipo KEYWORD2 que se resaltan en marrón

Para que el fichero keywords.txt se aplique al IDE es necesario reiniciar el IDE.

El fichero keywords.txt quedaría:

Morse KEYWORD1
dash KEYWORD2
dot KEYWORD2

Recomendación de uso de KEYWORDS:

  • Datatypes and Classes (KEYWORD1)
  • Methods and Functions (KEYWORD2)
  • Instances (KEYWORD2)
  • Class (KEYWORD3)
  • Constants (LITERAL1)
Type ID Purpose Color
KEYWORD1 Datatypes Brown #cc6600,plain
KEYWORD2 Method and function names Brown #cc6600,plain
KEYWORD3 setup, loop, Serial, and a few more Brown, bold #cc6600,bold
LITERAL1 Constants Blue #006699,plain
LITERAL2 Apparently, not used Blue #006699,plain

Las KEYWORDS predefinidas en Arduino están en el fichero C:\Program Files (x86)\Arduino\lib

Más explicación de keywords: https://spencer.bliven.us/index.php/2012/01/18/arduino-ide-keywords/

También es aconsejable ofrecer ejemplos de uso de la librería para que los posibles usuarios sepan usarla. Esto se hace creando un directorio “examples” dentro del directorio Morse y añadir en el subdirectorio los sketches de ejemplos que serán visibles desde el IDE.

La librerías morse con los ejemplos y el fichero keywords.txt se puede descargar en: http://www.arduino.cc/en/uploads/Hacking/Morse.zip

Para más información sobre la creación de librerías con un buen “estilo Arduino”, ver la Guía de Estilo de API. Guia de estilo para escribir librerías: http://arduino.cc/en/Reference/APIStyleGuide

IMPORTANTE: Como se ve en el código de una librería usamos código de de Arduino y por lo tanto podría la librería funcionará con cualquier placa compatible. Pero generalmente las librerías tienen código a bajo nivel que puede que solo valga para un tipo de procesadores y en ese caso habrá que adaptar la librería a las instrucciones del microprocesador con el que queramos usar la librería.

Para saber la arquitectura soportada por una librería ver https://arduinolibraries.info

Librería adaptada para Arduino y ESP8266: https://github.com/adafruit/Adafruit_NeoPixel donde se ha creado el fichero esp8266.c para que cuando compile con una placa ESP8266 o ESP32 sea compatible.

Más información:

Ejemplo Librería Semáforo

Para crear una clase semáforo que representa un semáforo y cuyo programa de uso es:

 
#include <Semaforo.h>

Semaforo miSemaforo(2,3,4,12);

void setup() { 
}

void loop() {
  miSemaforo.Verde();
  delay(3000);
  miSemaforo.Rojo();
  delay(3000);
}

semaforo.h

 
/*
Semaforo.h - Libreria para control de luces de un Semaforo
Por Leo Lamolda, marzo de 2018, para LMDAPPS
experimentosconarduino.blogspot.es.com
*/
#ifndef Semaforo_h
#define Semaforo_h

#include "Arduino.h"

class Semaforo
{  
 public:
  Semaforo(int rojo, int amarillo, int verde, int buzzer);
  void Rojo();
  void Verde();
  void Cambia();
  bool EsRojo();
  bool EsVerde();
 private:
        int _rojo;
        int _amarillo;
        int _verde;
        int _buzzer;
} ;

#endif

Semaforo.cpp

 
/*
Semaforo.h - Libreria para control de luces de un Semaforo
Por Leo Lamolda, marzo de 2018, para LMDAPPS
experimentosconarduino.blogspot.es.com
*/

#include "Semaforo.h"

Semaforo::Semaforo(int rojo, int amarillo, int verde, int buzzer)
{ 
 pinMode(rojo,OUTPUT);     digitalWrite(rojo,LOW);
    pinMode(amarillo,OUTPUT); digitalWrite(amarillo,LOW);
    pinMode(verde,OUTPUT);    digitalWrite(verde,LOW);
    pinMode(buzzer,OUTPUT);   digitalWrite(buzzer,LOW);
   _rojo = rojo;
   _amarillo=amarillo;
   _verde=verde;
   _buzzer=buzzer;             
}

void Semaforo::Rojo(){
 digitalWrite(_rojo,LOW);
  digitalWrite(_verde,LOW);
  for (int i=0;i<5;i++){
        digitalWrite(_amarillo,HIGH);
        digitalWrite(_buzzer,HIGH);
        delay(200);
        digitalWrite(_amarillo,LOW);
        digitalWrite(_buzzer,LOW);
        delay(200);
    } 
 digitalWrite(_rojo,HIGH);
}

void Semaforo::Verde(){
    digitalWrite(_rojo,LOW);
    digitalWrite(_amarillo,LOW);
    digitalWrite(_verde,HIGH);
}

void Semaforo::Cambia(){
 if (EsVerde()) Rojo();
  else Verde(); 
}

bool Semaforo::EsRojo(){
 return digitalRead(_rojo);
}

bool Semaforo::EsVerde(){
 return digitalRead(_verde);
}

Y si tenemos dos semáforos podemos hacer:

 
#include <Semaforo.h>

Semaforo miSemaforo1(2,3,4,12);
Semaforo miSemaforo2(8,9,10,12);

void setup() {  
}

void loop() {
  miSemaforo1.Rojo();
  delay(500);
  miSemaforo2.Verde();
  delay(3000);
  miSemaforo2.Rojo();
  delay(500);
  miSemaforo1.Verde();
  delay(3000);
}

 

Más información:  http://experimentosconarduino.blogspot.com/2018/04/un-clasico-semaforo-con-arduino-y.html

Otros Ejemplos de Librerías

Ver ejemplos simples de librerías:

Librería para el manejo de una API: https://github.com/jecrespo/apisiar_arduino/tree/master/apisiarlib

Guía de estilo para escribir una librería de Arduino

Para facilitar el entendimiento de las librerías o APIs de Arduino y hacer que el entorno de Arduino sea más homogéneo, desde arduino.cc dan unas pautas para escribir librerías al “estilo Arduino”. Algunas de estas prácticas van en contra de la programación programación profesional, pero esto hace posible a los principiantes comenzar a trabajar de forma sencilla con Arduino.

  • Se amable con el usuario. Tener una modelo claro del concepto que va tratar la librería y las funciones que se van a implementar.
  • Organizar las funciones pública alrededor de los datos y funcionalidades que el usuario quiere. Frecuentemente el conjunto de comandos para un módulo electrónico son demasiado complicado, pero podemos reorganizar las funciones desde un punto de vista de uso a alto nivel. Pensar en lo que hace la mayoría de las personas y organizar la API en función de ese uso. Un ejemplo es la librería https://github.com/adafruit/Adafruit-BMP085-Library. La función readPressure() hace todos los pasos para obtener la presión final, siendo transparente para el usuario todos los complejos pasos intermedios. Esto abstrae al usuario no solo de los comandos I2C necesarios, sino de de los cálculos intermedios.
  • Usar palabras claras para escribir la librerías. Usar nombres de funciones y variables claros que expresen claramente lo que son o hacen y no usar términos técnicos.
  • Evitar palabras que tengan diferente significado para el público en general.
  • Documentar todo. Al escribir ejemplos usar esta guía: http://www.arduino.cc/en/Reference/StyleGuide
  • Usar las librerías del core de Arduino y su estilo:
    • Usar read() para leer entradas y write() para escribir salidas
    • Usar las librerías Stream.h y print.h cuando se estén manejando byte streams. Si no es posible al menos intentar usar su modelo de API.
    • Para aplicaciones de redes, usar las librerías de Client y Server como base.
    • Usar begin() para inicializar unas instancia de una librería, normalmente con unos parámetros de configuración. Usar end() para finalizarla.
  • Usar funciones camel case, no con guión bajo. Por ejemplo analogRead en lugar de analog_read. Esto es una adopción de processing por motivos de facilidad la lectura.
  • No usar nombre de constantes largos que son difíciles de leer.
  • Evitar usar argumentos booleanos. En su lugar es preferible ofrecer dos funciones diferentes con nombres que describan la diferencia entre ellas.
  • No asumir conocimiento de punteros. Los principiantes en C suelen encontrar dificultades con el uso de & y *, en la medida de lo posible tratar de evitar el uso de punteros.
  • Al usar la comunicación serie de cualquier tipo, permitir al usuario especificar el objeto de stream en lugar de solo “Serial”, esto hará la librería compatible con los los puertos del Arduino Mega y Due y también poder usar interfaces alternativos como el SoftwareSerial. ver el uso de begin(Stream &serial) en las librerías https://github.com/firmata/arduino y https://github.com/andrewrapp/xbee-arduino
  • Cuando se escriba una librería que ofrezca comunicación byte-stream heredada de la la clase Stream de Arduino, de forma que la librería pueda ser usada por otras librerías que acepte objetos Stream: si es posible, el método read() inmediatamente accede a los datos del buffer sin esperar a que lleguen más datos y si es posible el método write() debe guardar los datos al buffer de transmisión, pero debe esperar si el buffer no tiene suficiente espacio para guardar inmediatamente todo los datos salientes. La función yield() debe llamarse mientras se espera. De esta forma mantenemos compatibilidad con el restos de librerías Stream.

Unos ejemplos de librerías que definen realmente bien las funciones de alto nivel son:

Viendo los métodos públicos que definen es muy fácil entender que es lo que hacen.

Otro buen ejemplo de abstracción de la librerías wire (I2C) se puede ver en: https://github.com/adafruit/RTClib donde con una serie de métodos obtengo los datos del RTC siendo totalmente transparente para el usuario el uso de la librería wire.

Es frecuente que nos encontremos que algunas librerías se quedan cortas para algunas funcionalidades avanzadas, puesto que como se ha visto en la guía de estilo se tiende a simplificar. Un ejemplo de esto es la librería ethernet donde muchas de las funcionalidades del Wiznet 5100 no están implementadas en la librería, pero esto no impide que nosotros podamos añadirlas.

Más información: https://www.arduino.cc/en/Reference/APIStyleGuide

Modificar librerías

Es habitual que al usar una librería necesitemos una propiedad o un método que no esté implementado o queramos modificar el comportamiento, para ello podemos modificar localmente la librería que tengamos instalada en nuestro IDE.

En el caso que queramos colaborar en una librería hecha, podemos hacer un fork de esa librería en nuestra cuenta de github y añadir una nueva funcionalidad o corregir ese fallo e incluso podemos hacer un pull request para que se añada en la librería original nuestra modificación. También podemos tener nuestra propia librería como un fork de la librería original.

Un pull request es una petición que el propietario de un fork de un repositorio hace al propietario del repositorio original para que este último incorpore los commits que están en el fork. Explicación de pull request: http://aprendegit.com/que-es-un-pull-request/

Para modificar la librería time y añadir una funcionalidad, lo primero es hacer un fork del código https://github.com/PaulStoffregen/Time en tu repositorio, en mi caso en https://github.com/jecrespo/Time y luego clonarlo en el ordenador para modificarlo.

Ejemplo de librería Ethernet modificada: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Otros/Ethernet%20Modificada

Añado los métodos:

  • uint8_t *getRemoteIP(uint8_t remoteIP[]);//adds remote ip address
  • uint8_t *getRemoteMAC(uint8_t remoteMAC[]);
  • uint16_t getRemotePort();

Ejercicios Librerías

Hacer Librería Morse

Ejercicio: Hacer la librería Morse y probarla con los leds del montaje.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio15-Libreria_Morse

Hacer Librería Detecta Flanco

Ejercicio: Hacer una librería que detecte un flanco basado en la clase detecta flanco del ejercicio https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio12-Clase_Detecta_Flanco_cpp .

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio18-Libreria_Detecta_Flanco

Hacer Librería Coche

Ejercicio: Hacer la librería coche para aplicar en un sketch como el visto en https://aprendiendoarduino.wordpress.com/2017/07/08/clases-y-objetos/

 
#include “Coche.h”
 
Coche MiCocheRC(6,7)
 
void setup() {
MiCoche.Arranca()
}
 
void loop() {
char valor = leeBluetooth();
 
switch (valor) {
    case ‘F’:
      MiCoche.Adelante();
      break;
    case ‘R’:
      MiCoche.Derecha();
      break;
    case ‘L’:
       MiCoche.Izquierda();
      break;
    case ‘B’:
       MiCoche.Atras();
      break;
    case ‘S’:
       MiCoche.Para();
      break;
  }
}

Crear los métodos y configurarlos:

  • Arranca()
  • Adelante()
  • Derecha()
  • Izquierda()
  • Atras()
  • Para()
  • MuestraGasolina()
  • EchaGasolina()
  • EncidendeLuces()
  • ApagaLuces()
  • Pita()

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio13-Libreria_Coche

Crear una librería para NTP

Ejercicio: A partir del ejemplo de Arduino para obtener la hora de un servidor NTP https://www.arduino.cc/en/Tutorial/UdpNtpClient, crear una librería para obtener de forma sencilla la hora con una llamada a la función readNTP().

Ver Ejercicio39-NTP para obtener fecha y hora en Arduino sin necesidad de un RTC usando NTP: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio39-NTP

Basado en:

Protocolo:

Las firmas de tiempo que se usan en NTP, son de 32 bits indicando la parte entera en segundos desde  el 1 de Enero de 1900, y una parte fraccionaria también de 32 bits. Por ello la resolución teórica de NTP sería de 232 segundos =136 años, y una resolución teórica de 2E-32 segundos, o sea 0,233 nanosegundos.

Nota: Ojo al llamar al constructor de algo p.e. ethernet sin hacer el begin ethernet antes.

Solución: https://github.com/jecrespo/simpleNTP