El lenguaje de programación que se utiliza en Arduino está basado en Processing, un lenguaje de programación muy similar a C++. A la hora de enfrentarnos a un desarrollo debemos tener claro desde el principio los tipos de datos en Arduino. En este artículo vamos a repasar los conceptos básicos a la hora de programar.
Lo primero que veremos son las directivas de precompilador. Estas directivas se ejecutan antes de compilar el código y no se ejecutan en tiempo de ejecución como el resto de código. Nos permite incluir ficheros, definir constantes y aplicar condicionales.
- #include
Con esta directiva podemos incluir ficheros externos a nuestro proyecto. Un ejemplo sería el uso de alguna librería que haga una función especial. Se puede definir de dos maneras diferentes.- #include Busca en los directorios de librerías por defecto
- #include “C:libreriasfichero.h” Una ruta completa al archivo
- #define
Esta directiva permite definir un alias a un texto y su uso más extendido es la declaración de constantes. La principal utilidad es que se puede reutilizar en cualquier parte del código afectando a todas las referencias que se hagan a partir de entonces. La norma aconseja poner todos los define en mayúsculas para identificarlos claramente. - Directivas condicionales #if #ifdef #ifndef #else #endif
Nos permite incluir o quitar código dependiendo de una condición. Un ejemplo claro puede ser cuando trabajemos en modo DEBUG es decir, cuando estamos haciendo pruebas. Podemos decir que en este caso nos escriba en el monitor serie información de como está funcionando nuestra aplicación. Esto se escribiría de la siguiente manera.#define DEBUG
#ifdef DEBUG
...
#else
...
#endif
En el código anterior estamos diciendo si está definida la constante DEBUG que ejecute un código en caso contrario otro código.
Ahora veremos los tipos de datos que podemos usar cuando programamos para Arduino. Para definir una variable debemos escribir primero el tipo, luego un nombre descriptivo y por último podemos asignar un valor inicial, esto último no es obligatorio en la declaración.
tipo nombre = valor;
Números
- Enteros
- byte: números sin signo que ocupan hasta 8 bits [0,255]
- (unsigned) int: números enteros de 16 bits, 2 bytes. [-32768, 32767] (unsigned 65535) Uno y en Arduino Due 32 bits, 4 bytes[-2,147,483,648, 2,147,483,647] (unsigned 2,147,483,647).
- word: son varialbes unsigned int
- (unsigned) long: 32 bits, 4 bytes[-2,147,483,648, 2,147,483,647] (unsigned 2,147,483,647).
- Coma flotante (decimales)
- float: variable numérica con coma flotante de 32 bits (4 bytes) [-3.4028235E+38 , 3.4028235E+38]
- double: es igual que los float
Textos
- char: carácter de 1 byte
- string: secuencia de char terminado por null char[5];
Complejos
- array: colección ordenada de variables del mismo tipo. Puede ser de una sola dimensión ([n]) o multidimensional ([n][m]…)
int d[2][2]={ {1,1},{1,0}}:
int c[3]={1,2,3};
- struct: colección de varias variables de diferentes tipos
struct posicion{
int x;
int y;
float angulo;
};
posicioon pos;
void setup(){
// Inicializamos la estructura
pos.x = 0;
pos.y = 0;
pos.angulo = 0;
}
Otros tipos de datos
- boolean: solo toma valores true o false. Ocupan un byte entero.
- void: solo se utiliza en los valores de retorno de las funciones para indicar que esa función no devuelve valor.
- enum: variables para almacenar estados predefinidos. Un ejemplo claro sería los estados de un sensor.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Declaramos la enumeración que nos indica el estado del PH
enum EstadoPH {
desconocido,
reposo,
activo,
error
};
// Declaramos una variable que almacenará el estado del PH
EstadoPH dispositivoph;
void setup(){
// Inicializamos la variable
dispositivoph = desconocido;
}
void loop() {
// Comprobamos el estado del dispositivo de PH
if(dispositivoph == desconocido)
{
// Cambiamos el estado del dispositivo de PH
dispositivoph = activo;
}
}
- typedef: este elemento genera un nuevo tipo de variable con el nombre que queramos darle. Se puede utilizar con cualquier tipo de dato que queramos. Veamos un ejemplo:
// Así se declara el typedef
typedef enum unaEnumeracion miNuevaEnum;
typedef float anguloRota;
typedef struct unaStructura miNuevaStru;
// Para declarar una variable de esos tipos
miNuevaEnum variableEnum;
anguloRota variableFloat;
miNuevaStru variableStru;
- union: permite apuntar a dos variables al mismo espacio de memoria.
union {
byte b[4];
float f:
} val;
Punteros
Almacena la dirección de memoria de otra variable. Es muy útil cuando estamos trabajando con variables con mucha información como por ejemplo estructuras o arrays muy grandes. En estos casos pueden llegar a tener cientos de bytes mientras que la dirección de memoria solo tiene 2 bytes. Para evitar pasar la información de un sitio a otro utilizamos los punteros que son la dirección física donde está guardada la información. Veamos un ejemplo:
// Declaramos una variable del tipo String con un texto largo String var1 = “Sed case blandit te, eos ignota imperdiet consectetuer et, in pro enim delenit. Ex lorem doming delicatissimi usu. Id expetenda periculis definitiones mei, ius soluta volutpat postulant ex. Id vitae impedit disputationi sed, sumo rebum te usu, te affert primis appetere his. Ut duo ferri mazim laudem, te alterum probatus definitiones nec, duo dolor aeterno mediocrem eu.”; // Declaramos un puntero que será del tipo int // Almacenará la dirección de memoria y se declara con el signo * antes del nombre int *p_var1; // Asignamos la dirección de memoria aplicando a la variable que se quiere obtener // la dirección de memoria el símbolo & p_var1 = &var1; // Modificar el puntero o la propia variable surte el mismo efecto *p_var1 = “Pepe”; |