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
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.
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)
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 :
- 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,
- 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,
- 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),
- lo cuarto que hacemos es definir concretamente qué es lo que va a hacer nuestra función,
- 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
- 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.
Publicado por
Protoboard
en
2:00
No hay comentarios:
Enviar por correo electrónicoEscribe un blogCompartir en XCompartir con FacebookCompartir en Pinterest
Etiquetas:
argumentos,
código,
Función
Suscribirse a:
Entradas (Atom)