Las librerías: qué son y para qué sirven
En el mundo del software, una librería es una colección de programas que facilita la ejecución de una serie de funciones relacionadas entre sí. Por ejemplo las funciones que facilitan la escritura en una pantalla LCD o las que nos permiten calcular la posición de un sistema de navegación GPS.
Las librerías de software funcionan de la misma manera que una biblioteca tradicional: pides información sobre un tema concreto y después la utilizas dentro de tu proyecto según te convenga o la necesites.
Imagínate que estás trabajando en un proyecto de investigación: sacas un libro de consulta de la biblioteca y utilizas las informaciones que necesitas de ese libro para tu proyecto. Exactamente lo mismo sucede con una librería de software.
En el mundo de Arduino, una librería es una colección de funciones que incluyes de una manera muy sencilla y explícita en tu sketch y que proporciona una cierta funcionalidad específica. Por ejemplo, hay una librería de cristal líquido que, cuando está incluida en tu sketch, te dará la capacidad de usar fácilmente una pantalla LCD. Una misma librería puede usarse en varios proyectos diferentes.
Algunas librerías se pueden utilizar sin necesidad de extender el Arduino con otros dispositivos, mientras que otras necesitan ser utilizadas con componentes electrónicos adicionales, a menudo bajo la forma de “shields” (escudos = componentes adicionales de mayor o menor complejidad, pero que cubren una función específica).
Hay tres diversos tipos de librerías de Arduino: base, estándar, y contribuciones (“contributed librairies”). Comenzaremos con la librería de base.
librería de base (“Core library”)
La biblioteca de la base forma parte del entorno de desarrollo del Arduino (IDE). El propósito de esta librería es ocultar mucha de la complejidad que tradicionalmente implica el trabajar con el microprocesador.
En efecto, esta es una de las razones aducidas más frecuentemente por principiantes y usuarios experimentados sobre la dificultad de trabajar con microprocesadores tradicionales. Esta librería de base (“core”) es una de las grandes ventajas del Arduino al hacerlo fácilmente accesible a todos los usuarios.
Los diseñadores del Arduino desarrollaron esta librería a partir de las peticiones de los estudiantes e incluye aquellas acciones que son más comunes.
La mayoría de los proyectos leen datos de una de las entradas o escriben datos en una de las salidas. La librería core hace que estas tareas comunes sean simples ejecutar. Por ejemplo, para leer el valor de un pin digital basta con usar la función digitalRead (por otra parte, el nombre es fácil de recordar).
En el capítulo precedente (funciones) hemos visto todas las funciones de base (core) que constituyen el núcleo del Arduino. A continuación vamos a pasar revista a las librerías estándar que forman parte del IDE del Arduino.
Librerías estándar
Al descargar e instalar en tu ordenador el entorno de desarrollo del Arduino (IDE), se incluyeron algunas librerías estándar con la instalación. Las librerías estándar son aquellas que el equipo de desarrollo de Arduino estimó que serían necesarias para los desarrollos de muchos usuarios.
Estas librerías no se incluyen como opción por defecto en tus sketches, tienes que cargarlas una por una (aquellas que necesites). De esta manera se utilizan los recursos de memoria del Arduino con mayor eficiencia al cargar únicamente aquellas librerías que vas a usar en tu sketch.
Para incluir un librería basta con añadir una declaración #include al comienzo del sketch. Por ejemplo, si quieres incluir la librería de cristal líquido, que se utiliza para exhibir datos en una pantalla LCD, basta con incluir la siguiente declaración al principio de tu sketch:
#include <LiquidCrystal.h>
Observa que el nombre de la librería tiene que ir limitado por los corchetes menor/mayor: < y >. Además hay que notar que la línea no termina con un punto y coma (;) como es la norma en las demás líneas de código.
A continuación veremos las diferentes librerías estándar:
- Librería ArduinoTestSuite
- Librería EEPROM
- Librería SD
- Librería Ethernet
- Librería Firmata
- Librería LiquidCrystal
- Librería Servo
- Librería Stepper
- Librería SPI
- Librería Wire
- Librería SoftwareSerial
Programación en un entorno de test: ArduinoTestSuite
La manera en que los programas y aplicaciones para Arduino se escriben está sujeta a una continua evolución y mejora. La innovación más reciente consiste en un entorno de programación llamado test-driven-development (TDD, desarrollo bajo test).
En TDD, un proyecto de software se divide en pequeños módulos, y antes de escribir un módulo dado, estableces las pruebas (tests) que verifican el funcionamiento de cada función del módulo.
Cuando finalmente escribes el módulo, se ejecuta bajo un entorno de test que comprueba que los resultados obtenidos por el módulo son los descritos en el entorno de test que definiste previamente. Si no es así corriges los errores y vuelves a ejecutar el módulo en el entorno de test.
Cuando un módulo ha pasado los tests, desarrollas el siguiente módulo de la misma manera y así hasta que el proyecto haya sido completado. Si más tarde tienes que modificar uno de los módulos lo ejecutas bajo el entorno de test hasta que funcione de acuerdo con las especificaciones.
La biblioteca ArduinoTestSuite es el primer paso para implantar esta metodología TDD en el Arduino. Se trata de una librería relativamente nueva, pero se considera como esencial para el futuro del desarrollo en Arduino.
La librería ArduinoTestSuite proporciona métodos estándar y funciones que se pueden utilizar para probar sus sketches antes de cargarlos en el Arduino. De esta manera nos aseguramos de que el sketch funcione según lo previsto antes de usarlo en el mundo real con costosos dispositivos que pueden ser dañados si se utilizan incorrectamente.
La librería está todavía en fase de desarrollo, pero tiene actualmente tests para los procesos listados en la tabla siguiente:
Test | Description |
---|---|
ATS_begin |
Inicia el proceso de test |
ATS_end |
Termina el proceso de test |
ATS_Test_DigitalPin |
Testea un pin de entrada digital dado |
ATS_Test_PWM |
Testea la salida PWM |
ATS_Test_AnalogInput |
Testea la entrada analogical |
ATS_Test_EEPROM |
Testea la EEPROM |
ATS_TestSerialLoopBack |
Testea los pins RX y TX de una puerta Serie |
ATS_GetFreeMemory |
Devuelve el número de posiciones libres de memoria en el Arduino |
La idea de incorporar un entorno de test como parte del Arduino IDE es nueva, pero se convertirá probablemente en una parte importante del IDE a medida que la funcionalidad de los Arduinos siga evolucionando.
Usando la EEPROM como sistema de almacenamiento de datos
La memoria EEPROM es un tipo de memoria de sólo lectura que puede ser borrada y reescrita mediante la aplicación de una tensión eléctrica y al mismo tiempo conserva los datos almacenados incluso tras desconectar la alimentación de la placa del microprocesador.
La cantidad de EEPROM en un Arduino depende del microprocesador de base que lleve.El cuadro siguiente muestra la cantidad (en octetos o bytes) de memoria EEPROM disponible en diversos Arduinos.
Microprocesador | EEPROM memory (bytes) |
---|---|
ATMega8 and ATMega168 | 512 |
ATMega328 | 1,024 |
ATMega1280 and ATMega2560 | 4,096 |
- Nota: El Arduino Uno basado en el chip ATMega328; tiene 1.024 bytes de memoria EEPROM.
La librería EEPROM proporciona sketches que permiten el acceso a la EEPROM del Arduino e incluye dos funciones, read y write, tal y como se muestra en cuadro de abajo.
Function | Description |
---|---|
Read | Lee el valor de un byte almacenado en una posición de la EEPROM |
Write | Escribe un valor en una posición de la EEPROM |
- Nota: Cualquier dato escrito en la EEPROM se conserva incluso cuando el Arduino se apaga.
Un buen uso de la librería EEPROM puede ser el almacenamiento de aquellos datos que serán necesarios entre dos sesiones de uso del Arduino (contadores, constantes necesarias para el uso de ciertos dispositivos periféricos, como una pantalla LCD, etc.).
Si el volumen de datos que quieres almacenar entre sesión y sesión es considerable, debes de usar una memoria SD.
Almacenando datos en un tarjeta SD
El Arduino no está dotado con memoria RAM ni memoria masiva para almacenar datos en grandes cantidades.
En efecto, la memoria EEPROM integrada en el microprocesador sólo puede almacenar unos pocos cientos de octetos en el mejor de los casos. Para almacenar volúmenes considerables de datos (tal como demandan la mayor parte de las aplicaciones) tenemos que recurrir a tarjetas de memoria SD o SDHC.
Una de las muchas ventajas de estas memorias es que están fácilmente disponibles en una variedad de tamaños de memoria y de precios (en general relativamente baratos). La tabla de abajo muestra las diferencias entre las tarjetas SD y las SD de alta capacidad (SDHC).
SD | SDHC | |
---|---|---|
Capacidad | 0–2 GB | 4 GB–32 GB |
Sistema de Almacenamiento de ficheros | FAT16 o FAT32 | FAT32 |
William Greiman escribió una librería para Arduino llamada SdFat basada en los sistemas de codificación de ficheros FAT16 y FAT 32. La librería SdFat proporciona una gama exhaustiva de funciones para el manejo de estas tarjetas de memoria: crear y suprimir ficheros y directorios, formateo, etc.
El equipo de desarrollo del Arduino se dió cuenta de que esta librería es relativamente difícil de utilizar, así que construyeron una envoltura alrededor de ella, haciéndola más sencilla de usar e incluyendo solamente un subconjunto de sus funciones.
- Nota: La librería utiliza mucha memoria de programa, lo cual limita el tamaño de tus sketches, por lo tanto se recomienda el uso de esta librería solamente con un Arduino equipado de un procesador ATMega328P.
Cuando se incluye esta librería en un sketch, la librería SD proporciona una gama de funciones básicas (ver siguiente tabla) que permiten a tu Arduino interaccionar con las tarjetas SD:
Clase | Función | Descripción |
---|---|---|
SD | begin | Inicializa la librería y la tarjeta SD |
exists | Verifica la existencia de un fichero o directorio en la tarjeta | |
mkdir | Crea un directorio en la tarjeta | |
rmdir | Suprime un directorio en la tarjeta | |
remove | Suprime un fichero de la tarjeta | |
open | Abre un fichero en la tarjeta | |
File | available | Verifica que quedan bytes por leer en el fichero |
close | Cierra un fichero y se asegura que los datos escritos en él han sido salvaguardados en la tarjeta. | |
seek | Busca una posición en un fichero | |
position | Devuelve la posición actual dentro del fichero. | |
size | Devuelve el tamaño del fichero. | |
Escribe datos en un fichero abierto. | ||
println | Escribe datos en un fichero y añade un carácter “newline” al final. | |
write | Escribe datos en un fichero | |
read | Lee un octeto (byte) de un fichero abierto. |
- Nota: La librería SD usa solamente la nomenclatura 8,3 (8 caracteres para el nombre del fichero y 3 para la extensión). No se pueden usar nombres de fichero más largos o conteniendo espacios.
Arduino usa un bus serie para comunicar con sus periféricos (el bus SPI del que hablaremos más adelante) y en particular con la tarjeta SD (pins digitales 11, 12, y 13 en un Arduino estándar y 50, 51, y 52 en un Mega).
Además, el pin 10 se usa generalmente para seleccionar el dispositivo de tarjeta en un Arduino estándar y el 53 en un Mega. Podemos usar un pin diferente para esta función usando la función SD.begin.
- Nota: Antes de usar una tarjeta SD en el Arduino, debemos formatearla en formato FAT16 o FAT32 usando tu ordenador y el lector de tarjetas.
Existen microSDshields disponibles en el mercado. Asimismo está disponible una gama de shields con conectores integrados microSDcard, incluyendo el último shield oficial Ethernet y shields de registro de datos.
Conectándose con Ethernet
Si quieres que tus aplicaciones Arduino sean accesibles a otras personas de nuestro entorno (o a través de internet) vas a necesitar la librería Ethernet que te simplificará el acceso a funciones TCP/IP y te permitirá comunicar tu Arduino con Internet o la red doméstica.
Esta librería está diseñada para interactuar con placas basadas en WIZnet W5100. La placa oficial más reciente de Arduino lleva incorporada también un conector microSDcard que resulta muy apropiado para el registro y almacenamiento continuo de datos.
De esta manera puedes, por ejemplo, utilizar el Arduino para tomar lecturas de datos en una ubicación remota y publicar estos datos en una página web básica mientras los almacena en un microSDcard que podría ser recuperado y analizado más adelante.
La biblioteca de Ethernet es muy extensa y permite configurar el Arduino como servidor recibiendo conexiones de clientes, o como cliente, que se va conectando con uno o varios servidores. La tabla siguiente muestra algunas de las funciones de la librería.
Class | Function | Description |
---|---|---|
Ethernet | begin | Inicializa la librería y configura los parámetros de red |
localIP | Devuelve la dirección IP local | |
dnsServerIP | Devuelve la dirección DNS del servidor | |
Server | Server | Crea un servidor |
begin | Comienza a escuchar posibles peticiones de conexión | |
available | Localiza un cliente para el que tiene datos disponibles para su lectura | |
write | Escribe datos a clientes; tipo: byte o char | |
Escribe datos a clientes; tipo puede ser: byte, char, int, long, o string | ||
println | Escribe datos a clientes, seguidos por un carácter “newline” | |
Client | Client | Crea un cliente |
connected | Devuelve TRUE si el cliente está conectado al servidor | |
Connect | Conecta a la dirección IP y al puerta especificado | |
write | Escribe datos a un servidor conectado. | |
Escribe datos a un servidor, tipo puede ser: byte, char, int, long, o string | ||
println | Escribe datos a un servidor seguido por un carácter “newline” | |
available | Devuelve el número de bytes que están listos para su lectura en el servidor | |
read | Lee el siguiente octeto (byte) desde el servidor | |
flush | Desestima los bytes que están en espera de ser leídos por el cliente | |
stop | Se desconecta del servidor |
Como puedes ver la librería Ethernet es muy rica en contenido y sigue siendo extendida dado su interés de cara a conectar nuestras aplicaciones Arduino con el resto del mundo.
Comunicaciones serie con Firmata
Firmata es un protocolo de comunicaciones que permite al ordenador (tu PC o laptop) comunicar con uno o varios Arduinos y controlar sus microprocesadores desde el ordenador.
La librería Firmata proporciona los protocolos de comunicación serie (métodos) que permitirán comunicar al PC con el Arduino. Usando Firmata podrás controlar servos, motores, pantallas, LEDs, etc desde tu PC a través de uno o varios Arduinos. La tabla siguiente muestra los protocolos o métodos más usuales de Firmata:
Método | Descripción | |
---|---|---|
Común | begin | Inicializa la librería Firmata |
printVersion | Envía versión del protocolo al PC | |
setFirmwareVersion | Establece la versión del firmware | |
Enviar mensajes | sendAnalog | Envía un mensaje analógico |
sendDigitalPortPair | Envía el valor de un pin digital | |
sendsysex | Envía un comando con un array de bytes | |
sendString | Envía un string al PC | |
Recibir mensajes | available | Comprueba que hay mensajes en el buffer de entrada |
processInput | Procesa los mensajes entrants | |
attach | Asocia una función a un cierto tipo de mensaje de entrada | |
detach | Disocia una función de un cierto tipo de mensaje de entrada |
El protocolo Firmata esta evolucionado constantemente; visita http://firmata.org/wiki/ para obtener las actualizaciones más recientes e informarte sobre el protocolo.
Visualizando datos usando la librería LiquidCrystal
Muy frecuentemente queremos visualizar la información generada no en la pantalla del PC, sino en una pequeña pantalla LCD de 2 filas de 6 caracteres para mostrar la información a los usuarios de la aplicación (sin necesidad de disponer de un PC).
La mayor parte de estas pequeñas pantallas LCD se basan en el Hitachi HD44780 u otro microprocesador compatible. La pantalla LCD puede servirnos para mostrar datos del GPS, mensajes de situación del sistema, y cualquier otra información útil para el usuario o el programador.
La herramienta que necesitamos para poder usar estas pantallas desde nuestro sketch es la librería LiquidCrystal. La siguiente tabla enumera algunas de las funciones disponibles en la librería.
Función | Descripción |
---|---|
begin | Establece las dimensiones en filas y columnas de la pantalla LCD |
LiquidCrystal | Inicializa la librería y determina los pins usados para comunicar con la pantalla LCD |
Visualiza datos en la pantalla LCD | |
clear | Borra los contenidos de la pantalla LCD |
setCursor | Posiciona el cursor sobre la pantalla |
Controlando un motor servo
Los motores servo se usan generalmente para controlar con precisión movimientos dentro de nuestros modelos (por ejemplo en radio-control, las aletas de un aeroplano, o la dirección de un volante o timón, etc.).
Son ideales para los proyectos que necesitan el movimiento exacto, como por ejemplo evitar obstáculos o colocar una pieza en un ángulo pre-determinado en aplicaciones robóticas, etc.
La librería Servo permite al Arduino controlar hasta 12 motores servos con un Arduino estándar, y 48 con un Mega. La siguiente tabla muestra las principales funciones proporcionadas por la biblioteca Servo.
Función | Descripción |
---|---|
attach | Asigna el servo a un pin. |
Attached | Verifica que el servo está conectado al pin |
Detach | Desconecta el servo del pin. |
Read | Lee el ángulo del servo. |
Write | Hace girar el eje del servo al ángulo especificado. Entre 0 y 180 en un servo clásico. En un servo de rotación continua establece la velocidad de rotación. |
writeMicroseconds | Gira el eje del servo un arco expresado en microsegundos. |
- Nota: El uso de la librería Servo en un Arduino estándar deshabilita la función analogWrite en los pines 9 y 10 del PWM. En el Mega, se deshabilita analogWrite en los pins 11 y 12 si estamos controlando más de 12 servos.
Controlando el giro de un motor de pasos
Un motor de pasos gira su eje en pasos. La especificación de un motor de pasos viene dada generalmente en pasos, así que un motor con una especificación de 200 pasos necesitaría 200 pequeños giros angulares para completar una revolución.
La especificación se da a veces grados que se pueden convertir fácilmente en pasos dividiendo una revolución (360 grados), por el número de grados dados para cada paso en la especificación. Para un motor de pasos con una especificación de 1,5 grados calculamos el número de pasos por la revolución como sigue:
360 grados/1,5 grados por paso = 240 pasos
Los motores de pasos nos proporcionan una manera muy precisa para controlar dispositivos. La librería Stepper nos proporciona la manera de controlar motores de pasos unipolares y bipolares con un Arduino.
Usando la librería podemos establecer la velocidad de la rotación del motor el número de pasos que queremos dar y la dirección de estos pasos. La siguiente tabla muestra las principales funciones de la librería Stepper:
Función | Descripción |
---|---|
Stepper | Inicializa la librería Stepper y establece el número de pasos por revolución. |
setSpeed | Establece la velocidad de rotación del motor en revoluciones por minute (RPM) |
step | Gira el motor el número de pasos indicado. Un número positive gira en un sentido y uno negativo en el contrario. |
Comunicando con periféricos SPI
El Bus Serie para Periféricos (denominado con las siglas SPI en inglés), también llamado el bus de 4 hilos (four-wire bus) es un protocolo de comunicaciones síncrono usado para comunicar en distancias cortas con periféricos externos como sensores, incluyendo los sensores de temperatura, sensores de presión, convertidores analógico- digital, pantallas táctiles, controladores de videojuegos, y pantallas de visualización. Arduino usa también el bus SPI para comunicar con tarjetas de memoria SD.
Este protocolo tiene un solo master, el Arduino, y uno o más dispositivos esclavos. Debido a la falta de un estándar formal, han surgido diferentes implementaciones del protocolo SPI según los diversos fabricantes de dispositivos periféricos, es decir, que probablemente tendrás que recurrir a las especificaciones del periférico en cuestión para manejarlo desde el Arduino.
El protocolo utiliza cuatro hilos, de los cuales tres son comunes a cada dispositivo y el cuarto que es específico (no compartido) para cada periférico. Sus designaciones se muestran en la siguiente tabla:
Designación | Descripción | Pin Arduino | Pin Mega |
---|---|---|---|
MISO | Master In Slave Out, envio datos al master | 12 | 50 |
MOSI | Master Out Slave In, envio datos al esclavo | 11 | 51 |
SCK | Reloj Serie | 13 | 52 |
SS | Selección de esclavo | Normalmente10 | 53 |
Cada esclavo tiene un hilo “selectwire” específico para él, pero comparte los otros tres hilos del bus con los otros periféricos. El pin 10 (53 en el Mega) se usa generalmente como línea de selección de esclavo (“slave select”), pero los otros tres pueden ser elegidos durante la configuración.
El shield Ethernet del Arduino utiliza el pin 4 para conectar con el conector SD integrado y el pin 10 para el controlador Ethernet.
La librería SPI proporciona las funciones que nos permitirán actuar sobre los periféricos SPI tal y como se muestra a continuación:
Función | Descripción |
---|---|
Begin | Inicializa el bus SPI y pone los pins MOSI y SCK en baja y el SS en alta |
End | Desactiva el bus SPI |
setBitOrder | Establece el orden en el cual se cargan los bits en el bus |
setClockDivider | Establece el divisor de reloj SPI como una fracción del reloj del sistema |
setDataMode | Establece el modo de datos en el bus SPI |
Transfer | Transfiere un byte al bus |
Veamos más en detalle alguna de estas funciones:
setBitOrder: Establece el orden en el que los datos son puestos en el bus. Hay dos posibilidades: empezar por el bit de mayor peso (Most Significant Bit, MSB) o por el de menor peso (Least Significant Bit, LSB). Las especificaciones del periférico concreto te dirán cuál de estas dos opciones debes de usar.
setClockDivider: Establece la velocidad a la que opera el bus SPI como una fracción del periodo del reloj del sistema. El divisor por defecto es 4, lo cual reduce la velocidad del bus SPI a un cuarto del periodo del reloj del sistema; otros ratios posibles son 2, 8, 16, 32, 64, y 128.
setDataMode: Controla el modo de transmisión de datos entre el periférico esclavo y el master. Existen tres modos de transmisión que vienen dados por cuando se ponen los datos en el bus: cuando el reloj del sistema pasa a alta, cuando pasa a baja (estos dos modos se denominan “fase de reloj” (clock phase). El tercer modo es cuando el reloj está estable en el momento de poner los datos en el bus. Este es el modo de “polaridad de reloj” (clock polarity). La tabla expuesta a continuación resume estos modos de transmisión.
Modo | Polaridad del Reloj (CPOL) | Fase del Reloj (CPHA) |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
Todo esto parece un poco complicado, sin embargo verás que leyendo las especificaciones del periférico y siguiendo sus instrucciones con cuidado podrás comunicar con el bus SPI sin problemas.
Comunicando con el interface de dos hilos (I2C)
Este interface comúnmente llamado interface de dos hilos (TWI, two wire interface) se usa para comunicar a baja velocidad con una amplia gama de dispositivos y componentes (incluyendo relojes de tiempo real).
Es muy indicado para aplicaciones de registro de datos (logging applications), pantallas LCD, sensores ultrasónicos para medir distancias y potenciómetros digitales cuya resistencia pueda ser leída o regulada por control remoto.
I2C se usa en los mandos Nintendo, el Wii Motion Plus, y Wii Nunchuks.
Solo se necesitan dos pins para el interface con el bus i2C (ver tabla).
Arduino Estándar | Mega | |
---|---|---|
SDA data line | Analog input pin 4 | Digital pin 20 |
SCL clock line | Analog input pin 5 | Digital pin 21 |
Con la librería Wire el Arduino puede actuar como master o esclavo. Lo más frecuente es que Arduino haga de master e interactúe con uno o varios esclavos en el bus I2C; cada esclavo tiene una dirección única que lo distingue en la red del bus. Se pueden concatenar hasta un máximo de 112 dispositivos en el bus. El Arduino puede también operar como dispositivo esclavo interaccionado con un master.
La siguiente tabla lista las funciones más importantes de la librería Wire:
Function | Description |
---|---|
Begin | Inicializa la librería Wire y conecta el Arduino al bus I2C como master o esclavo. |
requestFrom | Pide datos del esclavo al master. |
beginTransmission | Prepara la transmisión de datos. |
Send | Envía datos del esclavo al master o pone en cola bytes para la transmisión de master a esclavo. |
endTransmission | Finaliza la transmisión (comenzada con beginTransmission) de datos a un esclavo y envía los datos puestos en cola de envío por send. |
Available | Devuelve el número de bytes disponible para su recepción con receive. Debe de ser usado en el dispositivo master tras una llamada requestFrom de un esclavo dentro de la función activada por onReceive. |
Receive | requestFrom o desde el master a un esclavo. |
onReceive | Determina la función que se ha de activar cuando el esclavo recibe una transmisión desde el master. |
onRequest | Determina la función que se ha de activar cuando el master pide datos al dispositivo esclavo. |
Creando más puertas serie con SoftwareSerial
Muchos de los proyectos que podemos realizar con el Arduino requieren al menos una puerta serie. Los dispositivos GPS, las pantallas LCD y otros dispositivos necesitan conectarse a una puerta serie. Esta puerta consiste en dos conexiones: una RX para recibir mensajes y una TX para enviarlos.
La utilidad de esta puerta radica en su simplicidad. En el pasado todos los ordenadores tenían una o varias puertas serie. De hecho, el Arduino original usaba una puerta serie para conectarse al ordenador y, aunque actualmente la conexión se realiza a través de un USB, lo hace a través de una emulación de puerta serie (que vista desde el ordenador es una conexión serie).
Los Arduino Uno y Duemilanove tienen una puerta serie conectado a los pines digitales 0 y 1, pero si tu proyecto necesita conectarse a más dispositivos serie (por ejemplo un GPS y un display LCD) puedes hacer dos cosas: comprarte el Arduino Mega (o compatible) que tiene 4 puertas serie o usar la librería SoftwareSerial que se distribuye con el entorno de desarrollo del Arduino (IDE).
La librería original solo proporcionaba una puerta software adicional además de la puerta hardware de serie y su velocidad estaba limitada a 9600 baudios. Estas limitaciones fueron superadas por la nueva librería NewSoftSerial escrita por Mikal Hart que fue incorporada por el equipo de desarrollo del Arduino a medidos de 2011 como la nueva SoftwareSerial. La siguiente tabla muestra las funciones incluidas en esta librería:
Función | Descripción |
---|---|
Begin | Activa la puerta y establece la velocidad de transmisión en baudios |
Available | Comienza a usar la puerta |
isListening | Devuelve la puerta active en este momento |
listen | Escucha a ese puerta y lo activa |
end | Termina el uso de ese puerta |
read | Lee datos de la puerta |
write | Escribe datos en la puerta |
Esta nueva librería puede crear varias puertas serie software que pueden comunicar a velocidades de hasta 115,000 baudios. Pero toda esta funcionalidad adicional tiene un precio: el Arduino sólo puede escuchar o recibir datos de una puerta serie software a la vez (sin embargo, sí que puede transmitir por varias simultáneamente).
Cuando uses la librería con más de una puerta serie software tienes que planificar cuidadosamente tu sketch y el orden en el que recibirás los datos.
Consideremos un ejemplo: quieres conectar un GPS y un termómetro usando puertas serie software. Los dispositivos GPS suelen enviar sus datos en paquetes espaciados un segundo entre sí, de manera que tu sketch puede comenzar escuchando la puerta serie software y una vez ha recibido el primer paquete de datos pasar a escuchar la otra puerta software, procesar sus datos y devolver la escucha al GPS.
Este sketch muestra cómo funciona esto en la práctica:
#include <SoftwareSerial.h> SoftwareSerial gpsPort(2, 3); SoftwareSerial thermPort(4, 5); void setup() { gpsPort.begin(9600); thermPort.begin(9600); } void loop() { gpsPort.listen(); while (gpsPort.available() > 0) { char inByte = gpsPort.read(); } thermPort.listen(); while (thermPort.available() > 0) { char inByte = thermPort.read(); } }
Como puedes ver la librería SoftwareSerial es una contribución fantástica a tu entorno de desarrollo, pero tienes que tener cuidado al usarla con más de una puerta software.
Esto cierra el capítulo de librerías estándar. Te puedes preguntar, qué sucede si quieres usar periféricos o dispositivos que no están cubiertos por las librerías estándar o de base (core).
Casi con seguridad existe una librería escrita por otro usuario que se puede adecuar a tu proyecto. En el próximo capítulo vamos a ver cómo usar estas librerías llamadas “contributed libraries”.
Las “contributed librairies”
Estas librerías son contribuciones de los usuarios del Arduino que no se distribuyen como parte del entorno de desarrollo IDE. Puedes encontrar muchas de estas librerías listadas en el sitio web Arduino.
Algunas de estas librerías son extensiones de las librerías estándar que añaden algunas funciones suplementarias, y con el tiempo, si estas funciones resultan ser útiles, el equipo de desarrollo puede añadirlas a las librerías estándar o incluso a la librería de base. Otras “contributed librairies” están diseñadas para funcionar con dispositivos específicos como consolas de juegos.
Dado que estas librerías no forman parte del IDE vas a necesitar hacer una serie de operaciones previas para poder trabajar con ellas. En el siguiente capítulo explicamos cómo proceder.
Para añadir una nueva librería al entorno de desarrollo IDE basta con realizar las siguientes operaciones:
- Bájate la librería (que va a venir normalmente como un fichero zip).
- Instálala en el IDE copiando los ficheros extraídos del fichero zip al directorio establecido por defecto para las librerías. Si dicho directorio no existe tienes que crearlo.
- Si el IDE está ya funcionando tienes que reiniciarlo. Tras reiniciar el IDE la librería debiera estar disponible para inclusión en tus sketches.
- Añade la librería a tu sketch seleccionando Sketch > Import Library del menú
Nota: Una vez añadida la librería al IDE, queda disponible para su uso con futuros proyectos, de la misma manera que las librerías estándar. Una vez importada una librería en un sketch, todas sus funciones están disponibles en el sketch.
Cómo es una librería por dentro
Los sketches en Arduino utilizan C++ como lenguaje de programación, la mayor parte de la complejidad interna del Arduino queda enmascarada por las funciones disponibles en las diferentes librerías escritas en C++.
Una librería está constituida por al menos una clase C++. Una clase consiste en dos ficheros: un fichero cabecera (header con una extensión .h) y un fichero con una extension .cpp.
El fichero de cabecera (extensión .h o header) es una especie de mapa de la librería: declara las funciones de la librería y la descripción de la clase. El fichero .cpp contiene el detalle de la librería: el código de las funciones y las variables declaradas en el fichero header.
En el fichero cabecera se describe la librería de clases. En este ejemplo se describe una librería para un sensor de un detector de metales llamado DetMet que detecta el número de objetos de metal en una zona. Esta librería tiene dos funciones disponibles a nivel “public”: una inicializa el sensor DetMet y la otra actualiza las lecturas del sensor.
El fichero “header” sería:
#ifndef DETMET_H // (1) Incluye directiva “guard” #define DETMET _H #include <Arduino.h> // (2) Incluye librería del Arduino class MetDet // Comienzo de la clase MetDet { public: // Declaraciones de palabras clave públicas MetDet(); // (3) Declara “class contructor” MetDet void begin(); //Declara funciones públicas void update(); private: // Declara palabras clave privadas a la clase int pollMetDet(); // Declara funciones privadas int countFossils(int inputData); }; #endif // (4) Marca el fin de la directiva ifndef
Notas:
- El propósito de la instrucción #ifndef al comienzo del fichero es evitar que el código se incluya más de una vez en un sketch durante la compilación.
- La inclusión de la librería Arduino es opcional, pero puede ser necesaria si tu código usa elementos de esta librería como digitalWrite(), delay(), pinMode(), etc.
- Tras la instrucción “public:” se incluyen las funciones públicas de la librería así como el nombre del constructor de la librería (MetDet()).
- Tras la instrucción “private:” se especifican las funciones privadas a la librería, estas son las funciones que son solamente accesibles dentro de la librería. El final de la clase queda delimitado por la instrucción #endif .
Una vez completado el fichero “header” podemos pasar a codificar el fichero .cpp que contiene el código que implementa las clases y funciones de la librería.
Si el fichero “header” es el esqueleto de la librería, el .cpp es la carne sobre los huesos. Las clases y funciones declaradas en el “header” están desarrolladas en el .cpp:
#include "MetDet.h" //(1) Declara e incluye la clase MetDet MetDet::MetDet () { //(2) Declara “class constructor” } void MetDet::begin() { //Define las funciones públicas // Aquí iría el código de inicialización del sensor MetDet } void MetDet::update() { int data = pollMetDet(); int result = countMetales(data); } int MetDet::pollMetDet() {//Aquí iría el código para realizar el sondeo de metales con el sensor MetDet } int MetDet::countMetales(int inputData) {//Aquí iría el código para contar el número de metales encontrados al sondear }
- Notas: La declaración de la clase se incluye al principio del fichero antes de construir la clase (1). Tras la declaración de clase, se construye la clase MetDet() con las funciones públicas y privadas que constituyen la librería (2).
- Nota: los cuatro puntos (::) sirven para declarar que una función está dentro de la clase (MetDet). Se denomina “scope resolution operator”.
Una vez hayas acabado de escribir tu librería el siguiente paso es usarla desde tus sketches. Para hacer esto necesitas incluir una copia de los ficheros .h (“header”) y .cpp en un subdirectorio del directorio de librerías del Arduino que lleve el nombre de la librería:
libraries/MetDet/MetDet.h libraries/MetDet/MetDet.cpp
Utilización de librerías
Una vez creada la librería y almacenados sus ficheros en el directorio apropiado, puedes usarla en tus sketches y distribuirla de manera que otros usuarios puedan también trabajar con ella. Puedes compartir tu código en el siguiente sitio web: http://playground.arduino.cc. Este sitio es un buen lugar para compartir y encontrar código escrito por otros usuarios que puede serte útil.
El siguiente sketch muestra como la librería DetMet sería usada desde un sketch, con el Arduino conectado al detector de metales equipado de un sensor MetDet:
#include "MetDet.h" // (1) Incluye librería MetDet MetDet myMetDet // (2) Inicializa instancia de la clase MetDet void setup() { // Inicializa el sensor MetDet myMetDet.begin(); } void loop() { // Actualiza lectura del sensor myMetDet.update() }
- Notas: Es necesario incluir la librería MetDet (1) antes de inicializar cualquier instancia de la clase MetDet (2). El sensor MetDet se inicializa durante la fase setup y se actualiza en el bucle loop del sketch.
Si quieres compartir tus librerías es aconsejable empaquetarlas en un fichero zip con los ficheros de la librería (.h y .cpp) junto con algunos sketches de ejemplo. Los ejemplos deben de ubicarse en un subdirectorio de ejemplos:
Libraries/MetDet/Examples/MetDet.ino