Siempre creciendo, siempre aprendiendo. Cultura maker.

En esta ocasión, quiero mostraros un montaje muy sencillo de hacer, rápido de montar y que va a conjugar varios de los parámetros con los que estamos jugando en Tecnología y en Robótica en la ESO:

LA PELOTA ÉTEREA

¡CHÁN CHÁN CHÁN CHÁN CHÁN CHÁN!

 

La idea es muy sencilla, pero muy atractiva al mismo tiempo: vamos a mover una pelotita roja en la pantalla, intentando salvar los obstáculos que se va encontrando, SÓLO MOVIENDO NUESTRA MANO ARRIBA Y ABAJO.

controlPelotaporLED

Con este montaje, podemos trabajar muchos conceptos:

 

  • La variación de resistencia en una LDR con el grado de luz
  • Qué es y cómo funciona un divisor de tensión
  • Diferencia entre señales analógicas y digitales.
  • Funcionamiento de un conversor A/D
  • Comunicación entre dispositivos a través del puerto serie.
  • Proporciones entre rangos de valores (pues tendremos que transformar la señal obtenida dentro del rango {0-1023} al rango {0-255}, dado que a través del puerto Serie queremos transmitir a Processing un valor que pueda ser contenido en un único byte.

 

¿Es complicado? ¡NO! ¡EN ABSOLUTO!.

 

Verás: el proyecto está enfocado desde tres apartados:

  1. Con sólo una célula LDR (Light Dependent Resistance, resistencia dependiente de la luz) y un potenciómetro (que nos permitirá adaptarnos a las distintas gradaciones de luz en que nos podemos encontrar, dependiendo de la hora y de la luminosidad de la estancia), mediremos la sombra que hacemos con nuestra mano sobre la protoboard, que es proporcional a la distancia a la que la hemos puesto.
  2. Arduino transformará el valor proporcionado por la LDR a un valor entre 0 y 1023, mediante el convertidor Analógico/Digital, A/D. Este valor se va a transmitir mediante el puerto Serie a nuestro ordenador, donde tenemos corriendo un programa en Processing.
  3. Processing recibe este mismo valor a través de dicho puerto Serie (Serial), y lo convierte a un valor proporcional entre el valor mínimo y máximo de altura de la pantalla, donde situará un círculo dibujado en Processing, que nos proporcionará así la ilusión de que movemos una pelota con nuestra mano, mágicamente. ¡La Pelota Etérea!.

 

¿Que necesitamos para hacer este montaje? ¡Solo un potenciómetro (quizás de unos 10 kΩ) en divisor de tensión con nuestra LDR!. Aquí tienes el esquema:

 

conexionElectronica

 

Como puedes ver, es sencillísimo: de Alimentación a potenciómetro, de potenciómetro a LDR y de éste a tierra. Mediante un cable, conectaremos la primera patilla, A0, del convertidor A/D de la Arduino al punto en que contactan el potenciómetro y la LDR.

 

Arduino va a recibir un valor analógico entre 0 y 5 V (que aumentará con la luz recibida, es decir, cuanto más alejemos la mano de la LDR) que transformará a un valor analógico entre 0 y 1023, y que luego, mediante la orden map, recalculará al rango 0-255, para finalmente transmitirla vía puerto Serie.

 

Aquí está el código de Arduino:

 

int lectura;

int val;
int vMin;
int vMax;
int vEnviado;
void setup() 
{

  Serial.begin(9600);
}
void loop()
{
  if (Serial.available() > 0) { // If data is available to read,
    val = Serial.read(); // read it and store it in val

    if(val == '1') //if we get a 1
    {
   //espero a que deje de escribir 1
    }
    delay(100);
  } 
    else {
      lectura=analogRead(A0);
      if (lectura<vMin){vMin=lectura;}
      if (lectura>vMax){vMax=lectura;}
      vEnviado=map(lectura,vMin,vMax,0,255);
    Serial.write(vEnviado); //send back a hello world
    delay(50);
    }
}

Ahora es el turno de Processing. Es muy difícil transmitir a nuestro alumnado, salvo quizás a los Bachilleratos, el concepto de Programación Orientada a Objetos (POO). Tampoco es lo que queremos. Bástese explicarles que Processing está esperando un valor a través del puerto Serie. Como no sabemos cuál es el número al que se asociará dicho puerto, me he permitido resaltar la parte del código donde se intenta determinar esto. En el valor entre corchetes en Serial.list()[X], empezando por cero, iremos probando con 1, 2, 3... hasta que veamos que Processing y Arduino han conectado.

Por otro lado, también podemos explicar a los estudiantes que este es el valor que determina la altura de la pelota dentro del juego, que se va redibujando varias veces por segundo, creando la ilusión de que la estamos moviendo con la mano. En fin, aquí está el código de Processing:

import processing.serial.*; 
 Serial myPort;  
muro m;
int val;
int altura;
int v=3;
int choques=0;
boolean juegoSigue;
int valorAleatorio;

boolean firstContact = false;
String texto="Nº de choques: ";
void setup() {
  randomSeed(0);
  size(800, 600); 
  //en Serial.list()[numero], éste será el orden en que 
  //hemos conectado nuestra Arduino al USB. Ir probando con 0,1,2...
  myPort = new Serial(this, Serial.list()[1], 9600);
  m=new muro(100,v);
  textSize(32);
}
void draw() {
  if (juegoSigue){
  background(255,255,255);
   fill (255,0,0);
  m.dibuja();
  m.mueve();
  
  if (m.dameX()>800){
    valorAleatorio=(int)random(600);
    if (valorAleatorio>500){
      valorAleatorio=550;
    }
    
    if (valorAleatorio<100){
      valorAleatorio=100;
    }
    m.hazAltura(valorAleatorio);
    m.hazX(0);
    m.hazVelocidad(v+2);
  }
  
  if((m.dameX()<400)&&(m.dameX()>350)&&((altura<m.dameAltura())||(altura>m.dameAltura()+100))){
    //juegoSigue=false;
    choques++;
  }
  
if (myPort.available()>0){
 val=myPort.read(); 
}
println(val);

altura=(int)map(val,190,240,0,600);
ellipse(400,altura,50,50);
fill(0,0,255);
text(texto+choques,500,50);
  }else{
    //TODO QUEDA PARADO HASTA QUE PULSAMOS ESPACIO
   background(255,0,0);
   fill(255,255,255);
  m.dibuja(); 
  ellipse(400,altura,50,50);
  text("PULSA ESPACIO PARA CONTINUAR",200,200);
  }
}
void keyPressed(){
if (key==' '){
  juegoSigue=true;
  m.hazX(0);
  m.hazVelocidad(2);
 } 
}

//CREAMOS UNA CLASE PARA EL MURO QUE DEBE SALTAR LA PELOTA.
class muro{
 int x,rojo,verde,azul;
 int altura;
 int velocidad;
   muro (int alt, int vel){
   altura=alt;
   velocidad=vel;
   x=0;
   rojo=(int)random(255);
   verde=(int)random(255);
   azul=(int)random(255);
   
 }
 void dibuja(){
  
  rect(this.x,0,50,altura);
  rect(this.x,altura+200,50,600-altura);
 }
 void mueve(){
  this.x=this.x+this.velocidad; 
 }
 int dameX(){
  return this.x; 
 }
 int dameAltura(){
   return this.altura;
 }
 void hazX(int a){
  this.x=a; 
 }
 void hazAltura(int a){
   this.altura=a;
 }
 void hazVelocidad(int a){
  this.velocidad=a; 
 }
}

 

 Y ya está. Con un poco de suerte, puedes tener todo montado en menos de quince minutos, la primera vez. En las siguientes, puedes tardar incluso menos. De todos modos, como siempre, ya te digo que todo el material está disponible, como siempre, en mi Github:

https://github.com/agomezgar/tutoriales(en la carpeta pelotaEterea)

 

Y, como otras veces, te dejo un vídeo en el que se refleja y explica todo el proceso:

 

 

Y creo que eso es todo. Espero que os sea útil, o por lo menos resulte interesante. Os agradeceré que lo compartáis, y que me hagáis llegar cualquier tipo de opinión a través de los comentarios. ¡Sed felices!. ¡Hasta la próxima, makers!