viernes, 2 de mayo de 2014

Pasos para compilar un Sketch


En muchos sitios veréis que habitualmente se usa una palabra llamada "compilar".  El código se debe compilar antes de que nuestro Arduino pueda procesar el sketch que hemos escrito. Pero ¿qué es compilar un código? y ¿por qué necesitamos ejecutarlo antes de subir nuestro sketch a nuestro Arduino?

En esta entrada intentaremos explicar las tres fases que el IDE de nuestro microcontrolador necesita ejecutar para poder ejecutar las instrucciones que le hemos dado sin errores.

PROGRAMACIÓN (CODE)

El primer paso es escribir las instrucciones que queremos que lleven a cabo. Al igual que sucede con los seres humanos con los que podemos comunicarnos en distintos idiomas, con los microcontroladores podemos comunicarnos con distintos lenguajes. En nuestro caso nos comunicaremos con un lenguaje concreto de nuestro Arduino. Que está diseñado de una versión simplificada del lenguaje C.

VERIFICACIÓN (VERIFY)

Terminado de escribir nuestro sketch, ahora necesitamos, transformar nuestro código Arduino a un código  C/C++ puro (a este proceso se le llama "preprocesado"). Y ¿por qué no hemos escrito nuestro sketch directamente en C/C++? La razón es muy sencilla, la simplificación. El lenguaje Arduino está pensado para permitirnos escribir comandos e instrucciones de forma muy rápida y simple, para hacer lo mismo con lenguaje C, necesitaríamos haber dedicado bastante tiempo en entender este lenguaje y sus estructuras, y posiblemente muchos de nosotros habríamos abandonado antes de concluir el primer ejemplo.

Una vez terminado el preprocesado, ahora comienza el "enlazado". Y ¿esto que és?, pues básicamente consiste en insertar en nuestro código, no solo la llamada a la librería que hayamos decidido usar en nuestro sketch, sino todo el código de la misma. A fin de cuentas el programa que vamos a subir a nuestro microcontrolador debe estar completo y si por ejemplo vamos a usar una librería para usar una pantalla LCD sin complicarnos en saber cómo funciona, a nuestro Arduino, hay que darle todos estos detalles que sí vienen bien descritos en el interior de la librería que vayamos a usar. En caso contrario no sabría cómo ejecutar las ordenes que les hayamos dado.

En el caso de utilizar el IDE oficial, el código binario generado (ya sea ".hex" o ".bin") solo lo guarda de forma temporal hasta que es cargado (subido) en la memoria del microcontrolador.



SUBIR (UPLOAD)

Si en los pasos anteriores no se ha encontrado ningún error, se carga (se sube) el código binario resultante en la memoria de nuestro Arduino. Eso se realiza mediante el botón "Subir" (Upload).



