En este capitulo aprenderá a:
- Conocer los fundamentos de la programación
- Usar el entorno de desarrollo
- Crear sketches desde cero
- Usar el monitor serial.
Si se ha comprado una placa Arduino , es porque se le quiere dar una utilidad o probar su funcionamiento, dicho de otro modo, queremos hacer algo con ella. Para poder indicar que debe hacer y bajo que estímulos o condiciones, utilizaremos la programación.
La programación del Arduino esta basada en C, por lo que aquellos que tengan una base en C o Java(por usar estructuras semejantes)les será mucho mas sencillo avanzar en este capitulo, pero como se vera es muy sencillo crear programas.
General
Los sketches de Arduino están compuestos ficheros que contienen las instrucciones a ejecutar por el microcontrolador. Estos ficheros a su vez se componen de bloques de código con una finalidad determinada.
Los bloques de código se encuentran entre llaves que sirven para marcar el alcance de cada uno de ellos. Estos bloques pueden identificar funciones ,bucles , condiciones…
A diferencia de otros lenguajes de programación , aquí no se debe terminar cada linea de código con algún carácter, pero si se debe terminar cada instrucción mediante el carácter “;” , es decir podemos dar una instrucción y varias líneas mas abajo poner el “;” siempre que no haya mas instrucciones por el medio.
Aspecto
Todos los programas de Arduino tienen un aspecto similar en su composición principal, del mismo modo que en C podemos encontrar el main(), en Arduino los programas son semejantes a:
//inclusión de librerías
//definicion de variables;
//Configuracion de la placa
void setup(){
//se configuran los pines necesarios
}
//Bucle principal
void loop(){
// se ejecutan periodicamente
}
//Funciones
void Function(){
//funciones personales
}
Lo primero de todo es comenzar importando las librerías necesarias para la Programación del Arduino. Las librerías son bloques de código creados por nosotros mismos o por terceros, que encapsulan instrucciones con funcionalidad establecida, y que pueden ser reutilizados en otros programas.
El bloque setup() es en realidad una función que se ejecuta cada vez que se enciende la placa o se realiza un reset de la misma. Se ejecuta una y solo una vez por cada encendido de la placa y nos sirve para configurar el uso de pines, inicializar variables…
El bloque loop() es el corazón del sketch, como su propio nombre indica ejecuta una y otra vez en bucle lo que se encuentre en su interior. Se ejecuta después del bloque setup() y es el que tiene el control de la placa Arduino.
Sera dentro de el donde tendremos que leer las entradas, procesar los datos y escribir en las salidas.
Por ultimo el bloque function() en este caso nos sirve para representar todas las funciones adicionales que queremos crear, aunque en un punto posterior se trata con mas profundidad, una función es un bloque de código que se puede llamar en el programa desde distinto puntos.
Realmente las únicas secciones necesarias para que compile el sketch son los bloques loop() y setup(), so bien casi con toda seguridad necesitaremos hacer uso de alguno de los otros bloques o de todos ellos.
Estilo
El lenguaje de programación de Arduino, permite un estilo de programación bastante laxo, siempre que se cumplan unas pocas reglas claro.
Algunos lenguajes de programación exigen una codificación manteniendo unas tabulaciones entre líneas , obligan a dejar ciertos espacios entre operandos o no permiten tener mas de una instrucción por linea. Nada de esto aplica a em la Programación del Arduino.
Las instrucciones siguientes sirven para definir tres constantes:
const int buttonPin =2;
const int led1Pin = 4;
const int led2Pin =5;
Pero se podrían haber escrito:
const int buttonPin =2; const int led1Pin =4 ; const int led2Pin =5;
O incluso:
const int buttonPin =2 ; const int led1Pin
=4
; const int
led2Pin =5;
Aunque resulta mucho mas difícil de leer.
Las instrucciones en Arduino vienen marcadas por el carácter “;” que marca fin de instrucción y comienzo de una nueva, y si bien es cierto que se suele poner una instrucción por linea de código para facilitar su lectura, nada impide poner varias instrucciones por linea.
Los bloques de código vienen dados por la pareja de llaves que encierran el código correspondiente, pero estas llaves pueden ser colocadas a gusto del programador. Normalmente se usan dos estilos, poniendo la llave de apertura en la misma linea que el identificador de bloque:
void function(){
//datos
}
O poniéndolo en una linea inferior para marcar mas claramente el bloque:
void function(){
//datos
}
Comentarios
Los comentarios son anotaciones que se hacen en el código con tal de ser mas fácil entenderlo mas adelante. A medida que los programas son mas complejos, se hace mas difícil entender el código escrito y para facilitar esta tarea se deben añadir comentarios en lenguaje humano.
El comentario de linea sirve para hacer pequeñas anotaciones de una sola linea y suele utilizarse para aclarar las inicializaciones de variables y situaciones semejantes.
Para realizar un comentario de este estilo, se introduce una doble barra que marca comienzo de comentario; el final de comentario lo marca el fin de linea. Por ejemplo:
const int led1Pin = 3; // Es el led verde
const int led2Pin = 4; //Es el led rojo
El comentario de bloque permite mas flexibilidad en su uso. Para comenzar el bloque comentado se introducen los caracteres “/*” y para terminar el bloque “*/”. Todo lo que se encuentre entre medias se considera comentario.
Las variables
Las variables son la parte del código que sirve para almacenar datos en memoria y trabajar mas adelante con ellos. Se identifican por un nombre que puede ser desde una letra hasta una frase entera, pero teniendo en cuenta que el nombre debe empezar por una letra o el carácter “_”, siendo el resto del nombre un carácter numérico o una letra, bien sea mayúscula o minúscula y sin espacios.
Para definir la variable no solo hace falta el nombre de esta, también hay que indicar el tipo de valor que va a contener la variable, si será una cadena de texto, un carácter, un numero entero… Esto sirve para dos cosas:
- Permite al compilador tener una lista de variables con tipos y poder chequear en busca de errores, por ejemplo multiplicar una cadena de texto por un entero.
- Hacer que el compilador pueda tener información sobre la cantidad de memoria que va a necesitar para cada variable cuando se ejecute el programa y el tipo de operaciones que soporta.
Los tipos de variables se representan por una serie de palabras reservadas que no podemos usar como nombre de variables ni funciones. En Arduino los tipos disponibles son:
- void: Es el tipo nulo. Se usa solo en la declaración de las funciones, significa que la función no devolverá nada cuando retorne después de su ejecución.
- boolean: sirve para guardar verdadero o falso , solamente puede tener dos valores true o false. Ocupa un byte de memoria. Ej: boolean error = false;
- char: Mantiene un carácter. En memoria ocupa un byte. Para informarlo se debe utilizar la comilla simple , guardando la comilla doble para las cadenas de texto, es decir ‘s’ es un caracter, pero “s” es una cadena de texto y no se puede guardar en una variable de este tipo. Ej: char killMe =’x’;char other = 64 // es la @
- unsigned char: Mantiene valores de 0 a 255, es lo mismo que el tipo byte y se aconseja el uso de byte en lugar de este tipo de dato. Ej: unsigned char years = 33;
- byte: Guarda un valor de 0 a 255. En memoria ocupa (como su nombre indica) 1 byte (8bits). Ej: byte years = B100001;//33 en decimal.
- int: En memoria ocupa 2 bytes(16 bits) y utiliza complemento a dos para guardar los números negativos. El echo de trabajar en complemento a dos con números negativos hace que se deba tener especial cuidado en operaciones de bitshift o desplazamiento de bits: Ej: int years = -33;
- unsigned int: Es semejante al tipo int con la diferencia que guarda solamente números positivos. Ocupa 2 bytes en memoria y en este caso puede guardar valores numéricos desde 0 a 65535. Ej: unsigned int years = 33;
- word: es idéntico en memoria al tipo unsigned int y como el , puede guardar valores numéricos desde 0 hasta 65535 Ej: word years = 1880;
- long: Mantiene valores numericos superiores al tipo int. En memoria ocupa 4 bytes(32bits) y puede guardar valores negativos. El rango de valores es de -2,147,483,648 a 2,147,483,648 Ej: long amount = -34254329L;
- unsigned long: Parecido al tipo long pero solo para valores positivos. Ocupa en memoria 4 bytes lo que da lugar a un rango de valores de 0 a 4,294,297,295 Ej: unsigned long amount = 34254329L;
- double: Debería doblar la precisión del tipo float pero por el momento es idéntico a este.
- array: El array o arreglo es una colección de variables del mismo tipo que se acceden mediante un índice que indica la posición en la que se encuentra el valor dentro de la colección. Ej: int days[] ={22,11,19,12}.
Advertencia: |
---|
Los arrays tienen como índice del primer elemento el 0, es lo que se llama zero indexed o zero based, entonces si se crea un array de 5 posiciones, el índice de la ultima es 4. Además, en caso de intentar acceder al elemento con índice 5, no daría error como en java , si no que devolvería lo que hubiera en memoria una posición mas allá de donde se encuentre alojado el array, devolviendo realmente cualquier dato totalmente impredecible y en caso de escribir mas allá de los limites del array, el resultado puede ser que el programa se vuelva inestable. |
Modificadores
Cuando se declaran las variables, se les puede añadir ciertas palabras reservadas que modificaran el comportamiento estándar de las mismas. Estos modificadores son:
- Static: Al añadir la palabra static a una variable se indica que la variable es visible solo en la funcion en la que esta declarada y que su valor debe persistir entre distintas llamadas a la misma funcion. Mantienen el valor de las variables entre distintas llamadas a la función. Ej: static int years = 10;
- volatile: Es una directiva de compilador que modifica el modo en el que este tratara la variable. Se usa cuando se trabaja por ejemplo con interrupciones. Ej: volatile int error Num=0;
- const: Esta convierte la variable en una constante, no se puede modificar su contenido y en caso de intentarlo se recibirá un error de compilación. Ej: const float gravity = 9.8;
Constante enteras
Cuando se programa es habitual utilizar constantes numéricas para asignar a variables o constantes por ejemplo en int years = 123; 123 es una constante (no years… que es una variable, sino el 123 en si) ya que siempre tendrá el valor 123. En Arduino estas constantes se tratan como enteros con signo en base 10 por defecto (tipo int), pero se puede hacer que traten de distintas maneras.
Para indicar otro tipo de base que no sea la base decimal, Arduino ofrece también algunos modificadores, concretamente disponemos para las bases binaria, octal y hexadecimal (muy útiles cuando se trabaja a nivel de bits). Los modificadores son ‘B’ para binario, ‘0’ para octal y ‘0x’ para hexadecimal y se deben poner delante del valor que se quiere expresar en la base.
El modificador binario solo puede tener como caracteres 1 y 0. Trabaja en 8 bits dando valores entre 0 y 255. En caso de ser necesario indicar valores binarios de mas de 8 bits se debe hacer manualmente multiplicando el byte superior por 255:
int myValue =(B10000101 * 256) + B11101100; //34284 en decimal
El modificador octal expresa en base 8 y solo puede tener como caracteres números del 0 al 7. Ej: int myValue = 0123; //83 en decimal
El modificador hexadecimal expresa el numero en base 16 y los caracteres validos son los números y las letras de la ‘A’ a la ‘F’. Siendo el ‘A’ el 10 , la ‘B’ el 11 y sucesivamente hasta la ‘F’ el 15. Ej: int myValue =0x1A3;// 419
Operaciones
Una operación es una manipulación de una variable o varias con tal de modificar su contenido o comprarlo con algo. Arduino nos proporciona todas las operaciones necesarias o herramientas para implementarlas. Podríamos clasificar las operaciones en aritméticas, de comparación, con booleanos, a nivel de bit y de composición entre aritméticas o nivel de bit y de asignación.
Dentro de las operaciones aritméticas tenemos:
- =: Es el operador de asignación, da a la variable situada a la izquierda del operador el valor de lo situado a la derecha. No se debe confundir con el operador de comparacion ==. Ej: int i =8; // da el valor 8 a la variable i.
- +: Permite sumar dos operandos.
- –: Permite restar dos operandos.
- *: Permite multiplicar dos operandos.
- /: Permite dividir dos operandos.
- %: Es el operador llamado modulo. Obtiene el resto de una división entera. Ej: i=9 %4; // i tendría el valor de 1.
Truco: |
---|
Cuando se trabaja con constantes numéricas sin decimales, estas siempre se tratan como enteros en base 10. Si prestamos atención al ejemplo del tipo long visto anteriormente: long amount = -34254329L; aparece una L al final de la constante numérica; e separa forzar al compilador para que la trate como un long en lugar de como un int A la hora de ejecutar las operaciones Arduino utiliza los tipos de los operandos para obtener el resultado, así al realizar 5 /2 se obtendrá como resultado 2 como entero, por lo que se debe tener cuidado con los tipos seleccionados en cada operación. También se debe vigilar el desbordamiento por tipo de dato; el tipo int puede almacenar valores de -32,768 a 32,768, eso quiere decir que si tenemos una variable entera que tenga de valor 32,767 y le sumamos 1… automáticamente pasa a tener de valor -32,768 por desbordamiento. |
Las operaciones de comparación son:
- ==: Igualdad; compara si los operandos a cada lado de la operación son iguales o no y devuelve true en caso de ser iguales y false en caso de no serlo.
- !=: Desigualdad; compara si los operandos a cada lado de la operación son diferentes o no y devuelve true en caso de ser distintos y false en caso de ser iguales.
- >: Mayor que; compara si el operando situado a la izquierda operación es mayor que el de la derecha y devuelve true en caso de ser mayor y false e caso de no serlo.