Crea tus propias librerías para Arduino
Si has estado creando con Arduino, seguramente ya hayas recurrido a librerías externas para facilitarte acceso a módulos o facilitarte la vida de alguna manera. Pero, ¿sabías que tú también puedes crear tus propias librerías para simplificar tus programas y reutilizar código útil en otros proyectos?
¡Vamos a ver cómo podemos hacer esto creando una librería de cero!
¿Qué es una librería?
Una librería en Arduino es una serie de rutinas, clases y trozos de código que han sido escritos para usarse en varios proyectos y así acelerar el ritmo de trabajo del programador.
¿No querrías tener que, por ejemplo, reescribir el mismo código para mover un motor paso a paso en cada uno de tus que incluya este componente, no?
Siempre puedes copiar y pegar el código ya usado, pero esto puede dar lugar a errores, y ya ni hablamos sobre utilizar trozos de código de terceras personas.
Imaginemos que usamos un módulo complejo con nuestro Arduino, ¿imaginas lo tedioso que sería tener que escribir el código que interactuase con este hardware para cada módulo que utilizáramos? Por este mismo motivo, los módulos de Arduino casi siempre vienen con una librería que nos ofrece una serie de funciones con las que hablar con los componentes del módulo en cuestión.
En resumen, una librería no es más que código escrito para ser incorporado en otros programas, piensa en ellas como colecciones de funciones preparadas de antemano para ayudarte a alcanzar algún objetivo en concreto.
Escribiendo la librería
Escribir una librería en Arduino es una tarea sencilla, pero requiere conocer un poco de programación en C++. En este artículo, crearemos una librería muy básica para controlar un motor paso a paso, como el que vimos en este artículo anteriormente:
El código de nuestra librería lo dividiremos en dos partes:
- Una cabecera que incluirá las definiciones de todas nuestras funciones (dentro de una clase en nuestro caso);
- un archivo de código fuente que describirá el código de las funciones declaradas en la cabecera.
Después de escribir estos archivos, será cuestión de incluir la cabecera en nuestro programa, como con cualquier otra librería, pero primero empecemos por escribir la cabecera:
Ver en GithubVamos a desgranar el código, para poder entenderlo bien.
Primero empezamos escribiendo unas protecciones para el preprocesador. Básicamente le dicen al compilador que si la variable indicada, en este caso libPaso_h
(pero podría ser cualquier valor), no ha sido definida, que la defina y continúe incluyendo el resto del documento, hasta llegar al final del condicional. Esto evita que la cabecera se incluya más de una vez, problema que podría surgir si, por ejemplo, varios archivos incluyeran esta cabecera. Simplemente recuerda añadir estas protecciones en tus archivos de cabecera, ¡recordando cambiar el valor a definir!
A continuación, incluimos las librerías de Arduino. Esto se hace normalmente automáticamente en tus programas de Arduino, pero en el caso de librerías, es necesario hacerlo manualmente.
Procedemos a el bloque principal de nuestra cabecera, definimos una nueva clase que llamaremos MotorPaso
. Será con esta clase que crearemos después un objeto que controle el motor paso a paso del programa principal.
En cuanto a sus miembros, definimos un constructor que tomará los pines del motor paso a paso, una función para definir los modos de dichos pines y una función que usaremos para mover el motor hacia delante o hacia atrás.
Y en cuanto a las variables, tendremos los valores de los pines que usaremos para mover el motor y una variable que nos indicará en qué estado nos encontramos actualmente.
Recuerda que puedes consultar el artículo sobre el motor paso a paso para encontrar las tablas con los valores para cada estado:
En el archivo de código fuente simplemente nos dedicamos a definir todo lo declarado en la cabecera:
Ver en GithubA partir de ahora vamos función a función. No dejes que la nomenclatura te confunda, el MotorPaso::
solo indica que la función es un miembro de esa clase.
MotorPaso::MotorPaso(int pin1, int pin2, int pin3, int pin4)
: mPin1(pin1)
, mPin2(pin2)
, mPin3(pin3)
, mPin4(pin4)
, mState(0)
{}
Empezamos con el constructor; se trata de un constructor vacío con una lista de inicialización en la que asignamos los valores de las variables de los pines a los valores que se nos suministra.
void MotorPaso::begin()const{
pinMode(mPin1,OUTPUT);
pinMode(mPin2,OUTPUT);
pinMode(mPin3,OUTPUT);
pinMode(mPin4,OUTPUT);
}
Pasamos a una función para ajustar los pinModes
; normalmente esto lo haríamos en el constructor, pero tratándose de Arduino, es mejor hacer este tipo de operaciones en el setup
, por lo que no lo incluimos en el constructor.
La función setPins
simplemente se encarga de asignar valores altos o bajos a los pines según el estado actual:
void MotorPaso::setPins(){
switch(mState){
case 0:
digitalWrite(mPin1,HIGH);
digitalWrite(mPin2,LOW);
digitalWrite(mPin3,LOW);
digitalWrite(mPin4,LOW);
break;
case 1:
digitalWrite(mPin1,LOW);
digitalWrite(mPin2,HIGH);
digitalWrite(mPin3,LOW);
digitalWrite(mPin4,LOW);
break;
case 2:
digitalWrite(mPin1,LOW);
digitalWrite(mPin2,LOW);
digitalWrite(mPin3,HIGH);
digitalWrite(mPin4,LOW);
break;
case 3:
digitalWrite(mPin1,LOW);
digitalWrite(mPin2,LOW);
digitalWrite(mPin3,LOW);
digitalWrite(mPin4,HIGH);
break;
}
}
Y por último tenemos la función que hace que el motor se mueva. Toma un booleano como variable de entrada para definir la dirección del movimiento. Simplemente actualizamos el estado de los pines con la función setPins definida anteriormente y después incrementamos y disminuimos el valor del estado actual, teniendo cuidado de recolocarlo en el valor más alto o más bajo si alcanzamos el último estado del bucle, con tal de hacer que dé la vuelta por completo:
void MotorPaso::move(bool direction){
// activamos los pins correspondientes para el estado actual
setPins();
// avanzamos o retrocedemos según la dirección
if(direction)
mState++;
else
mState--;
// recolocamos el estado en 0 o 3 cuando llega al limite
if(mState<0)mState=3;
if(mState>3)mState=0;
}
Instalamos la librería
Una vez escrita, la instalación es muy sencilla, simplemente basta con navegar hasta nuestro directorio de Arduino en el ordenador y encontrar o crear una carpeta llamada “libraries”:
Es aquí donde moveremos nuestros dos archivos dentro de una carpeta con el nombre de la librería. ¡Y con eso ya estaría instalada!
Escribimos un programa que use nuestra nueva librería
Pero claro, la librería por sí sola no hará nada, necesitamos escribir un programa que la utilice:
Ver en GithubEste programa se parece mucho al que hicimos para controla el motor paso a paso, pero ahora eso está controlado por nuestra librería. Para utilizar nuestra nueva librería basta con incluirla al principio del programa:
#include <libPaso.h>
Y después crear un objeto de MotorPaso
, al que llamamos miMotor
en este caso, con los pines del motor paso a paso:
MotorPaso miMotor(2,3,4,5);
Procedemos a establecer los pinModes
en el setup()
y nos movemos unos segundo hacía delante y otros hacia atrás, controlando el tiempo entre pasos de forma externa con un delay()
.
Esquemático
Utilizamos el mismo circuito que en nuestro artículo anterior:
Y comprobamos que nuestra librería funciona perfectamente.
Conclusiones
Está claro que esta librería no está nada optimizada, pues he preferido hacerla más sencilla y fácil de entender, pero como desafío, sería un buen ejercicio optimizar la función setPins()
para ir moviéndose por un contenedor, incluir el tiempo entre pasos en la misma clase (y sin delay()
), o implementar el movimiento de medio paso. ¡Ánimos!
Si estás buscando una alternativa económica a Arduino, sobre todo si es la segunda o tercera placa, recomiendo las alternativas económicas de Elegoo que puedes encontrar en Amazon, tal y como explico en mi guía de compras: