Ir al contenido principal

Juegos con matrices de LEDs y Arduino

En una entrada anterior ya utilizamos una matriz de LEDs junto con el integrado max7219. Una de las virtudes de este integrado es que facilita la conexión de varias matrices usando un bus serie SPI, así como otros tipos de displays, como los de siete segmentos. En este artículo vamos a utilizar dos matrices para construir un pequeño juego tipo Pong, Arkanoid o, en fin, ya sabes a lo que me refiero, una raqueta que controla el jugador y una pelotita que hay que evitar que se salga por la parte inferior.

He montado el circuito sobre una protoboard usando un Arduino Nano, dos matrices de LEDs y un potenciómetro conectado a una entrada analógica del Arduino para controlar la raqueta. El esquema del circuito es el siguiente.

Juego con LEDs

Como ves, el circuito no tiene nada de particular. Los pines D8, D9 y D10 de Arduino se conectan a los pines CS, CLK y DIN del bus SPI de la matriz de LEDs. Además, obviamente, de conectar VCC y GND. El integrado max7219 nos provee, en la parte superior de la matriz de LEDS, de las conexiones necesarias para conectar una segunda matriz (y una tercera, cuarta, etc.). También he aprovechado las salidas VCC y GND de la segunda matriz para conectarlos al potenciómetro y así dejar más limpia de cables la protoboard. Finalmente, he conectado el potenciómetro a la entrada analógica A3 de Arduino. La tensión de entrada en el pin se convierte en digital mediante un ADC de 10 bits, así que tenemos un valor entre 0 y 1023, que usando la función map() de la librería de Arduino, adaptaremos a nuestras necesidades.

El código para Arduino es el siguiente.

#include "LedControl.h" 
#define WIDTH 16
#define HEIGHT 8
#define PADLENGTH 3
 
// Parámetros: pines DIN, CLK, CS y 2 (2 displays)
LedControl lc=LedControl(8,10,9,2);
const int analog_in = A3; // entrada analogica potenciometro
int val, pos; 
byte pantalla[8][16]; // pantalla
int x, y; // posición de la bola
int dx, dy; // delta
int gameover = 0;

void plot(int x, int y)
{
  int screen;
  
  if (x>=0 && x==0 && y<HEIGHT) { 
    if (x > ((WIDTH/2)-1)) {
      x = x - HEIGHT;
      screen = 1;
    } else {
      screen = 0;
    }
    lc.setLed(screen, x, y, 1);
  }
}

void draw_screen(int x, int y)
{
  int i;     
  // draw PAD
  for (i=0; i<PADLENGTH; i++) {
    plot(pos+i, 0);
  }
  // draw ball
  plot(x, y);
  
}

void move()
{
  x = x + dx;
  y = y + dy;
  if (x<1 || x>=WIDTH-1) {
    dx = -dx;
  } 
  
  if (y>=HEIGHT-1) {
    dy = -dy;
  }
  
  if (y==1 && x>=pos && x<=pos+PADLENGTH) {
    // rebota con la raqueta
    dy = -dy;
  } 
  
  if (y < 0) {
    // pelota sale por abajo. Game over
    gameover = 1;  
  }
}
 
void setup() {
  lc.shutdown(0,false);    // Iniciamos la matriz led
  lc.setIntensity(0,5);    // Intensidad de los leds
  lc.clearDisplay(0);      // Apagamos los leds
  lc.shutdown(1,false);    // Iniciamos la matriz led
  lc.setIntensity(1,5);    // Intensidad de los leds
  lc.clearDisplay(1);      // Apagamos los leds
  x = y = 0;
  dx = dy = 1;
  pos = 0;
  Serial.begin(9600);
}
 
void loop() {      
  int i;
  
  while(true) {   
    if (!gameover) {
      // leer entrada
      val = analogRead(analog_in);
      pos = map(val, 0, 1023, WIDTH - PADLENGTH, -1);
      Serial.println(pos);
  
      // actualizar matriz de LEDs
      lc.clearDisplay(0);
      lc.clearDisplay(1);
      draw_screen(x,y);
      move();
      delay(200);
    } else {
      // game over
      for (i=0; i<HEIGHT; i++) {
        lc.setColumn(0,i,B11111111);
        lc.setColumn(1,HEIGHT-i-1,B11111111);
        delay(200);  
      }
      x = y = 0;
      dx = dy = 1;
      gameover = 0;
      
    }
  }
}

La función plot() se encarga de activar un pixel en la pantalla "virtual" de 16x8 (las dos matrices juntas). Es decir, calcula en cuál de las dos matrices está el LED que se quiere activar y cuál es el LED físico que le corresponde dentro de esa matriz. La función draw_screen() dibuja la raqueta y la pelota en cada iteración del bucle principal y, finalmente, la función move() calcula la nueva posición de la pelota, verifica si ha rebotado o si ha tocado la base, en cuyo caso, hemos perdido y se muestra una pequeña animación en las matrices.

Aquí os dejo un vídeo con el resultado final.

Comentarios

Entradas populares de este blog

Creando firmas de virus para ClamAV

ClamAv es un antivirus opensource y multiplataforma creado por Tomasz Kojm muy utilizado en los servidores de correo Linux. Este antivirus es desarrollado por la comunidad, y su utilidad práctica depende de que su base de datos de firmas sea lo suficientemente grande y actualizado. Para ello es necesario que voluntarios contribuyan activamente aportando firmas. El presente artículo pretende describir de manera sencilla cómo crear firmas de virus para ClamAV y contribuir con ellas a la comunidad.

Ingeniería inversa de un parche de Microsoft Windows

A estas alturas ya hemos asumido que la seguridad total en Internet es, cuanto menos, un mito. Ningún software está libre de vulnerabilidades, y por mucha auditoría, test de intrusión o pruebas de fuzzing que nos empeñemos en hacer, ninguna metodología puede demostrar sin lugar a dudas que un software es 100% seguro. Ante este panorama, hay dos tendencias mayoritarias a la hora de hacer públicas las vulnerabilidades. Por un lado, están los que piensan que cuando se descubre un fallo ha de hacerse público de forma inmediata. En este escenario, la publicación de una vulnerabilidad es el pistoletazo de salida para una carrera entre el desarrollador para sacar el parche y los "malos" para lograr explotarla. Esta política es conocida como full disclosure . Por otro lado, tenemos a los siguen una política responsible disclosure , que abogan por mantener la vulnerabilidad en secreto hasta la salida del parche por parte del desarrollador. Sin entrar en cuestiones filosóficas que no...

Manejo de grafos con NetworkX en Python

El aprendizaje computacional es un área de investigación que en los últimos años ha tenido un auge importante, sobre todo gracias al aprendizaje profundo (Deep Learning). Pero no todo son redes neuronales. Paralelamente a estas técnicas, más bien basadas en el aprendizaje de patrones, también hay un auge de otras técnicas, digamos, más basadas en el aprendizaje simbólico. Si echamos la vista algunos años atrás, podemos considerar que quizá, la promesa de la web semántica como gran base de conocimiento ha fracasado, pero no es tan así. Ha ido transmutándose y evolucionando hacia bases de conocimiento basadas en ontologías a partir de las cuales es posible obtener nuevo conocimiento. Es lo que llamamos razonamiento automático y empresas como Google ya lo utilizan para ofrecerte información adicional sobre tus búsquedas. Ellos lo llaman Grafos de Conocimiento o Knowledge Graphs . Gracias a estos grafos de conocimiento, Google puede ofrecerte información adicional sobre tu búsqueda, ad...