Subido por Leandro Barcala

Programación C++ para Arduino

Anuncio
Referencia rápida
de Arduino
A continuación le mostramos una guía de referencia rápida de todas las
instrucciones estándar admitidas por el lenguaje de Arduino.
Si necesita más información al respecto, visite
http:/arduino.ccies/pmwik.php?n=Referente/ HomePage.
Estructura
Un sketch de Arduino se ejecuta en dos partes:
void setup()
En esta parte configuramos todo lo que tiene que ejecutarse antes de que se
inicie el bucle principal del sketch y que después no se necesitará más.
void loop()
Contiene el código principal de nuestro sketch. Es un conjunto de instrucciones
que se repite una y otra vez hasta que se apaga la placa.
Símbolos especiales
Arduino incluye diversos símbolos para definir líneas de código, comentarios
y bloques de código.
; (punto y coma)
Toda instrucción (línea de código) se termina con un punto y coma. Esta sintaxis
nos permite aplicar al código el formato que deseemos. Podemos incluso
colocar dos instrucciones en la misma línea, siempre que las separemos con
punto y coma (sin embargo, esta práctica dificulta la lectura del código).
Ejemplo:
delay(100);
{} (llaves)
Las llaves se usan para marcar bloques de código. Por ejemplo, cuando escribimos código para la función l oop O , tenemos que usar llaves antes y después
del código.
Ejemplo:
void loop() {
Serial.println("hola");
}
Comentarios
Los comentarios son partes de texto que ignora el microcontrolador de Arduino,
pero que son muy útiles para recordarnos (a nosotros y a otras personas) el
cometido de un fragmento de código. Existen dos estilos de comentarios en
Arduino:
// una sola línea: este texto se ignora hasta el final de la
línea /* varias líneas:
aquí podemos escribir
un poema completo
*/
Constantes
Arduino incluye un conjunto de palabras predefinidas con valores especiales.
Por ejemplo, HIGH y LOW se usan cuando queremos activar o desactivar un
pin de Arduino. INPUT y OUTPUT se usan para establecer un pin específico
como entrada o como salida. Las constantes true y false se indican si una
condición o expresión es verdadera o falsa, respectivamente. Se suele usar con
operadores de comparación.
Variables
Las variables son áreas con nombre de la memoria de Arduino en las que
podemos guardar datos. El sketch puede usar y manipular estos datos haciendo
referencia a los mismos por medio del nombre de variable. Como sugiere su
nombre, se pueden cambiar tantas veces como queramos.
Como Arduino es un microcontrolador muy simple, al declarar una variable
tenemos que especificar su tipo. Esto le indica al procesador el tamaño del
valor que queremos guardar. Estos son los tipos de datos disponibles:
boolean (booleano)
Pueden tener uno de dos valores: true o false.
char (carácter)
Contiene un solo carácter, como por ejemplo la letra A. Como sucede en otros
ordenadores, Arduino guarda este dato como un número, aunque nosotros
veamos texto. Cuando se usan caracteres para guardar números, pueden
contener valores comprendidos entre -128 y 127.
Nota: En los sistemas informáticos, hay dos conjuntos principales de caracteres:
ASCII y UNICODE. ASCII es un conjunto de 127 caracteres que se usaba, entre otras
cosas, para transmitir texto entre terminales en serie y sistemas informáticos de
tiempo compartido, como mainframes y miniordenadores. UNICODE es un conjunto
de valores mucho más amplio utilizado por los sistemas operativos modernos para
representar caracteres en una amplia variedad de lenguajes. ASCII sigue siendo
útil para intercambiar fragmentos cortos de información en idiomas como
español o inglés, que usan caracteres latinos, números arábigos y símbolos de
escritura comunes para la puntuación, etc.
byte
Contiene un número comprendido entre O y 255. Igual que los caracteres, los
bytes solo usan un byte de memoria pero al contrario de estos, solo pueden
almacenar números positivos.
int (entero)
Usa dos bytes de memoria para representar un número comprendido entre
-32.768 y 32.767; es el tipo de datos más común en Arduino. Si no sabe qué
tipo de datos usar, pruebe con int.
unsigned int (entero sin signo)
Igual que int, usa dos bytes pero el prefijo unsigned indica que no puede
guardar números negativos, por lo que su rango es de O a 65.535.
long (largo)
Duplica el tamaño de un entero y contiene números comprendidos entre
-2.147.483.648 a 2.147.483.647.
unsigned long (largo sin signo)
Versión sin signo de long, con un rango de O a 4.294.967.295.
float (decimal flotante)
Esta variable es bastante grande y puede contener valores de coma flotante,
una forma elegante de decir que podemos usarla para guardar números con
coma o punto decimal. Usará hasta cuatro bytes de nuestra preciosa RAM y
las funciones que los procesan usan también mucha memoria de código. Por
tanto, es mejor que use esta variable solo cuando la necesite.
double (flotante de 32 bits)
Número decimal de doble precisión, con un valor máximo de
1,7976931348623157 x 10308. iEnorme!
string (cadena de caracteres)
Conjunto de caracteres ASCII que se usa para guardar información de texto
(podríamos usar una cadena para enviar un mensaje a través de un puerto
serie o para mostrarla en una pantalla LCD). Para almacenamiento, usan solo
un byte por cada carácter de la cadena, más un carácter null para indicarle a
Arduino que es el final de la cadena. Los siguientes códigos son equivalentes:
char string1[] = "Arduino";
char string2[8]= "Arduino";
/ / 7 ca racte re s + 1 ca rácte r nul l
// Igual que el anterior
array (matriz )
Una lista de variables a la que se puede acceder a través de un índice. Se usan
para crear tablas de valores a las que se pueda acceder fácilmente. Por ejemplo,
si queremos guardar distintos niveles de brillo para usarlos para debilitar la
intensidad de un LED, podemos crear seis variables denominadas luz01,
luz02, etc. Mejor aún, podemos usar una sencilla matriz como la siguiente:
int luz[6] = {O, 20, 50, 75, 100};
En realidad, la palabra "matriz" no está en la declaración de variable: dicha
palabra queda sustituida por los corchetes [ ] y las llaves { }. Las matrices son
perfectas para realizar la misma operación con un grupo de datos, ya que puede
escribir la operación una sola vez y ejecutarla en cada variable de la matriz con
tan solo cambiar el índice, por ejemplo por medio de un bucle.
Ámbito o alcance de variables
En Arduino, las variables cuentan con una propiedad denominada ámbito o
alcance (“scope” en inglés). Las variables pueden ser locales o globales, en
función de dónde se declaren. Una variable global es la que se puede ver (y
utilizar) en todas las funciones del programa. Las variables locales solamente son
visibles para la función en la que se declaran. Cuando aumenta el tamaño y la
complejidad de un programa, las variables locales resultan muy útiles para
garantizar que todas las funciones tienen acceso a sus propias variables. De este
modo se evitan errores de programación si una función modifica accidentalmente
las variables utilizadas por otra. Las variables que deban usarse en varias
funciones pueden ser globales.
En el entorno de Arduino, toda variable declarada fuera de una función (como
por ejemplo setup(), loop() o sus propias funciones, es una variable global.
Toda variable declarada en función es local (y accesible) solamente desde
dicha función.
En ocasiones resulta muy útil declarar e inicializar una variable dentro de un
bucle for. De este modo se crea una variable a la que solamente se puede
acceder desde las llaves del bucle for. De hecho, siempre que una variable
se declara entre llaves, se considera local solamente en ese bloque de código.
Estructuras de control
Arduino incluye palabras clave para controlar el flujo lógico de nuestros sketch.
if ... else (Si….entonces…)
Esta estructura toma decisiones en nuestro programa. A i f le sigue una
pregunta especificada como expresión entre paréntesis. Si la expresión es
t rue, se ejecutará lo que sigue. Si es false, se ejecutará el bloque de código
que sigue a la cláusula else. La cláusula else es opcional. También es posible
implementar más operaciones de comparación mediante la forma else if.
Ejemplo#1:
if (val == 1) { //Si val vale 1 -> se prende el led
digitalWite(LED,HIGH);
}
Ejemplo#2:
if (val == 1) { //Si val vale 1 -> se prende el led
digitalWite(LED,HIGH);
}
else{ //Si val no vale 1 -> se apaga el led
digitalWite(LED,LOW);
}
Ejemplo#3:
if (val == 1) {
digitalWite(LED,HIGH);
}
else if (val==2){
digitalWite(LED,LOW);
}
else{
serial.print(“la variable val es distinta de 1 y de 2”);
}
for
Nos permite repetir un bloque de código una cantidad especificada de veces.
Ejemplo:
for (int i = 0; i < 10; i++) {
serial.print("hola");
}
//Se imprime 10 veces “hola”
switch case
Similar a if, la estructura switch case permite al programa tomar varias
direcciones, dependiendo del valor de una variable. Es muy útil para mantener
limpio nuestro código, ya que reemplaza a las largas listas de instrucciones if.
No olvide incluir la instrucción break al final de cada caso o Arduino ejecutará
las instrucciones de los demás casos hasta que llegue a una instrucción
break o al final de la instrucción switch.
Ejemplo:
switch (sensorValue) {
case 23:
digitalwrite(13,HIGH);
break;
case 46:
digitalwrite(12,HIGH);
break;
default: // si nada coincide, se ejecuta este código
digitalwrite(12,L0w);
digitalWrite(13,L0w);
}
while
De forma similar a if, la estructura while ejecuta un bloque de código siempre
y cuando una determinada condición sea true.
if ejecuta el bloque una sola vez, mientras que while continua ejecutando el
bloque mientras la condición siga siendo true.
Ejemplo:
// hacer parpadear a un LED cuando el sensor está por debajo de 512
sensorvalue = analogRead(1);
while (sensorvalue < 512) {
digital Wri te (13, HIGH) ;
delay(100);
digitalwrite(13,HIGH);
delay(100);
sensorvalue = analogRead(1);
}
do while
Igual que while, pero el código se ejecuta antes de evaluar la condición. Esta
estructura se usa cuando queremos que el código que se encuentra dentro del
bloque se ejecute al menos una vez antes de comprobar la condición.
Ejemplo:
do {
digitalWrite(13,HIGH);
delay(100);
digitalwtite(13,HIGH);
delay(100);
sensorvalue = analogRead(1);
} while (sensorValue < 512);
break
Este término nos permite salir de un bucle while o for aunque la condición
del bucle indique que debe continuar. También se usa para separar distintas
secciones de una instrucció n switch case .
Ejemplo:
// hacer parpadear un LED cuando el sensor está por debajo de 512
do {
// Dejar el bucle si se pulsa un botón
if (digitalRead(7)== HIGH)
break;
digitalwrite(13,HIGH);
delay(100);
digitalwrite(13,LOW);
delay(100);
sensorvalue = analogRead(1);
} while (sensorvalue < 512);
continue
Cuando se usa dentro de un bucle, nos permite omitir el resto del código y
forzar a que se vuelva a probar la condición.
Ejemplo:
for (light = 0; light < 255; light++){
// omitir intensidades entre 140 y 200
if ((x > 140) && (x < 200))
continue;
analogwrite(PWMpin, light);
delay(10);
}
continue es similar a break, pero break permite salir del bucle, mientras que
continue prosigue con la siguiente repetición del bucle.
return
Detiene la ejecución de una función y vuelve al punto desde el que se haya
invocado. También se puede usar para devolver un valor desde el interior de
una función. Por ejemplo, si tenemos una función denominada computeTem pe
ratu re O y queremos devolver el resultado a la parte de código que invoca la
función, escribiríamos lo siguiente:
int computeTemperature() {
int temperature — 0;
temperature = (analogRead(0) + 45) / 100;
return temperature;
}
Aritmética y formulas
Puede usar Arduino para realizar cálculos complejos usando una sintaxis
especial. Los signos de suma + y resta - funcionan como tales y la
multiplicación se representa con un asterisco (*) mientras que la división se
expresa con una barra inclinada (/). Existe un operador adicional denominado
modulo (%), que devuelve el resto de una división de enteros. Podemos usar
tantos niveles de paréntesis como sean necesarios para agrupar expresiones.
Al contrario de lo que aprendimos en el colegio, los corchetes y las llaves se
reservan para otros propósitos (índices de matrices y bloques,
respectivamente).
Ejemplo:
a = 2 + 2;
light = ((12 * sensorValue) - 5 ) / 2;
remainder = 3 % 2; // devuelve 1
Operadores de comparación
Cuando especificamos condiciones o pruebas para las instrucciones if, while
y for, podemos usar los siguientes operadores:
==
Igual a
!=
No igual a
<
Menor que
>
Mayor que
<=
Menor que o igual a
>=
Mayor que o igual a
Al realizar pruebas de igualdad, asegúrese de usar el operador de
comparación == y no el de asignación =, o su programa no se comportara de la
forma esperada.
Operadores booleanos
Estos operadores se usan cuando queremos combinar varias condiciones.
Por ejemplo, si queremos comprobar si un valor proveniente de un sensor se
encuentra comprendido entre 5 y 10, escribiremos lo siguiente:
if ((sensor => 5) && (sensor <=10))
Hay tres operadores:
“y”, representado por &&,
“o”, representado por ||
y “no”, representado por !
Operadares compuestos
Son operadores especiales utilizados para que el código sea más conciso para
algunas operaciones comunes, como el incremento de un valor.
Por ejemplo, para incrementar un valor en una unidad, escribiríamos lo siguiente:
value = value +1;
pero, con un operador compuesto, se convertiría en:
value++;
Puede optar por no utilizar estos operadores compuestos pero son tan habituales que, como principiante, le resultara complicado aprender de los ejemplos
si no los entiende.
Incremento y decremento (- - y ++)
Estos operadores incrementan o disminuyen un valor en una unidad. Tenga
cuidado, ya que si escribe variable++, incrementara variable en 1 y se
evaluará el equivalente a variable+1, y si escribe ++valor, se evaluará el
valor de variable y después se incrementará. Lo mismo se aplica a --.
Operadores “+ =” , “- =”, “*=” y “/=”
Son similares a ++ y --, pero le permiten incrementar y reducir por valores
distintos a 1, además de permitir operaciones de multiplicación y división. Las
siguientes expresiones son equivalentes:
a = a + 5;
es lo mismo que escribir
a += 5;
Funciones de entrada y salida
Arduino incluye funciones para controlar la entrada y salida. Ya hemos visto
algunos ejemplos en los programas del libro.
pinMode(pin, modo)
Reconfigura un pin digital para que se comporte como entrada o como salida.
Ejemplo:
pinMode(7,INPUT); // convierte el pin 7 en una entrada
Una causa habitual de salida fallida o de funcionamiento defectuoso es por
haberse olvidado de establecer pines en salidas por medio de pinMode().
Aunque se suela usar en setup(), pinMode() también se puede usar en un
bucle si es necesario cambiar el comportamiento del pin.
digitalWrite(pin, valor)
Convierte un pin digital en HIGH o LOW. Los pines se tienen que convertir
explícitamente en salida usando pinMode() antes de que digitalwrite() tenga
el efecto deseado.
Ejemplo:
digitalWrite(8,HIGH); // establece el pin digital 8 en 5V
Aunque HIGH o LOW suelen corresponderse a encendido o apagado,
respectivamente, depende de cómo se utilice el pin. Por ejemplo, un LED
conectado entre 5V y un pin se enciende cuando dicho pin es LOW y se apaga
cuando es HIGH.
int digitalRead(pin)
Lee el estado de un pin de entrada y devuelve HIGH si el pin detecta voltaje o
LOW si no se aplica voltaje alguno.
Ejemplo:
val= digitalRead(7); // lee el pin 7 en val
int analogRead(pin)
Lee el voltaje aplicado a un pin analógico de entrada y devuelve un número
comprendido entre O y 1023, que representa los voltajes comprendidos entre O
y 5V.
Ejemplo:
val = analogRead(0); // lee el pin analógico de entrada 0
analogWrite(pin, valor)
Cambia la velocidad PWM en uno de los pines marcados como PWM. pin solo
puede ser un pin que admita PWM, es decir, los pines 3, 5, 6, 9, 10 u 11 en la
placa Uno y los pines 3, 5, 6, 9, 10, 11 o 13 en el modelo Leonardo. valor
debe ser un número comprendido entre O y 255. Imagine que valor representa
la cantidad media de energía proporcionada por Arduino, siendo 0 el
equivalente a estar totalmente apagado y 255 a totalmente encendido.
Ejemplo:
analogWrite(9,128); // Reducir la luz del LED en el pin 9 en un 50%
Si valor es 0 se establece la salida en
establece en H IGH .
LOW,
mientras que si es 255 se
shift0ut(dataPin, clockPin, bitOrder, valor)
Envía datos a un registro de cambios, un dispositivo que se usa para ampliar
el número de entradas digitales. Este protocolo usa un pin para los datos
(dataPin) y otro para el reloj (clockPin). bitOrder indica el orden de los
bytes (del menos significativo al más significativo) y valor son los datos que
se van a enviar.
Ejemplo:
shiftOut(dataPin, clockPin, LSBFIRST, 255);
unsigned long pulseIn(pin, valor)
Mide la duración de un pulso entrante en una de las entradas digitales; algo
útil, por ejemplo, para leer sensores de infrarrojos o acelerómetros que envían
su valor como pulsos de duración variable.
Ejemplo:
time = pulsein(7,HIGH); // mide el tiempo que el siguiente pulso
// permanece activado
Funciones temporales
Arduino incluye funciones para medir el tiempo transcurrido y también para
pausar el sketch.
unsigned long millis()
Devuelve el tiempo transcurrido en milésimas de segundo desde que se inició
el sketch.
Ejemplo:
duration = millis()-lastTime; // calcula el tiempo transcurrido desde lastTime
delay(ms)
Pausa el programa durante la cantidad de milésimas de segundo especificada.
Ejemplo:
delay(500); // detiene el programa durante medio segundo
delayMicroseconds(us)
Pausa el programa durante una determinada cantidad de microsegundos.
Ejemplo:
d e la yM icr o se co nd s( 1 0 00 ) ; // espera durante una milésima d e s eg und o
Funciones matemáticas
Arduino incluye diversas funciones matemáticas y trigonométricas:
min(x, y)
Devuelve el menor de x e y.
Ejemplo:
val = min(10,20); // val es ahora 10
max(x, y)
Devuelve el mayor de x e y.
Ejemplo:
val = max(10,20); // val es ahora 20
abs(x)
Devuelve el valor absoluto de x, convirtiendo los números negativos en positivos.
Si x es 5 devolverá 5, pero si es -5, devolverá también 5.
Ejemplo:
val = abs(-5); // val es ahora 5
constrain(x, a, b)
Devuelve el valor de x, limitado entre a y b. Si x es menor que a, solo devolverá
a y si x es mayor que b, solo devolverá b.
Ejemplo:
val = constrain(analogRead(0), 0, 255); // rechaza los valores
// superiores a 255
map(value, fromLow, fromHigh, toLow, toHigh)
Asigna un valor dentro del rango fromLow y fromHigh al rango de toLow y
toHigh. Es muy útil para procesar valores de sensores analógicos.
Ejemplo:
val = map(analogRead(0),0,1023,100, 200);// asigna el valor analógico del
// pin 0 a un valor comprendido
// entre 100 y 200
double pow(base, exponente)
Devuelve el resultado de elevar un número (base) a un valor (exponente).
Ejemplo:
double x = pow(y, 32); // establece que se eleve x a la 32 potencia
double sqrt(x)
Devuelve la raíz cuadrada de un número.
Ejemplo:
double a = sqrt(1138); // aproximadamente 33,73425674438
double sin(rad)
Devuelve el seno de un ángulo especificado en radianes.
Ejemplo:
double sine = sin(2); // aproximadamente 0,90929737091
double cos(rad)
Devuelve el coseno de un ángulo especificado en radianes.
Ejemplo:
double cosine = cos(2); // aproximadamente -0,41614685058
double tan(rad)
Devuelve la tangente de un ángulo especificado en radianes.
Ejemplo:
double tangent = tan(2); // aproximadamente -2,18503975868
Funciones de números aleatorios
Si tenemos que generar números aleatorios, podemos usar el generador de
números seudoaleatorios de Arduino. Los números aleatorios son muy útiles
para que el comportamiento de un programa varíe cada vez que lo utilicemos.
randomSeed(seed)
Restablece el generador de números seudoaleatorios de Arduino. Aunque la
distribución de números devuelta por random() es básicamente aleatoria la
secuencia es predecible. Por tanto, debemos restablecer el generador a un valor
aleatorio. Si tenemos un pin analógico sin conectar, recogerá un ruido aleatorio
del entorno que le rodea (ondas de radio, rayos cósmicos, interferencias
electromagnéticas de teléfonos móviles y luces fluorescentes, etc), por lo que
será impredecible.
Ejemplo:
randomSeed(analogRead(5));
// generar número aleatorio usandz
// el ruido del pín 5
long random(max), long random(min, max)
Devuelven un valor entero long seudo-aleatorio comprendido entre min
y max. Si no se especifica min, el límite inferior es 0.
Ejemplo:
long randnum = random(0, 100); // un número comprendido entre 0 y 99
long randnum = random(11);
// un número comprendido entre 0 y 11
Comunicación en serie
Arduino puede comunicarse con otros dispositivos a través del puerto USB
usando un protocolo de comunicación en serie. A continuación le
mostramos las funciones en serie.
Serial.begin(velocidad)
Prepara al Arduino para empezar a enviar y recibir datos en serie .
Generalmente, con el monitor serie del IDE de Arduino se usan 9.600
baudios (bits por segundo), pero hay otras velocidades disponibles,
normalmente no superiores a 115.200 bps. La velocidad de baudios concreta
es irrelevante mientras que ambos lados acuerden utilizar la misma.
Ejemplo:
Serial.begin(9600);
Serial.print(datos), Serial.print(datos, codificación)
Envía datos al puerto serie. La codificación es opcional. Si no se
suministra los datos se tratan como texto plano, tanto como sea
posible.
Ejemplos (en el último se utiliza Seri al . wri te):
Serial.print(75);
// Imprime "75"
Serial.print(75, DEC); // Igual que en el caso anterior.
Serial.print(75, HEX); // "4B" (75 en hexadecimal)
Serial.print(75, OCT); // "113" (75 en octal)
Serial.print(75, BIN); // "1001011" (75 en binario)
Serial.println(datos), Serial.println(datos, codificación)
Igual que Serial.print() pero añade un retorno de carro y un salto de línea
(\r\n) como si hubiésemos escrito los datos y después pulsado Intro o Retorno.
Ejemplos:
Serial.println(75);
Serial.println(75, DEC);
Serial.println(75, HEX);
Serial.println(75, OCT);
Serial.println(75, BIN);
//
//
//
//
//
Imprime "75\r\n"
Igual que en el caso anterior.
"4B\r\n"
"113\r\n"
"1001011\r\n"
int Serial.available()
Devuelve los bytes sin leer disponibles en el puerto serie para su lectura a
través de la función read(). Después de tenerlos disponibles a través de
read(), serial.available() devuelve 0 hasta que llegan nuevos datos al puerto
serie.
Ejemplo:
int count = Serial.available();
int Serial.read()
Recupera un único byte de los datos de serie entrantes.
Ejemplo:
int data
Serial.read();
Serial.flush()
Como los datos pueden llegar a través del puerto serie más rápido de lo que
nuestro programa puede procesarlos, Arduino mantiene todos los datos
entrantes en un búfer. Si tenemos que limpiar el búfer y dejar que se llene de
datos nuevos, debemos usar la función flush() .
Ejemplo:
Serial.flush();
Descargar