Cada uno de los pasos anteriores es realizado internamente por una parte separada del IDE de nuestro microcontrolador, que nosotros no vemos. Pero si quisiéramos verlas, podríamos hacerlo de forma manual, ejecutándolas una a una. Si tenéis curiosidad de cómo se podría hacer, en una próxima entrada lo explicaremos paso a paso. Pero tanto manual (que nos llevará algo más de tiempo) como automático (gracias al uso de los botones de nuestro IDE, el resultado será exactamente el mismo.


Esperamos que ahora os quede más claro, qué es y por qué es necesario compilar un sketch.

Pero si tenéis alguna duda o sugerencia, no dudéis en contactar con nosotros intentaremos resolver vuestras dudas tan pronto como podamos.




jueves, 1 de mayo de 2014

Introducción a la estructura de los programas usados en el Arduino: Sketchs








Introducción a la estructura de los programas usados en el Arduino: Sketchs

Se denomina Sketch al código que necesitamos escribir para que sea interpretado por nuestro Arduino. Normalmente lo escriberemos dentro del la aplicación que nos permite traducir instrucciones simples que los humanos podamos entender al lenguaje que entiende nuestro Arduino. Esta aplicación se llama IDE (Entorno de Desarrollo, o en inglés Integrated Development Environment) y genera ficheros con extensión ino.
Un sketch se compone al menos de dos partes. Mejor dicho, un sketch necesita de dos bloques para poder ser compilado correctamente (que es la palabra técnica que se utiliza para el proceso de traducir las instrucciones que estamos escribiendo a un lenguaje que pueda entender el microprocesador).
Estructura de un Sketch 

void setup()
{
  y aquí escribimos las instrucciones en líneas separadas por ;
}

void loop()
{
  y aquí escribimos las instrucciones en líneas separadas por ;
}

El bloque setup()

La parte de código representada como void setup()   se ejecuta una sola vez cuando comienza el programa

Nos sirve para decirle al Arduino, qué partes de la placa vamos a usar para el proyecto que estamos desarrollando. Si Arduino fuera un cuerpo humano, sería algo así como decirle para el Sketch CogerLaPelota, solo necesitas usar los ojos y los brazos. Y de ese modo el robot concentra todos sus recursos en esas dos cosas, y se olvida de estar pendiente del olfato, del gusto, de la temperatura...  

En nuestro caso sería como que alguien te avise que vas a salir por la tele, y que tengamos que estar pendiente de 19 canales de televisión toda la tarde  a que nos digan “sintoniza TVE1”. Lo mismo le sucede a nuestro pequeño robot.

Es la forma de que sepa por donde y cómo queremos que interaccione con el mundo, es donde le decimos al Arduino, que pines de su placa vamos a usar y con qué objeto.  

En esta parte del sketch, es donde configuramos, qué pines y que finalidad va a tener, por ejemplo para enceder un LED, o bien para recibir algún dato, etc.

Aun cuando no escribamos nada en él, es necesario escribirlo y añadir las llaves de apertura y cierre { }.

En nuestro primer ejemplo, en el que enseñamos a guiñar un “ojo” que situamos en el pin 13, le decimos

void setup() {                  
 // aquí le decimos a nuestro Arduino que el LED, es para que hable, o lo que es lo mismo para mandar un mensaje de salida, un OUTPUT (salida en inglés)   
pinMode(led, OUTPUT);    
 }


El bloque loop()

Es la parte principal de nuestro programa pues en el tendremos que poner el código para que el microcontrolador lo ejecute de manera recursiva, es decir, esta parte del Sketch se repetirá una y otra vez mientras la placa Arduino tenga energía. Por ejemplo:

void loop() {
  digitalWrite(led, HIGH);   // enciende el LED (on)
  delay(1000);               // espera por un 1000 milisegundos   
  digitalWrite(led, LOW);    // apaga el LED (off)  
  delay(1000);               // espera por un 1000 milisegundos
}


Nota: Toda llave de apertura { ha de tener una llave de cierre al final del bloque de instrucciones, a modo de bocadillo }. Mientras editamos el código en el IDE de Arduino, si situamos el cursor justo después de una llave de apertura {, veremos resaltada la llave de cierre } asignada a la misma, permitiéndonos comprobar si lo que hemos escrito es realmente lo que hemos querido escribir.
Por su parte, el punto y coma ; se emplea para poner fin a una declaración (que es el nombre técnico que se le da a una instrucción concreta que hayamos escrito). El olvido del punto y coma es uno de los errores que más se repiten cuando se está empezando a programar.
Pero mirando nuestro Sketch más simple vemos que hay  además existe una instrucción solitaria al principio de todo
int led = 13;

que no va ni entre llaves, ni está dentro de las dos estructuras que hemos comentado 
void setup(), void loop()

Muy bien, veo que estáis en todo. Esto es lo que se conoce técnicamente como zona de declaración de variables.  Es algo parecido a un listín telefónico.  A todo el mundo le resulta más cómodo llamar a alguien por su nombre que por su DNI. Pues con ese propósito, el Sketch te permite apuntar en un sitio, cosas que vas a usar de forma repetitiva pero que no quieres memorizar. Por ejemplo la ubicación del LED de parpadeo. Decidimos que va a ser en el PIN número 13, pues a partir de ahí, con tal de referirnos a él como “led” basta. El IDE traducirá esa “variable” por el número 13.
Puede que ahora no le veas mucho sentido porque solo tenemos un LED y sabemos donde está.  Pero si tu Sketch tuviera 5000 líneas de código, y a mitad del proceso de programación decidiera cambiar la ubicación del LED al pin 8, tendrías que cambiarlo en cada instrucción que hayas dado al Arduino a lo largo de todo el programa, o bien, si has usado la zona de declaración de variable, cambiar int led= 13, por int led =8, y todo estaría funcionando en un solo segundo. ¿A que parece un buen truco?. Pues no se te olvide, eso se hace usando la declaración de variables.

¿Recordáis todo lo que hemos visto?: zona de declaración de variables, uso de llaves { }, bloque setup() y bloque loop().

¡Pues seguro que se os olvida algo! Y para eso están los comentarios. Si nuestro sketch, verás partes del código que están escritas en lenguaje  demasiado humano. Efectivamente hay frases que están escritas con objeto de autoexplicar lo que estamos haciendo y lógicamente no son entendible para el IDE de Arduino. Son como si fueran un “post-it” en el código para no olvidarnos de lo que hemos hecho, o por qué lo estamos haciendo. Un buen sketch va siempre acompañado de unos buenos comentarios, es decir, líneas de código que el programa ignorará y que nos servirán a la hora de entender mejor el código.
Existen dos tipos de comentarios, los de una línea y los de varias líneas:
- Los comentarios de una sola línea han de comenzar por //, y duran hasta que se encuentra un retorno de carro.

- Los comentarios de varias líneas o bloques de comentarios han de estar delimintados por /* al comienzo y por */ al final.
es → en
because
conjunción: since, then
adverbio: then, well

La estructura de una función




Una función es un bloque de código que tiene una cabecera y un cuerpo. En el lenguaje C estándar, la definición y declaración de la función se hacen en el fichero de cabecera (*.h).  Sin embargo el IDE del Arduino nos hace la vida más sencilla, y si necesitamos declarar una función, podemos hacerlo dentro del mismo código del programa principal (sketch).

Por ejemplo, si queremos crear una función que sume dos números enteros y nos devuelva el resultado, la llamada a la función podría ser algo así como

miSuma (número1, número2);

y nos devolvería el siguiente  = número1+número 2

Pero para que lo anterior lo entienda el IDE de Arduino como la declaración de una función, hace falta escribir el código siguiendo una serie de reglas concretas:

REGLA 1.-  Hay que definir cada tipo de elemento que vaya a usar o generar, para que pueda tratarlo convenientemente. No es lo mismo que te digan “vierte un litro de agua y en un litro de aceite” que nos digan “coge una tonelada de arena y un metro cúbico de cemento”. Para lo primero nos hará falta “reservar” un par de botellas de nuestra despensa y para los segundo tendremos que “reservar” alguna cuba industrial de las que se usan en las construcciones. Pues bien, nuestro Arduino, como nosotros tiene recursos limitados, y por ello necesita anticipar qué uso de su memoria tendrá que dedicar a cada cosa, y reservar ese espacio para que no se use en ningún otro proceso.

REGLA 2.- Hay que ponerle un nombre único a la función, para que podamos usarla cada vez que queramos. Algo representativo de lo que va a hacer, por ejemplo, encederLaBombilla, subirLaTemperatura, etc..

REGLA 3.-En caso de que la función vaya a devolver un valor, por ejemplo en el ejemplo anterior donde teníamos una función llamada miSuma, hay que ponerle un nombre a la variable donde se va almacenar el resultado, sin olvidar que le tenemos que aplicar la primera regla también, y tenemos que definir el tipo de resultado que va a suministrar (un texto, un valor numérico, etc..)

REGLA 4.- Hay que definir exactamente lo que va a hacer la función, en nuestro ejemplo de la función miSuma, pues sería algo al estilo

 resultado= número1+número2

REGLA 5.- Hay que definir si la función devolverá algún resultado o por el contrario consiste solo en la ejecución se una serie de instrucciones concretas. En nuestro caso usaremos que queremos que nos devuelva el resultado de la ecuación, sería algo como

return resultado

REGLA 6.- No hay que olvidarse de las llaves. Para que el IDE de Arduino sepa de qué se compone nuestra función, hay que usar un par de llaves, una tras definir el nombre de la función y otra, cerrando, tras la última instrucción. A fin de cuentas es como un bocadillo, todos son diferentes, los tenemos de tortilla, de chorizo, … pero siempre están contenidos entre dos trozos de pan.




Pues bien ahora que sabemos las seis reglas necesarias para definir una función, veamos como quedaría nuestra función miSuma.

int miSuma (int número1, int número 2)
{
            int  resultado;
            resultado = número1  + número 2;
            return resultado;
}

Como vemos :
  1. lo primero que hemos dicho es definir que tipo de función vamos a crear. En nuestro caso le hemos dicho que la función miSuma será un número entero (integer en inglés, int para el IDE), y tras ello (aplicando la sexta regla) abrimos una llave para especificar que lo que sigue será lo que definirá la función,
  2. lo segundo que hemos hecho es ponerle un nombre único a la función: miSuma. Por convección se comienza en minúscula y se concatena las palabras empezándolas por mayúsculas para facilitar su lectura. Y además le hemos dicho que para ejecutar esta función requerirá que le pasen dos cosas, a estas cosas, se le llaman Argumentos, y como aplicamos la primera regla,  definimos qué clase de argumentos serán, texto, número, o lo que sea, en nuestro caso también serán, cada uno de ellos, enteros (integer en inglés, int para el IDE), así mismo (aplicando la tercera regla) a cada objeto que se le pase, además de definir qué tipo de argumentos serán, tendremos que ponerle un nombre para luego poder hacer uso de él cuando haga falta,
  3. lo tercero que hacemos es definir el nombre de la variable donde guardaremos el resultado de la función, y aplicando la primera regla, definimos el tipo de resultado que será, en nuestro caso (integer en inglés, int para el IDE),
  4. lo cuarto que hacemos es definir concretamente qué es lo que va a hacer nuestra función,
  5. lo quinto, definir que queremos que una vez calculada la fórmula, queremos que nos devuelva el resultado, eso lo hacemos usando la palabra reservada return, y finalmente
  6. lo sexto, cerramos la función con una llave.
Notad que:
1.- Existen una serie de palabras reservadas que no se pueden usar para ningún otro propósito que el definido para ellas en el IDE. En nuestro ejemplo están marcadas en naranja, y son int (para referirnos a números enteros) y return (para ordenar a la función a que devuelva el resultado cuando termine de ejecutarse).
2.- Que después de cada sentencia acabamos con ";", para indicarle al IDE que hemos llegado al fin de una sentencia. A excepción de la declaración inicial de la función que no termina en ";" sino abriendo una llave "{".
3.- Que hemos formateado el texto, incluyendo una sangría a la derecha, con objeto de facilitar la lectura, aunque no es requisito del IDE, que se rige solo por las llaves y los ";"





¿Qué es una función?



Una función es un trozo de código definido por un nombre y que puede ser re-ejecutado desde diferentes puntos del programa.  Por ejemplo podríamos crear una función para apagar una luz o encender todos los LEDs que tengamos conectados.

El nombre de la función tiene que ser único dentro del programa.  Si dos códigos tuvieran el mismo nombre, el programa no sabría cuál es el que debería ejecutar en cada ocasión.

A veces puede requerir que le pasemos unos elementos especiales, llamados argumentos. Y también  a veces la función puede devolver resultados. Por ejemplo si enseñamos a una función a pasar de grados centígrados a grados Fahrenheit,  la función necesitará que le pasemos como argumentos la temperatura que queremos convertir, y el sistema al que queremos convertirlo, y el resultado será la solución de la fórmula que le hayamos pedido usar.