huborarduino.com

La web de Hubor para la simulación de Arduino con Proteus

Banner Guia Programacion Arduino Con Proteus

[Proteus versión 8.2]

En varias de las lecciones de este curso hemos utilizado una serie de funciones auxiliares que nos facilitaron la utilización de temporizadores, básculas set-reset, control de un motor, etc. Aunque estas funciones que hemos utilizado repetidamente, por ejemplo las funciones iniTemp() y chkTemp(), siempre contienen el mismo código, nos hemos visto obligados a escribirlas una y otra vez en cada nuevo programa que construíamos.

Por supuesto, que podemos utilizar las facilidades que nos brindan los procesadores de textos actuales para copiar y pegar el código de unos proyectos a otros. Pero, tendríamos que acordarnos en qué proyecto las usamos para ir a su código y realizar el proceso de copia. Y, a medida que va pasando el tiempo, esta tarea puede terminar siendo una labor de búsqueda pesada y difícil.

En general, todos los programadores acaban utilizando una serie de funciones de forma bastante repetitiva en todos sus proyectos. Por eso surge el concepto de librería (en algunos países también se le conoce con el nombre de biblioteca). Una librería es un fichero (o una serie de ellos) que contiene una serie de funciones que pueden ser enlazadas y utilizadas por nuestro proyecto.

Nuestro entorno de desarrollo ya viene con una gran cantidad de librerías disponibles para utilizar en nuestros proyectos. Algunas ya las hemos ido utilizando a lo largo de este curso. Sin embargo en esta lección queremos dar un paso más allá que la mera utilización de librerías de terceras personas. Nuestro objetivo es aprender a construir nuestra propia librería con una serie de funciones básicas y a utilizarlas en uno de nuestros proyectos. Por supuesto que cada usuario podrá incluir más funciones o eliminar aquellas que él no considere útiles para adaptar la librería a sus necesidades particulares.

En primer lugar, tenemos que tener en cuenta una cosa importante para facilitar la utilización de nuestras librerías en nuevos proyectos. El lugar donde coloquemos nuestra librería nos facilitará su uso desde nuestro entorno de desarrollo. En concreto, el sistema de desarrollo de ARDUINO busca, por defecto, todas las librerías que se encuentran en el directorio 'libraries' de la carpeta donde tengamos instalado el entorno ARDUINO. En nuestro caso (windows 7 64bits) la carpeta se encuentra en la siguiente ruta:

Lec22 001

Y contiene las siguientes librerías:

Lec22 002

Como es lógico, en cada ordenador encontraremos una lista diferente según el número de librerías de terceros que hayamos instalado.

Nosotros, vamos a crear una librería llamada Hubor. Si el usuario quiere cambiar el nombre de su librería por uno que se adecúe más a sus gustos, sólo tiene que seguir todos los pasos de esta lección cambiando 'Hubor' por el nombre elegido en todos ellos. Lo importante es que mantengamos la coherencia a lo largo de todo el proceso para que su utilización sea intuitiva y sencilla.

La primera tarea consiste en crear un directorio de nombre 'Hubor' en la mencionada carpeta de librerías. Dentro de esta carpeta que acabamos de crear tenemos que escribir dos ficheros de texto. Uno de ellos lo llamaremos 'Hubor.cpp' y el otro 'Hubor.h'. Por ahora están vacíos, pero más tarde iremos añadiendo los códigos necesarios. El primero contendrá el código en lenguaje 'c' de nuestras funciones. El segundo es un fichero de cabecera con información para el compilador (normalmente, una declaración directa de clases, subrutinas, variables, u otros identificadores) para el uso de la librería.

El código completo del archivo Hubor.cpp se puede descargar desde este enlace: Fichero Hubor.cpp. Este fichero contiene el código de las siguientes funciones: iniTemp(), chkTemp(), flancoSub(), flancoBaj(), bascula_r(), bascula_s(), pulso(), pulso_mem(), parpadeo(), retraso() y ctrlMotor(). En el código, delante de cada función, figura una pequeña explicación del funcionamiento de cada una de ellas y de la forma de utilizarla dentro de nuestro código. A efectos de esta lección, vamos a concentrarnos en el comienzo del archivo con el código de las dos primeras funciones, de sobra conocidas para quien siga este curso puesto que las hemos utilizado en varias lecciones. El resto de las funciones siguen un procedimiento de construcción similar.

Lec22 003

Es importante observar que nuestro fichero, después de los comentarios con la información de la librería, contiene dos sentencias #include. Cuando utilizamos una sentencia include, le estamos indicando al compilador que incluya en ese punto el archivo correspondiente y lo compile con el resto de los ficheros fuente que forman nuestro programa. Puesto que sólo le indicamos el nombre del archivo, el compilador entiende que lo tiene que buscar en el mismo directorio donde se encuentra el archivo que lo está llamando (en nuestro caso la carpeta Hubor que acabamos de crear y que es dónde está situado el archivo Hubor.ccp) o en alguno de los directorios definidos por el compilador como lugares de búsqueda por defecto.

Por lo tanto, con estas dos sentencias #include estamos diciendo al compilador que incluya en este punto los ficheros 'Hubor.h' y 'Arduino.h'. el primero es el fichero de cabecera que acabamos de crear para nuestra librería y el segundo contiene una serie de definiciones utilizadas de forma estándar por el entorno de programación ARDUINO. En realidad, estas definiciones incluidas en el fichero 'Arduino.h' las hemos estado utilizando en todos nuestros proyectos hasta ahora. Cuando creamos un programa en ARDUINO, el compilador enlaza a este fichero por defecto de forma automática para nosotros. Pero cuando construímos una librería no lo hace y, por ese motivo, se lo tenemos que indicar expresamente.

