Arrays y Arduino
Arrays y Arduino
com
Array
Índices
o Indexación base cero
Creando y declarando un arreglo
Accediendo a un array
Asignar un valor a un array
Acceder a un valor de un array
Array y bucles FOR
Referencias
Array
Un array es una colección de variables que tienen todas el mismo y único nombre, pero
que pueden distinguirse entre sí por un número de índice; es decir en vez de tener varias
variables con el mismo nombre por ejemplo valor1, valor2, valorN, para almacenar
números, podemos crear una sola variable de tipo int valor[], como veremos más
adelante.[1]
Las matrices sirven para ganar claridad y simplicidad en el código, además de facilitar la
programación.
Al utilizar matrices debemos tener presente que para consultar o asignar valores, debemos
comenzar indexando el primer elemento por el número cero, que será el primer elemento
del arreglo.
Índices
Todo vector se compone de un determinado número de elementos. Cada elemento es referenciado
por la posición que ocupa dentro del vector. Dichas posiciones son llamadas índice y siempre son
correlativos.[2]
En este modo el primer elemento del vector será la componente cero (0) del mismo, es
decir, tendrá el índice 0. En consecuencia, si el vector tiene 'n' componentes la última
tendrá como índice el valor n-1. El lenguaje C es un ejemplo típico que utiliza este modo de
indexación.
Todos los métodos a continuación son formas válidas de crear o declarar una arreglo[3].
Podemos declarar un array sin inicializarla, pero hay que tener en cuenta que arduino
exige que le asignemos un tamaño.
int myInts[6];
En myPins declaramos un arreglo sin elegir explícitamente un tamaño. El compilador
cuenta los elementos y crea el array del tamaño apropiado.
Accediendo a un array
mySensVals[0] == 2
mySensVals[1] == 4
También significa que en un arreglo con diez elementos, el índice nueve es el último
elemento. Por lo tanto:
Por este motivo, debe tener cuidado al acceder a las matrices. Acceder más allá del final
de un arreglo (usando un número de índice mayor que el tamaño del arreglo declarado -1)
se lee de la memoria que se usa para otros fines. Es probable que la lectura de estas
ubicaciones no haga mucho, excepto que se produzcan datos no válidos. Escribir en
ubicaciones de memoria aleatorias es definitivamente una mala idea y, a menudo, puede
llevar a resultados infelices, como bloqueos o mal funcionamiento del programa. Esto
también puede ser un error difícil de localizar.
Para asignar valores lo podemos realizar de la siguiente forma, hay que tener en cuenta
que la variable ya tiene que estar creada e inicializada con un tamaño determinado, hasta
este punto no interesa como se ha realizado.
mySensVals[0] = 10; //en la posición 0 o en primer lugar del array asignamos el valor 10
¿Tiene un entero límite de tamaño? La respuesta es afirmativa. Los enteros int en Arduino
utilizan 16 bits por lo que el máximo sería 2 elevado a 16 = 65.536, Pero como el tipo int
usa signo, su valor está comprendido entre -32.768 y +32.767.
De hecho en Arduino C++ hay varios tipos, de distintos tamaños para manejar enteros:
Todos estos tipos representan enteros con y sin signo y se pueden utilizar para trabajar
con números realmente grandes pero no sin límite.
Cuando nos salimos del tamaño máximo se le llama desbordamiento (overflow) y C++
ignora olímpicamente el asunto, dando lugar a problemas difíciles de detectar si uno no
anda con cuidado.
int i = 32767 ;
Serial.println ( i+1);
Enseguida veras que si i=32767 y le incrementamos en 1, para C++ el resultado es
negativo. Eso es porque sencillamente no controla el desbordamiento. También es
ilustrativo probar el resultado de
int i = 32767 ;
Serial.println (2* i + 1);
Que según Arduino es -1.
Esto no es un error, sino que se decidió así en su día y C++ no controla los
desbordamientos, así que mucho cuidado, porque este tipo de errores pueden ser muy
complicados de detectar.
Funciones
Supongamos que queremos crear un programa que nos devuelva true o false según que
el número que le pasamos sea primo o no y a la que podamos llamar varias veces sin
copiar el código una y otra vez. La llamaremos primo() y queremos utilizarla de la siguiente
manera: Si el numero n que le pasamos es primo nos tiene que devolver true y en caso
contrario que devuelva false, o sea, queremos que nos devuelva un valor bool.
En realidad, ya hemos utilizado varias funciones que Arduino trae predefinidas como el
Serial.print() o abs() , o Serial.available() y se las reconoce por esa apertura y cierre de
paréntesis.
C++ nos ofrece todas las herramientas para crear nuestras propias funciones y es algo
muy útil porque nos ayuda a organizar un problema general en trozos o funciones más
pequeñas y más fáciles de manejar.
Para definir una función así, tenemos que declararla primero y describirle a C++ que hacer:
Si una función no va a devolver ningún valor, sino que simplemente realiza su trabajo y
finaliza sin mas, entonces hay que declararla como void (vacía). Ya cononocemos dos
funciones así : setup() y loop()
Para saber si un número es o no primo basta con dividirlo por todos los números
positivos menores que él y mayores que 1. En el ejemplo dividimos el número n
empezando en 2 y finalizando en n-1.
Para usar primo hay que pasarle un entero. Recordad que al definir la función dijimos bool
primo (int n) donde n representa el valor que queremos probar.
void loop(){
int x = 427 ; // El número a probar
bool p = primo(x);
if(p)
Serial.print(String(x)+" Es primo.");
else
Serial.print(String(x)+" No es primo.");
}
if (primo(x) )
if ( contador++ % 8 == 0)
Serial.println( String(x)+»,» ) ;
else
Serial.print( String(x) +»,»+ ‘\t’) ;
Ahora el programa formatea la salida de una forma un poco más presentable y cómoda de
leer.
Para conseguirlo, hemos añadido una coma y un tabulador a cada número excepto a uno
de cada 8 que añadimos un intro. También tenemos una línea que conviene comentar:
if ( contador++ % 8 == 0)
Cuando a una variable se le añaden dos símbolos más (+) al nombre, significa que primero
se use su valor actual en la instrucción en curso, en este caso en el if, y después se
incremente en 1 su valor.
Si hubiéramos escrito:
if ( ++contador % 8 == 0)
Querría decir que queremos incrementar su valor antes de utilizarlo. Esta notación es muy
habitual en C++ y conviene reconocerla. También podemos usar contador– y –contador
para decrementar.
El tipo entero
Este sería un buen momento para preguntarnos hasta donde podría crecer la variable
máximo en el programa anterior. Le asignamos un valor de 1024, pero ¿Tiene un entero
límite de tamaño?
La respuesta es afirmativa. Los enteros int en Arduino C++ utilizan 16 bits por lo que el
máximo seria en principio 2 elevado a 16 = 65.536, Pero como el tipo int usa signo, su
valor está comprendido entre -32.768 y +32.767.
De hecho en Arduino C++ hay varios tipos, de distintos tamaños para manejar enteros:
Todos estos tipos representan enteros con y sin signo y se pueden utilizar para trabajar
con números realmente grandes pero no sin límite.
De hecho C++ tiene la fea costumbre de esperar que nosotros llevemos el cuidado de no
pasarnos metiendo un valor que no cabe en una variable. Cuando esto ocurre se le llama
desbordamiento (overflow) y C++ ignora olímpicamente el asunto, dando lugar a
problemas difíciles de detectar si uno no anda con cuidado.
Cuando se declara una función se debe especificar que valor va a devolver. Así:
Una función puede devolver cualquier tipo posible en C++, pero sólo puede devolver un
único valor mediante la instrucción return().
Con la función Primo() que vimos, a medida que el tamaño del número a probar crece, el
tiempo que tarda en determinar si es primo también, ya que dividimos por todos los
números que le preceden.
Una manera más eficaz de calcular si un número es primo, es dividirlo solo por los
números primos menores que él. Pero para esto necesitaríamos un modo de archivar estos
primos.
Podríamos ejecutar primero el programa anterior y hallar los N primeros números primos, y
si dispusiéramos de algún medio para guardarlos, tendríamos un sistema más eficaz para
decidir si un número es o no primo.
Empecemos con un array de una sola dimensión. Para definirlo podemos optar por dos
maneras:
En el primer caso definimos un array de enteros, de una sola dimensión con 5 elementos,
sin asignar valores de momento.
En el segundo caso asignamos un array de enteros a los valores que le pasamos entre
llaves, sin especificar cuantos, porque le dejamos a C++ la tarea de contarlos. Decimos
que definimos el array por enumeración.
Para asignar o leer los valores de un array se utiliza un índice entre corchetes. Veamos
este programa:
void setup(){
Serial.begin(9600) ;
void loop(){
Uno esperaría que C++ generase un error, ya que definimos un array de 5 elementos y
hacemos referencia a 100, pero no. Nuevamente C++ nos sorprende devolviendo
correctamente los 5 primeros valores y luego sigue leyendo posiciones de memoria
consecutivas tan tranquilo, como si tuvieran sentido.
C++ espera que seamos nosotros quienes controlemos esto, así que mucho cuidado
int tablero[ 8, 8 ] ;
Imaginad que tablero representa las posiciones de una partida de ajedrez y cada valor que
contiene esa posición corresponde a una pieza que se encuentra en esa casilla.
La función getLine()
Aunque ya comentamos que podemos usar una función parseInt() incluida en Arduino para
recoger un valor del puerto serie, tiene el inconveniente de que si no recibe una entrada,
salta al cabo de un tiempo y devuelve 0, por lo que tendríamos que controlar el valor
devuelto para que no se repitiese continuamente.
Por eso vamos a escribir una función de uso general que nos permita recoger una cadena
de texto de la puerta serie sin que salga hasta que reciba un String que vamos a hacer
finalice en intro.
String getLine(){
String s = «» ;
if (Serial.available()){
char c = Serial.read();
while ( c != ‘\n’) {
s=s+c;
delay(25) ;
c = Serial.read();
return(s) ;
Definimos getline() de tipo String, porque queremos que nos devuelva un texto.
Comprobamos que hay algo disponible en la puerta serie, y en caso afirmativo construimos
un String S añadiéndole cada uno de los caracteres que leemos del puerto serie, hasta que
encontremos un intro.
http://www.iescamp.es/miarduino