Manual Maple
Manual Maple
Manual Maple
void setup()
{
sentencias;
}
void loop()
{
sentencias;
}
La función setup() es la parte que se encarga de recoger la configuración de los pines (E/S),
velocidad del puerto serie, declaración de variables entre otras cosas y la función loop() es la
que contienen el código que se ejecutará cíclicamente (de ahí el termino loop –bucle-), esta
función es la parte principal de los programas de Maple/Arduino y la que realiza prácticamente
todo el trabajo. Ambas funciones son necesarias para que el programa trabaje.
La función setup.
La función setup() se invoca una sola vez cuando el programa empieza. Se utiliza para inicializar
los modos de trabajo de los pins, o el puerto serie. Debe ser incluido en un programa aunque
no haya declaración que ejecutar.
void setup()
{
pinMode(pin, OUTPUT); // configura el 'pin' como salida
}
La función loop.
Después de llamar a setup(), la función loop() hace precisamente lo que sugiere su nombre, se
ejecuta de forma cíclica, lo que posibilita que el programa este respondiendo continuamente
ante los eventos que se produzcan en la tarjeta
void loop()
{
digitalWrite(pin, HIGH); // pone en uno (on, 5v) el ´pin´
delay(1000); // espera un segundo (1000 ms)
digitalWrite(pin, LOW); // pone en cero (off, 0v.) el ´pin´
delay(1000);
}
Funciones de usuario.
Ya sabemos que una función es un bloque de código que tiene un nombre y un conjunto de
sentencias que son ejecutados cuando se llama a la función. Las funciones de usuario pueden
ser escritas para realizar tareas repetitivas y así disminuir el número de líneas de código en el
programa lo que hará que nuestro programa ocupe menos memoria y asi poder crear
programas de mayor complejidad.
Las funciones se declaran asociadas a un tipo de valor “type”. Este valor será el que devolverá
la función, por ejemplo 'int' se utilizará cuando la función devuelva un dato numérico de tipo
entero. Si la función no devuelve ningún valor entonces se colocará delante la palabra “void”,
que significa “función vacía”. Después de declarar el tipo de dato que devuelve la función se
debe escribir el nombre de la función y entre paréntesis se escribirán, si es necesario, los
parámetros que se deben pasar a la función para que se ejecute.
type nombreFunción(parámetros)
{
sentencias;
}
La función siguiente devuelve un número entero, delayVal() se utiliza para poner un valor de
retraso en un programa que lee una variable analógica de un potenciómetro conectado a una
entrada de Arduino. Al principio se declara como una variable local, ´v´ recoge el valor leído del
potenciómetro que estará comprendido entre 0 y 1023, luego se divide el valor por 4 para
ajustarlo a un margen comprendido entre 0 y 255, finalmente se devuelve el valor ´v´ y se
retornaría al programa principal. Esta función cuando se ejecuta devuelve el valor de tipo
entero ´v´
int delayVal()
{
int v; // crea una variable temporal 'v'
v= analogRead(pot); // lee el valor del potenciómetro
v /= 4; // convierte 0-1023 a 0-255
return v; // devuelve el valor final
}
Las llaves sirven para definir el principio y el final de un bloque de instrucciones. Se utilizan
para los bloques de programación setup(), loop(), if.., etc.
type funcion()
{
sentencias;
}
Una llave de apertura “{“siempre debe ir seguida de una llave de cierre “}”, si no es así el
programa dará errores.
El punto y coma.
Bloques de comentarios.
Los bloques de comentarios, o multi-línea de comentarios, son áreas de texto ignorados por el
programa que se utilizan para las descripciones del código o comentarios que ayudan a
comprender el programa. Comienzan con / * y terminan con * / y pueden abarcar varias líneas.
Debido a que los comentarios son ignorados por el programa y no ocupan espacio en la
memoria de Arduino pueden ser utilizados con generosidad y también pueden utilizarse para
"comentar" bloques de código con el propósito de anotar informaciones para depuración.
Líneas de comentarios.
Una línea de comentario empieza con / / y terminan con la siguiente línea de código. Al igual
que los comentarios de bloque, los de línea son ignoradas por el programa y no ocupan
espacio en la memoria.
// Esto es un comentario.
Una línea de comentario se utiliza a menudo después de una instrucción, para proporcionar
más información acerca de lo que hace esta o para recordarla más adelante.
#include y #define
#define permite al programador dar un nombre a un valor constante antes de que el programa
sea compilado. El compilador reemplazara las referencias a estas constantes con el valor
definido en el momento de compilación.
Esto puede tener algunos efectos secundarios indeseados. En general, se prefiere el uso de
const para definir constantes.
#define MAPLE_LED_PIN 13
Este es un ejemplo (del Tutorial Arduino LiquidCrystal) que incluye una librería para el control
de pantallas LCD.
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("hello, world!");
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
}
Variables.
Una variable es una manera de nombrar y almacenar un valor numérico para su uso posterior
por el programa. Como su nombre indica, las variables son números que se pueden variar
continuamente en contra de lo que ocurre con las constantes cuyo valor nunca cambia. Una
variable debe ser declarada y, opcionalmente, asignarle un valor. El siguiente código de
ejemplo declara una variable llamada x y luego le asigna el valor obtenido en la entrada
analógica del PIN2:
'x' es la variable en sí. La primera línea declara que será de tipo entero “int”. La segunda línea
fija a la variable el valor correspondiente a la entrada analógica PIN2. Esto hace que el valor de
PIN2 sea accesible en otras partes del código.
Una vez que una variable ha sido asignada, o re-asignada, usted puede probar su valor para ver
si cumple ciertas condiciones (instrucciones if..), o puede utilizar directamente su valor. Como
ejemplo ilustrativo veamos tres operaciones útiles con variables: el siguiente código prueba si
la variable “x” es inferior a 100, si es cierto se asigna el valor 100 a “x” y, a continuación,
establece un retardo (delay) utilizando como valor “x” que ahora será como mínimo de valor
100:
Declaración de variables.
Todas las variables tienen que declararse antes de que puedan ser utilizadas. Para declarar una
variable se comienza por definir su tipo como int (entero), long (largo), float (coma flotante),
etc, asignándoles siempre un nombre, y, opcionalmente, un valor inicial. Esto sólo debe
hacerse una vez en un programa, pero el valor se puede cambiar en cualquier momento
usando aritmética y reasignaciones diversas.
El siguiente ejemplo declara la variable entradaVariable como una variable de tipo entero
“int”, y asignándole un valor inicial igual a cero. Esto se llama una asignación.
int entradaVariable = 0;
Una variable puede ser declarada en una serie de lugares del programa y en función del lugar
en donde se lleve a cabo la definición esto determinará en que partes del programa se podrá
hacer uso de ella.
Una variable puede ser declarada al inicio del programa antes de la parte de configuración
setup(), a nivel local dentro de las funciones, y, a veces, dentro de un bloque, como para los
bucles del tipo if.. for.., etc. En función del lugar de declaración de la variable así se
determinara el ámbito de aplicación, o la capacidad de ciertas partes de un programa para
hacer uso de ella.
Una variable global es aquella que puede ser vista y utilizada por cualquier función y
estamento de un programa. Esta variable se declara al comienzo del programa, antes de
setup().
Una variable local es aquella que se define dentro de una función o como parte de un bucle.
Sólo es visible y sólo puede utilizarse dentro de la función en la que se declaró.
Por lo tanto, es posible tener dos o más variables del mismo nombre en diferentes partes del
mismo programa que pueden contener valores diferentes. La garantía de que sólo una función
tiene acceso a sus variables dentro del programa simplifica y reduce el potencial de errores de
programación.
El siguiente ejemplo muestra cómo declarar a unos tipos diferentes de variables y la visibilidad
de cada variable:
Inicialización de variables.
Las variables se pueden inicializar (le asigna un valor inicial) que hayan sido declarados o
no. Siempre es buena práctica de programación sin embargo para comprobar el doble que una
variable tiene datos válidos en ella antes de que se utiliza. Utilizar una variable antes de darle
un valor es una fuente común de errores.
Tipos de Datos.
void setup () {
// ...
}
void loop () {
// ...
}
• boolean: El formato del tipo “lógico” solo puede ser verdadero o falso.
• double: El formato de dato del tipo “punto flotante” “double” se aplica a los números
con decimales con un rango comprendido de -1,79769 +308 a 1,79769 +308. La
variable doublé presenta más precisión 8bytes, que le tipo float que es solo de 4bytes.
• unsigned char: Las variables de tipo char almacenan un valor de carácter de 1 byte (o
entero con valor entre 0 y 255).
• byte: Byte almacena un valor numérico de 8 bits sin decimales. Tienen un rango entre
0 y 255.
• Int, long: Se refiere a números enteros (tipo 32 bits) sin decimales que se encuentran
dentro del rango -2147483648 a 2147483647.
• unsigned Int, unsigned long: Se refiere a números enteros (tipo 32 bits) sin decimales
que se encuentran dentro del rango 0 a 4,294,967,295.
• long long: Se refiere a números enteros (tipo 64 bits) sin decimales que se encuentran
dentro del rango -9.2 +18 a 9.2 +18.
• unsigned long long: Se refiere a números enteros (tipo 64 bits) sin decimales que se
encuentran dentro del rango 0 a 1,8 +19.
• float: El formato de dato del tipo “punto flotante” “float” se aplica a los números con
decimales. Los números de punto flotante tienen una mayor resolución que los de 32
bits con un rango comprendido 3.4028235E +38 a +38-3.4028235E.
float x = 3.14; // declara 'x' como tipo float
Nota: Los números de punto flotante no son exactos, y pueden producir resultados
extraños en las comparaciones. Los cálculos matemáticos de punto flotante son
también mucho más lentos que los del tipo de números enteros, por lo que debe
evitarse su uso si es posible.
• array: Un array es un conjunto de valores a los que se accede con un número índice.
Cualquier valor puede ser recogido haciendo uso del nombre de la matriz y el número
del índice. El primer valor de la matriz es el que está indicado con el índice 0, es decir
el primer valor del conjunto es el de la posición 0. Un array tiene que ser declarado y
opcionalmente asignados valores a cada posición antes de ser utilizado int miArray[] =
{valor0, valor1, valor2...} .
Del mismo modo es posible declarar una matriz indicando el tipo de datos y el tamaño
y posteriormente, asignar valores a una posición especifica:
Las matrices se utilizan a menudo para sentencias de tipo bucle, en los que la variable
de incremento del contador del bucle se utiliza como índice o puntero del array. El
siguiente ejemplo usa una matriz para el parpadeo de un LED.
Utilizando un bucle tipo for, el contador comienza en cero 0 y escribe el valor que
figura en la posición de índice 0 en la serie que hemos escrito dentro del array
parpadeo[], en este caso 180, que se envía a la salida analógica tipo PWM configurada
en el PIN10, se hace una pausa de 200 ms y a continuación se pasa al siguiente valor
que asigna el índice “i”.
parpadeo[]
delay(200); // espera 200ms
}
}
• Strings: Las cadenas de texto en el Maple se puede representar con un array de tipo
char, las siguientes son formas validas de estos arrays.
char str1[15];
char str2[6] = {'m', 'a', 'p', 'l', 'e'};
char str3[6] = {'m', 'a', 'p', 'l', 'e', '\0'};
char str4[ ] = "maple";
char str5[6] = "maple";
char str6[15] = "maple";
Como puedes ver, hay varios métodos disponibles para declarar e inicializar cadenas
de texto:
Declarar una matriz de caracteres sin inicializarla, str1.
Declarar una matriz de caracteres (con un carácter extra) y el compilador agregará el
carácter nulo requerido, str2.
Agregue explícitamente el carácter nulo ("\ 0”), str3.
Inicializar con una constante de cadena entre comillas ("...”), el compilador tamaño de
la matriz para adaptarse a la constante de cadena y un carácter nulo de terminación
(STR4).
Inicializar la matriz con un tamaño explícito y constante de cadena (str5).
Inicializar la matriz, dejando un espacio extra para una cadena más grande (str6).
Terminación NULL
En general, las cadenas se terminan con un carácter nulo ( ASCII código 0). Esto
permite que las funciones (como SerialUSB.print () ) sepan dónde está el final de una
cadena. De lo contrario, continuará la lectura de bytes siguientes de la memoria que
no son en realidad parte de la cadena.
Esto significa que la cadena tiene que tener espacio para un carácter más que el
texto que desea introducir. Es por eso que str2 , y str5 tienen que ser de seis
caracteres, a pesar de "maple" es sólo de cinco - la última posición se rellena
automáticamente con un carácter nulo. En STR4 será automáticamente añadido al
tamaño de seis caracteres, uno para la terminación null. En el caso de str3 , hemos
incluidoexplícitamente el carácter nulo (escrito '\ 0' ).
Tenga en cuenta que es posible tener una cadena sin un carácter nulo final (por
ejemplo, si ha especificado la duración de str2 en cinco en lugar de seis). Si usted nota
algo de manera extraña (errores durante el uso de cadenas), este podría ser el
problema.
Matrices de cadenas
En el código de abajo, el asterisco después del tipo de datos char, char * indica que
se trata de un conjunto de "punteros". Todos los nombres de matrices son
realmente punteros, por lo que este está obligado a hacer una matriz de
matrices. Los punteros son una de las partes más complejas de C para los
principiantes, pero no es necesario entender los punteros en detalle para
utilizarlos de manera efectiva en este caso:
void loop() {
for(int i=0; i <6; i++) {
SerialUSB.println(MyStrings[i]);
delay( 500 );
}
}
Una vez que hemos definido este tipo, se pueden crear variables de tipo weather , de
la misma manera que lo haría con un int :
Los operadores aritméticos que se incluyen en el entorno de programación son suma, resta,
multiplicación y división. Estos devuelven la suma, diferencia, producto, cociente, asignación y
modulo (respectivamente).
y = y + 3;
x = x - 7;
i = j * 6;
r = r / 5;
h= 7;
d= 5 % 2;
La operaciones se efectúa teniendo en cuanta el tipo de datos que hemos definido para los
operandos (int, dbl, float, etc..), por lo que, por ejemplo, si definimos 9 y 4 como enteros “int”,
9 / 4 devuelve de resultado 2 en lugar de 2,25 ya que el 9 y 4 se valores de tipo entero “int”
(enteros) y no se reconocen los decimales con este tipo de datos.
Esto también significa que la operación puede sufrir un desbordamiento si el resultado es más
grande que lo que puede ser almacenada en el tipo de datos. Recordemos el alcance de los
tipos de datos numéricos que ya hemos explicado anteriormente. Si los operandos son de
diferentes tipos, para el cálculo se utilizará el tipo más grande de los operandos en juego. Por
ejemplo, si uno de los números (operandos) es del tipo float y otra de tipo integer, para el
cálculo se utilizará el método de float es decir el método de coma flotante.
Elija el tamaño de las variables de tal manera que sea lo suficientemente grande como para
que los resultados sean lo precisos que usted desea. Para las operaciones que requieran
decimales utilice variables tipo float, pero sea consciente de que las operaciones con este tipo
de variables son más lentas a la hora de realizarse el cómputo.
Asignaciones compuestas.
Las asignaciones compuestas combinan una operación aritmética con una variable asignada.
Estas son comúnmente utilizadas en los bucles tal como se describe más adelante. Estas
asignaciones compuestas pueden ser:
Nota: Por ejemplo, x * = 3 hace que x se convierta en el triple del antiguo valor x y por lo tanto
x es reasignada al nuevo valor.
Operadores de comparación.
Las comparaciones de una variable o constante con otra se utilizan con frecuencia en las
estructuras condicionales del tipo if.. para testear si una condición es verdadera. En los
ejemplos que siguen en las próximas páginas se verá su utilización práctica usando los
siguientes tipo de condicionales:
x == y // x es igual a y
x != y // x no es igual a y
x<y // x es menor que y
x>y // x es mayor que y
x <= y // x es menor o igual que y
x >= y // x es mayor o igual que y
Operadores lógicos.
Los operadores lógicos son usualmente una forma de comparar dos expresiones y devolver un
VERDADERO o FALSO dependiendo del operador. Existen tres operadores lógicos, AND (&&),
OR (||) y NOT (!), que a menudo se utilizan en sentencias de tipo if..:
Logical AND:
if (x > 0 && x < 5) // cierto sólo si las dos expresiones son ciertas
Logical OR:
if (x > 0 || y > 0) // cierto si una cualquiera de las expresiones es cierta
Logical NOT:
if (!x > 0) // cierto solo si la expresión es falsa
Constantes.
TRUE/FALSE.
Estas son constantes booleanas que definen los niveles HIGH (alto) y LOW (bajo) cuando estos
se refieren al estado de las salidas digitales. FALSE se asocia con 0 (cero), mientras que TRUE se
asocia con 1, pero TRUE también puede ser cualquier otra cosa excepto cero. Por lo tanto, en
sentido booleano, -1, 2 y -200 son todos también se define como TRUE. (esto es importante
tenerlo en cuenta).
if (b == TRUE);
{
ejecutar las instrucciones;
}
HIGH/LOW.
Estas constantes definen los niveles de salida altos o bajos y se utilizan para la lectura o la
escritura digital para las patillas. ALTO se define como en la lógica de nivel 1, ON, ó 5 voltios,
mientras que BAJO es lógica nivel 0, OFF, o 0 voltios.
INPUT/OUTPUT.
Estas constantes son utilizadas para definir, al comienzo del programa, el modo de
funcionamiento de los pines mediante la instrucción pinMode de tal manera que el pin puede
ser una entrada INPUT o una salida OUTPUT.
Estructuras.
If.
if (unaVariable ?? valor)
{
ejecutaInstrucciones;
}
En el ejemplo anterior se compara una variable con un valor, el cual puede ser una variable o
constante. Si la comparación, o la condición entre paréntesis se cumple (es cierta), las
declaraciones dentro de los corchetes se ejecutan. Si no es así, el programa salta sobre ellas y
sigue.
Nota: Tenga en cuenta el uso especial del símbolo '=', poner dentro de if (x = 10), podría
parecer que es válido pero sin embargo no lo es ya que esa expresión asigna el valor 10 a la
variable x, por eso dentro de la estructura if se utilizaría X==10 que en este caso lo que hace el
programa es comprobar si el valor de x es 10.. Ambas cosas son distintas por lo tanto dentro
de las estructuras if, cuando se pregunte por un valor se debe poner el signo doble de igual
“==”
If…else.
if… else viene a ser un estructura que se ejecuta en respuesta a la idea “si esto no se cumple
haz esto otro”. Por ejemplo, si se desea probar una entrada digital, y hacer una cosa si la
entrada fue alto o hacer otra cosa si la entrada es baja, usted escribiría que de esta manera:
Else puede ir precedido de otra condición de manera que se pueden establecer varias
estructuras condicionales de tipo unas dentro de las otras (anidamiento) de forma que sean
mutuamente excluyentes pudiéndose ejecutar a la vez. Es incluso posible tener un número
ilimitado de estos condicionales. Recuerde sin embargo qué sólo un conjunto de declaraciones
se llevará a cabo dependiendo de la condición probada:
For.
La declaración for se usa para repetir un bloque de sentencias encerradas entre llaves un
número determinado de veces. Cada vez que se ejecutan las instrucciones del bucle se vuelve
a testear la condición. La declaración for tiene tres partes separadas por (;) vemos el ejemplo
de su sintaxis:
La inicialización de una variable local se produce una sola vez y la condición se testea cada vez
que se termina la ejecución de las instrucciones dentro del bucle. Si la condición sigue
cumpliéndose, las instrucciones del bucle se vuelven a ejecutar. Cuando la condición no se
cumple, el bucle termina.
Nota: Cualquiera de los tres elementos de cabecera puede omitirse, aunque el punto y coma
es obligatorio.
While.
Un bucle del tipo while es un bucle de ejecución continua mientras se cumpla la expresión
colocada entre paréntesis en la cabecera del bucle. La variable de prueba tendrá que cambiar
para salir del bucle. La situación podrá cambiar a expensas de una expresión dentro el código
del bucle o también por el cambio de un valor en una entrada de un sensor.
Do..while.
El bucle do while funciona de la misma manera que el bucle while, con la salvedad de
que la condición se prueba al final del bucle, por lo que el bucle siempre se ejecutará al
menos una vez.
do{
Instrucciones;
}while (unaVariable ?? valor);
El siguiente ejemplo asigna el valor leído leeSensor() a la variable 'x', espera 50 milisegundos, y
luego continua mientras que el valor de la 'x' sea inferior a 100:
do{
x = leeSensor();
delay(50);
} while (x < 100);
Switch / case.
switch (var) {
case 1:
doThing1();
break;
case 2:
doThing2();
break;
default:
doSomethingElse();
}
Break.
La sentencia break se usa para forzar un salto hacia el final de un ciclo controlado por for o
por while.
En el siguiente fragmento de código la sentencia break cierra el ciclo for cuando la variable ( i )
es igual a 5.
Continue.
La sentencia continue se usa para ignorar una iteración dentro de un ciclo controlado por for o
por while.
Los dos ejemplos anteriores se presentan en seguida, salvo que en lugar de for se hace uso de
while.
Nota: no deje de observar que la construcción del ciclo while para el caso de la sentencia
continue es diferente, esto para garantizar que el ciclo no vaya a caer en una iteración infinita.
Break Continue
Goto.
Goto significa ir a y en c++ nos sirve para que mandar al compilador a alguna parte
arbitrariamente, es decir nada más porque sí. No se suele usar mucho pero nos puede sacar de
algunos apuros.
Primero tenemos que definir un marcador, inmediatamente después poner dos puntos (:).
Cuando sea necesario escribiremos goto seguido de nuestro identificador y punto y como (;).
void loop() {
readpin:
int x = analogRead(some_pin);
if (x < 2000) {
goto startdelay;
}
SerialUSB.println(x); // for debugging
startdelay:
delay(x);
// ... more code ...
}
Return.