Las funciones en Arduino, las variables y el perreo
Bueno bueno bueno, ¿Cómo estas por ahí? Yo (Aunque no me lo preguntes) bien porque he escrito un programa que me ha quedado bastante aseado y legible.
La verdad es que siempre he pensado que eso de la legibilidad era una cosa inútil, pero es cierto que al mirar tu código unos años después se te pierden muchas cosas y no eres capaz de entender qué pasaba allí. Y tampoco es plan de comentar cada línea del código porque sino estás igual de perdido.
Esto de los comentarios es un arte pero también lo es lo de partir el programa. Sé que nunca hemos hablado de partir el programa pero es algo que se hace, sobretodo al hacer cosas de forma repetitiva. Y a eso vamos hoy… A tomar prestada la sierra del vecino y a cortar nuestros extensos programas…
Aquí, utilizando mi primera función
Una forma (o la forma) en la que se pueden dividir los programas es mediante funciones. Una función es una parte de código que hace una cosa concreta. Es decir, una función es una parte de código que ‘cumple su función’ (Qué humor a estas horas de la tarde…)
Las funciones pueden hacer algo como mostrar por el Serial una frase o incluso modificar datos. Vamos a ir viendo una serie de ejemplos para no agobiarnos. Lo primero es la función sencilla como es esta de imprimir por pantalla alguna información:
void muestraporpantalla(){ Serial.println("Acabo de ver un elefante volando"); delay(1000); }
Como ves, lo primero que aparece es la palabara void. La primera palabra de la definición de una función siempre es el tipo de variable que devuelve. Estarás acostumbrado a ver int, float… ¿Pero void? ¿Eso qué es? Void significa que la función no devuelve nada, es el vacío.
Esto es porque la función va a mostrar algo por pantalla pero no va a devolver una variable de ningún tipo. No se devuelven datos. Luego tenemos el nombre de la función (muestraporpantalla) y unos paréntesis. Como ves, la función está entre llaves, como lo están la función setup y loop.
Sí, setup y loop, que aparecen en todos los programas de Arduino, son funciones pero son un poco especiales ya que ya está preparado para que el setup se haga al inicio y el loop sea un bucle infinito que se esté ejecutando todo el tiempo.
Información básica sobre Proteción de datos
Responsable ➥ Sergio Luján Cuenca
Finalidad ➥ Gestionar el envío de correos electrónicos con artículos, noticias y publicidad. Todo relacionado con los temas de rufianenlared.com
Legitimación ➥ Consentimiento del interesado
Destinatarios ➥ Estos datos se comunicarán a MailRelay para gestionar el envío de los correos electrónicos
Derechos ➥ Acceder, rectificar y suprimir los datos, así como otros derechos, como se explica en la política de privacidad
Plazo de conservación de los datos ➥ Hasta que se solicite la supresión por parte del interesado
Información adicional ➥ Puedes encontrarla en la política de privacidad y el aviso legal
Utilizando el return en tus funciones
Tal y como he dicho, la función con la palabra void significa que no devuelve nada. ¿Qué significaría que devolviese algo? Por ejemplo una función que nos devolviese cuanto es 2+2 (Una función muy útil eh!). Para ello, al llamarla nos dará ese valor, el cuál deberemos guardar nosotros al llamarlo:
int damecuatro(){ int suma = 0; suma = 2+2; return suma; }
Como ves he utilizado algo nuevo ahí, la palabra return. Esta palabra lo que hace es devolver ese valor (Que puede ser una variable o directamente un número) y volver al programa que llamó a la función. Es decir, lo que haya debajo de la palabra return no se ejecutará y se volverá al programa principal. Esto te puede servir si detectas un fallo al leer un archivo o similar. Puedes hacer que la función devuelva un número y al detectar ese número o caracter o lo que sea, el programa principal pueda detectar que hay un error.
En lugar de utilizar la palabra return podrías utilizar una variable global. Las variables globales afectan a todo el programa y son utilizadas por todos. Son aquellas que definimos antes del setup. Esta opción te puede permitir ahorrarte el return pero se considera de riesgo. Esto es porque esa variable puede ser accedida por varias funciones a la vez o cambiarse y accionar algo que pueda ser peligroso.
En el ámbito maker tal vez no sea tan relevante lo de las variables globales pero es bueno tenerlo en cuenta e intentar utilizar la palabra return para tener variables locales.
Los parámetros de las funciones
Esto de la variable local lo he dejado ahí caer de una manera sutil. La variable local es aquella que solo pertenece a una función o (realmente) que se crea en esa función. Esto quiere decir que en otra función no la puedes utilizar ya que al salir de la función se destruye.
Veamos el siguiente caso:
int resuelveresta(termino1,termino2){ int resta = 0; resta = termino1 - termino2; return resta; }
Ahora tenemos una función que calcula una resta. Es evidente que no sería necesaria una función para una operación así pero es un ejemplo. La cosa es que tengo un int al inicio porque me va a devolver un número entero (Siempre que consideremos que vamos a hacer restas entre números enteros).
Luego aparece el nombre de la función y entre paréntesis dos nombres. Lo que está dentro del paréntesis es lo que llamamos parámetros. Los parámetros son valores que pasamos a la función y la función trabaja con ellos. Una vez hecho el trabajo nos devolverá otra variable (Tal y como nos confiesa el int del principio).
Este caso es el caso de una variable local ya que nos devolverá algo que utilizaremos en el loop. De hecho, la forma que tendría el llamar a esta función sería así:
void setup() { } void loop() { int restafinal = 0; restafinal = resuelveresta(8,5); Serial.println(restafinal); } int resuelveresta(int termino1,int termino2){ int resta = 0; resta = termino1 - termino2; return resta; }
Como ves, igualo la función a algo que es nuestra nueva variable donde guardaré el valor que me devuelva (return) la función. En el caso de una variable global, no haría falta esta igualación ya que al llamar a la función, el valor de mi variable se cambiaría solo. Para que fuese una variable global la tendría que declarar arriba del setup.
Por cierto, seguro que te has fijado que los términos dentro del paréntesis vienen con su tipo (int) definido delante. Esto es lo que me permite enviar cualquier valor entero, bien un número (como en este caso) o bien una variable.
Todo el mundo lo sabe, ¡Estamos de Perreo cuántico!
En cuanto al alcance de las variables locales, puedes tener dos variables llamadas de manera exactamente igual en funciones distintas y entre ellas no se cambiaran los valores . Si fuesen globales sería una locura y cada función andaría tocando el valor final de la variable.
Y con esto ya podemos dar por terminado el post este sobre las funciones y las variables y todo lo que se ha terciado. Nos vemos la semana que viene, mientras tanto aquí me quedo, de perreo cuántico…