El resto del fichero es el código de todas las funciones, tal y como lo hubierámos utilizado en cualquiera de nuestros proyectos.

A continuación vamos a escribir el código del fichero de cabecera 'Hubor.h'. Lo podemos descargar desde el siguiente enlace: Fichero Hubor.h. Como ya dijimos antes, contiene las definiciones para ayudar al compilador a utilizar la librería.

Lec22 004

En la línea 15 utilizamos una sentencia #include como la que acabamos de ver en el fichero Hubor.cpp para incluir el fichero con las definiciones estándar utilizadas por el entorno ARDUINO.

En las líneas 17 a 19 definimos los operadores lógicos para su utilización en nuestro código.

En la linea 21 declaramos la estructura MotorDatosControl que ya vimos en la Lección 19 y que se utiliza en la función ctrlMotor() para intercambiar datos.

Y, por último, de las líneas 35 a la 45 se incluyen los prototipos de todas las funciones incluídas en la librería. Un prototipo es una declaración de una función que se lleva a cabo con dos propósitos principales: evitar conversiones erróneas de valores (al definir el tipo de dato que utilizamos para cada parámetro pasado a la función y el tipo de dato que devuelve la propia función) y evitar errores en el número de argumentos pasados a la función.

Y ya tenemos todo listo para utilizar nuestra librería 'Hubor.h' en cualquier nuevo proyecto. Vamos a crear el siguiente montaje:

Lec22 005

Donde utilizaremos nuestro Arduino con cuatro entradas (tres pulsadores y un interruptor) y siete salidas para gobernar otros tantos leds.

El código de nuestro programa será el siguiente:

Lec22 006

Lec22 007

Observe que la manera de poder utilizar todas las funciones almacenadas en nuestra librería no puede ser más sencilla. Sólo con utilizar en la línea 10 la sentencia #include correspondiente ya las tenemos todas disponibles.

El resto de código ya no tiene que tener secretos a esta altura del curso. Primero definimos las variables de trabajo que vamos a utilizar. Luego la configuracion de los piines que vamos a usar como entradas y salidas en la función setup(). Por último el código de trabajo que se repetirá de forma cíclica en la función loop().

En la primera parte leemos los valores de las entradas. En la segunda, utilizamos las diferentes funciones de la librería. En la tercera, escribimos las salidas. Y en la cuarta y última parte, usamos las funciones de tiempo chkTemp() e iniTemp() para enviar información cada segundo al exterior. Como en este caso no utilizamos las comunicaciones, hemos utilizado este espacio para cambiar de valor una variable llamada flag1 que utilizamos para encender y apagar cada segundo el led incluído en la placa base de ARDUINO y conectado al pin IO13.

Si ejecutamos nuestro proyecto podemos ver como funciona cada una de las funciones de la librería. En este punto hay que hacer una salvedad importante. Para que Proteus vuelva a leer todas las librerías disponibles en el directorio 'libreries' de la carpeta 'Arduino' en lugar de compilar nuestro proyecto como siempre con la opción 'construir proyecto', necesitaremos utilizar la opción 'reconstruir el proyecto'. Una vez hecho esto la primera vez, ya podemos utilizar la opción 'construir proyecto' como siempre.

Lec22 008

Veamos con detalle el uso de las funciones:

Lec22 009

flancoSub() detecta el flanco de subida al pulsar el botón arranque1. Ese pulso de subida lo utilizamos para alimentar el set de la función bascula_r() y por lo tanto se activa la salida1. Cuando actuemos sobre el interruptor parada1 que utilizamos para alimentar el reset de la función bascula_r se desactiva la salida1.

flancoBaj() detecta el flanco de bajada al pulsar el botón arranque2. Ese pulso al cesar la señal lo utilizamos para alimentar el set de la función bascula_s() y por lo tanto se activa la salida2. Cuando actuemos sobre el interruptor parada1 que utilizamos para alimentar el reset de la función bascula_s se desactiva la salidas.

La diferencia entre bascula_r() y bascula_s() es la dominancia del set o el reset en caso de que ambas señales lleguen al mismo tiempo. Podemos comprobar su funcionamiento diferente ejercitando con este ejemplo.

pulso() genera un pulso de duración igual a 5000mseg cuando se recibe la señal del pulsador arranque2 y lo muestra en la salida3.

pulso_mem() genera un pulso de duración igual a 5000mseg cuando se recibe la señal del pulsador arranque2 y lo muestra en la salida4. 

La diferencia entre pulso() y pulso_mem() es que la primera interrumpe la salida si cesa la señal de entrada mientras que la segunda memoriza la orden de entrada y la sigue generando después de cesar el disparador. Para interrumpir el pulso antes de alcanzar el tiempo podemos utilizar el parámetro reset de la función (en este caso parada1).

parpadeo() genera una intermitencia sobre la salida5 mientras esté activa la entrada arranque3.

Por último, retraso() activa la salida6 1500mseg después de que se produzca la entrada3. Si la entrada cesa antes de que pasen los 1500mseg no se llegará a generar la salida6.

Por supuesto, que el lector ya está en condiciones de construir la librería con las funciones que él desee. Además podrá ir incorporando con el tiempo nuevas funciones acumulando trabajo para el futuro.

Esperamos que esta leccion haya resultado interesante y que la utilización de librerías sea una práctica habitual en los próximos proyectos.

 

 

Comparte este artículo en redes sociales

Submit to FacebookSubmit to Google PlusSubmit to TwitterSubmit to LinkedIn


Esta página es propiedad de Hubor.

2014.

¡Atención! Este sitio usa cookies y tecnologías similares. Si no cambia la configuración de su navegador, usted acepta su uso. Ampliar información