Tutorial Arduino: Construye tu propia caja fuerte

Tutorial Arduino: Construye tu propia caja fuerte
ar1

¡Noob a la vista! Este es el primer artículo de Javier Light.

¡Hola a todos! Soy Javier Andrés Pérez (a.k.a. @Javier_Light) y este es el primer tutorial que subo a GeekyTheory. He convertido a "formato tutorial" el material que utilicé para exponer el taller de Arduino durante las jornadas IEEE Developer Days 2014.

Pese a lo llamativo del título, antes de que haya malentendidos, me gustaría aclarar que no vais a conseguir construir una caja fuerte de verdad cuando terminéis de leer este tutorial. Pero sí una de juguete, por así decirlo, con la que además de poder trastear un rato, aprenderéis algunos conceptos bastante interesantes que os ayudarán a desenvolveros con más soltura en el mundo de Arduino.

¡Empezamos!

1) Material necesario

Para llevar a cabo este tutorial, necesitarás:

  • Arduino UNO (o superior).
  • Protoboard y 3 cables para realizar las conexiones.
  • Potenciómetro (resistencia variable).
  • Diodo LED.

¿Que qué es un potenciómetro? Muy sencillo: es exactamente igual a una resistencia, pero podemos modificar el valor de la misma simplemente girando una ruleta. Las resistencias (y por lo tanto, también los potenciómetros) no tienen polaridad. En el esquema de la imagen inferior se ha colocado una sugerencia de montaje, pero funcionaría de forma idéntica cambiando la tierra por el positivo de 5 voltios. El terminal que queda en medio (analog pin) servirá para leer el valor de tensión desde Arduino.

potenciometro

2) Breve explicación del programa

A grandes rasgos, la idea es crear un programa para Arduino que permita manejar el valor de tensión leído en el potenciómetro. Al girar la ruleta, regularemos ese valor de tensión desde el mínimo (resistencia máxima) hasta el máximo (resistencia cero). El programa sabrá en todo momento cuánto hemos girado la ruleta, y esa posición de giro será un número de 0 a 9. Al mismo tiempo, el monitor serial de Arduino servirá como interfaz entre el usuario y el propio programa. Podremos guiar a la persona que trata de adivinar el número secreto, dándole las instrucciones necesarias, que se imprimirán por pantalla.

esquema

3) Esquemático del montaje

Fritzing3

Colocaremos además un LED con la patilla más corta a GND (tierra) y la otra al pin digital 13 (están al lado uno de otro). Para el potenciómetro: 5V a un lado, tierra al otro, y cable desde el terminal central hasta el pin analógico número 2 de Arduino (o cualquier otro, siempre que modifiques el código).

4) Código

Puedes consultar y utilizar mi código, que está a disposición de cualquiera en este link de GitHub. Además, lo incluyo aquí, a continuación (recomiendo hacer scroll lateral para ver las explicaciones que quedan ocultas): /* @author: Javier Andrés Pérez (aka JavierLight) Este es el último ejemplo del taller. Se trata de construir una caja fuerte con un potenciómetro. --Estructura: 1) El usuario introduce el número secreto de 5 cifras por teclado. 2) El programa guarda dicho número (de uno en uno, como componentes de un vector) 3) Estructuras for para iterar entre todas las componentes del vector (de 0 a 4, las posiciones, total 5 iteraciones). 4) El programa lee el valor analógico del potenciómetro (de 0 a 1023). 5) Función matemática map para cambiar rango: ahora el máximo es 9 en lugar de 1023. 6) Imprimir mensajes por pantalla con Serial.print para guiar al usuario a través del programa. 7) Objetivo: girar la ruleta hasta adivinar todos los números. */ //Declaración de variables antes del setup: int led=13;      //El led está conectado al pin digital 13. int potenciometro=2;    //El potenciómetro está conectado al pin ANALÓGICO 2. int leer=0;      //Variable en la que se almacenará el valor leído en el potenciómetro. //se trata de un valor analógico (de 0 a 1023). int convert=0;      //Variable que contendrá el valor leído, convertido con función map() [rango de 0 a 9] int convert_anterior=0;   //Variable que almacena el número correspondiente a la anterior conversión. int secreto0;  //Número secreto en la posición 0 int secreto1;  //Número secreto en la posición 1 int secreto2;  //etc... int secreto3; int secreto4; int secreto_leer=0; //Variable para guardar cada uno de los 5 números secretos que introducimos por TECLADO. int secreto[]={secreto0, secreto1, secreto2, secreto3, secreto4};  //Vector que contiene el número secreto //que se compone de 5 cifras. void setup() { pinMode(led,OUTPUT);            //El led es una salida. pinMode(potenciometro,INPUT);   //El potenciómetro es una entrada. Serial.begin(9600);     //Se inicializa el puerto serial. //Pedimos que se introduzca el número secreto (5 cifras): Serial.println("Por favor, introduce tu numero secreto (5 cifras)."); for (int a=0; a < 5; a++) { secreto_leer= Serial.read(); while(secreto_leer < 0) { secreto_leer= Serial.read(); } secreto[a]=secreto_leer-48;    //El dato que introducimos por teclado está codificado en ASCII. 0=48, 1=49, 2=50... Restamos 48 para obtener el número en entero. Serial.print(secreto[a]); } //Ocultar número secreto: Serial.println();  //Salto de línea con texto vacío. for (int a=0; a < 40; a++) { Serial.println("..."); } Serial.println("Gira la ruleta de la caja fuerte para adivinar el numero secreto"); } void loop() { for (int b=0;b < 5;b++) { Serial.print("Adivina el numero secreto de la posicion "); Serial.print(b+1); Serial.println(); leer=analogRead(potenciometro); convert=map(leer, 0 , 1023 , 0 , 9); while(convert!=secreto[b]) { leer=analogRead(potenciometro); //Función matemática map()  --> map(value, fromLow, fromHigh, toLow, toHigh) convert=map(leer, 0 , 1023 , 0 , 9);    //Se cambia el rango. Ahora el máximo es 9. if(convert!=convert_anterior && convert!=secreto[b]) { Serial.print(convert); Serial.println(" no es el numero correcto"); delay(1000); } else { //no hacer nada } convert_anterior=convert; } //Cuando sale del bucle anterior es porque hemos adivinado un número. digitalWrite(led,HIGH);  //Para celebrarlo, encenderemos el led. Serial.println(); Serial.print("Bien hecho! Has adivinado el numero de la posicion "); Serial.print(b+1); Serial.print(", que era el numero "); Serial.print(convert); Serial.println(); delay(3000);  //Lo mantenemos encendido durante 3 segundos. digitalWrite(led,LOW); } //Cuando salimos del último bucle es porque hemos acertado los 5 números secretos. Serial.println("____________________________________________"); Serial.println("Enhorabuena, has adivinado el numero secreto!"); Serial.println("____________________________________________"); Serial.println("Puedes volver a empezar pulsando el botón de RESET"); //Para celebrarlo, ahora que somos ricos, haremos parpadear el LED infinitamente. for(int contador = 0 ; contador >= 0 ; contador=contador+1) { digitalWrite(led,HIGH); delay(600); digitalWrite(led,LOW); delay(600); } }

5) Notas sobre el programa

  • Entrada de datos por teclado con Serial.read( )

Cuando pedimos al usuario que introduzca el número secreto de 5 cifras por teclado, debemos tener en cuenta que Arduino manejará esos números de uno en uno. Durante todo el programa utilizaremos ciclos for, con una variable que tomará los valores de posición del vector en el que almacenaremos las componentes del número secreto.

Por defecto, cuando esperamos que el usuario introduzca algo por teclado pero este todavía no lo ha hecho, el valor que lee Arduino con Serial.read( ) es igual a -1. Este es un hecho a tener en cuenta, ya que en el programa nos aseguraremos de que los 5 números que se introducen por teclado se guarden, obligando a leer datos mientras el valor leído sea menor que cero (que es el caso por defecto, -1). Con seguiremos esto fácilmente con un while que fuerce a leer siempre que no se introduzca un número mayor o igual que cero.

  • Uso de variable vector para almacenar el número secreto y ciclos for para pasar por todas sus componentes

Por ejemplo, si el número secreto es el 65248, nuestro vector tendrá en la posición 0 guardado el número 6, en la posición 1 el número 5, en la posición 4 guardará el número 8, etcétera. Cuando la variable que utilicemos en el ciclo for tome un valor superior al de número de posiciones del vector (0,1,2,3,4), saldremos del ciclo y el programa continuará.

¿Por qué utilizar un vector para guardar el número? Muy sencillo: podremos acceder a cualquier componente del mismo indicando su posición. Por ejemplo, para hacer referencia a la primera cifra del número secreto, basta con acceder al valor de la variable secreto[0]. La segunda cifra, secreto[1]. Y así hasta la quinta, secreto[4].

  • Función map para cambiar el rango de lectura del potenciómetro

Al utilizar analogRead(pin) recibiremos como resultado el valor de tensión que lee Arduino en el potenciómetro (al tratarse de un valor analógico, tomará valores desde un mínimo de 0 hasta un máximo de 1023). En total, 1024 valores. La precisión del valor leído es muy baja, sucede que sin ni siquiera mover la ruleta del potenciómetro podemos ver cómo oscilan los valores de tensión leídos. Para solucionar este problema vamos a realizar un cambio de rango.

Conseguiremos un cambio de rango de forma sencilla utilizando la función matemática map. Esta función necesita como argumentos la variable a transformar, el mínimo anterior, el máximo anterior, el mínimo nuevo y el máximo nuevo. Los mínimos no los transformaremos, solo tocaremos el nuevo máximo. En vez de 1023, el máximo ahora será 9. Cuando giremos la ruleta, obtendremos en un extremo el valor 0 y en el otro extremo el valor 9.

Si tenéis cualquier duda, podéis plantearla en los comentarios. ¡Espero que os guste!