Control de una matriz de LED 8x8 con MAX 7219, aplicado a Tetris

¿Qué es Tetris?

Tetris, es un videojuego que consiste en tener 5 figuras aleatorias las cuales se pueden, rotar, trasladar, y apilar, esto con el fin de lograr llenar la mayor cantidad de espacios en la pantalla.

¿Qué se necesita para recrear un Tetris?

• Modulo Matriz 8x8 con Max7219

• Tarjeta de desarrollo (para este caso STM32F411 Nucleo-64)

¿Cómo recrear un Tetris? Para empezar a desarrollar este proyecto se deben tener en cuenta ciertos parámetros, que logran un mejor funcionamiento del sistema:

• Definición y selección de pines

Para lograr trabajar con este módulo, se debe entender primero como se realiza la comunicación entre Tarjeta de desarrollo y el driver de interfaz serial(MAX7219). Que para esto se utiliza el estándar de comunicación SPI (Serial Peripheral Inteface). Esta comunicación permite que se envíen datos de manera más óptima y de manera síncrona, por medio de un bus de datos el cual es enviado en un ciclo de reloj (Toma el dato en flanco de subida o bajada, segun a configuracion del integrado) esto es puede evidenciar mejor en las siguientes imagenes:

/media/uploads/Nicolas_11/time_spi_OV3WLiE.png

/media/uploads/Nicolas_11/spi_three_slaves.png

Una vez conociendo esto se observan los diferentes puertos con los periféricos que controlan la comunicación SPI, que consta de, Pin de función MOSI, Pin de CLK y Pin de selección, además de Vin y GND. El cómo conectarlo se evidencia en la siguiente figura:

/media/uploads/Nicolas_11/def_pines.png

• Definición de parámetros:

Para este proyecto se definieron ciertos parámetros de funcionamiento que son:

Ingresar datos por el puerto serial

Restringir el programa para que si no se expresa entre < > no realice el trabajo

Incluir 5 figuras de Tetris.

Desplazar las figuras de Tetris a una posición determinada en los 8 espacios

Rotar 5 figuras de Tetris en los grados (0, 90,180,270)

• Aplicación de parámetros:

Una vez definido los parámetros se empezará a aplicar realizando el código que este será:

Para esto primero se debe definir la velocidada la cual se realiza la transmision del serial para que el usuario ingrese datos y con esto empezar a delimitar los dato (definiendo el Baud de comunicación serial en 9600).

Inicio de codigo

#include "mbed.h"
SPI deviceM(PB_15, PB_14, PB_13);
DigitalOut ssel (PB_12);
Serial a(USBTX,USBRX);

Una vez definido el serial se configura los inicios del modulo para que la matriz se inicialice

Para esto se deben enviar ciertos comandos para que se defina, Tamaño de matriz, Intensidad de matriz, y por ultimo un Test de la matriz, estos comados son (Estos comandos se deben escribir en Hexadecimal):

0x0F, este comando realica un DisplayTest que debe tener valores de 1 para realizar el test y 0 para no hacerlo.

0x0C, este comando habilita el funcionamiento del MAX7219, 1 para activar.

0x0A, este comando le da al MAX7219 la intensidad que manejara estos estan en un rango de (0x00 hasta 0x0F).

0x0B, este comando delimita el maximo de digitos para el display que va desde (0x00 hasta 0x07), en este caso se trabajan datos de 8 bits dado por la matriz de 8x8, por ende se delimitara con un 0x07.

Inicializar matriz y el baud

int main() {
                    a.baud(9600);
                    sendSPI(0x0c,1);
                    sendSPI(0x09,0);
                    sendSPI(0x0A,0x01);
                    sendSPI(0x0F,1);
                    wait (0.5);
                    sendSPI(0x0F,0);
                    wait (0.5);
                    sendSPI(0xB,0x7);
                    borrar();

Con esto definido se procede al ejecutar los comandos para realizar las tareas propuestas.

Main

while(1){
                        in=a.getc();
                        Tipofig=a.getc();
                        vcol=a.getc();
                        grado=a.getc();
                        out=a.getc();
                        if(in==60 && 1<=Tipofig<=5 && 1<=vcol<=8 && 0<=grado<=3 && out==62){
                          switch(Tipofig)
                          {
                           case 1:
                           giro(F_t,vcol,grado);
                           break;
                           case 2:
                           giro(F_s,vcol,grado);
                           break;
                           case 3:
                           giro(F_c,vcol,grado);
                           break;
                           case 4:
                           giro(F_l,vcol,grado);
                           break;
                           case 5:
                           giro(F_I,vcol,grado);
                           break;
                           default:
                           borrar();
                           break;
                          }
                        }
                        else{
                            borrar();
                            }
                     }

o En el ciclo while, esta:

  • El como obtener los datos requiere: Para obtener el serial se utliza el metodo .getc, en este ejercicio se utiliza para obtener el dato por serial puesto que la variable a esta definida para usar (Tx,Rx).
  • Evaluar el dato que se envia: Se debe delimitar cual de las figuras debe mostrarse, que en este caso son el simbolo ‘<’ (En hexadecimal se representa 60) que delimita el inicio del comando, la selección de las 5 figuras, parametro de giro y columna en el cual inicia y para cerrar el comando ‘>’(En hexadecimal se representa 60), estos son llevados a las funciones que operan la figura y la muestran en la matriz.
  • Las funciones que se aplicaran, son:

/media/uploads/Nicolas_11/tabla_figuras.png

Funcion giro

void giro(uint8_t *f,uint8_t col,uint8_t gi)
     {  
     if(col>=5){
                col=5;
                }
     uint8_t a[3]={0,0,0};
     int i;
     int j;
         switch(gi){    
         case 0:
         printMatrix(f,col);
         break;
         case 1:
         for(j=0;j<3;j++){
            for(i=0;i<3;i++){
             a[i]=((((*(f+j))<<2-i)&0b10000000)>>j)+a[i];
            }
         }   
         printMatrix(a,col);
         break;
         case 2:
         for(j=0;j<3;j++){
            for(i=0;i<3;i++){
             a[i]=((((*(f+(2-i)))>>2-j)&0b00100000)<<j)+a[i];
            }
            }
         printMatrix(a,col);
         break;
         case 3:
         for(j=0;j<3;j++){
            for(i=0;i<3;i++){
             a[i]=((((*(f+j))>>2-i)&(0b00100000))<<j)+a[i];
            }
          }   
         printMatrix(a,col);
         break;
         default:
         break;
         }     
     }

La funcion giro(), se encarga de recibir el vector con las direcciones de cada figura, la columna en la cual inicia y el grado en el que se debe mostrar,

Para esto se evalua en un Switch cada caso de grados que para este caso sera (00=0⁰, 01=90⁰, 02=180⁰, 03=270⁰).

Para realizar estos giros se realiza un ciclo que lo que realiza es un recorrido binario y este lo sobre escribe según el giro que se selecciones.

Una vez ya se realice el giro de la figura se procede a la otra funcion que es printMatrix().

Funcion printMatrix

void printMatrix(uint8_t* vC, uint8_t col)
{
    int i;
    int j=1;
    int h=1;
    for(i=1;i<=8;i++){
        
        if(*(vC+1)==0b00000000 && *(vC)==0b00000000){
                sendSPI(i,*(vC+2)>>col-1); 
                  if(i>2){
                  sendSPI(i-1,0);
                  }   
        }
        else
        {  
          if(*(vC)==0b00000000 && i>=1){
                j=i;
                h=j-1;
                sendSPI(j,*(vC+1)>>col-1);
                sendSPI(h,*(vC+2)>>col-1);
                if(i>2){
                sendSPI(i-2,0);}
           }        
          else {
             if(i>=1){
             j=i-1;
             h=i-2;
             sendSPI(i,*(vC)>>col-1);
             sendSPI(j,*(vC+1)>>col-1);
             sendSPI(h,*(vC+2)>>col-1);
               if(i>2){
               sendSPI(i-3,0);
               }  
             }
           }  
        }
    wait(Vel);
    }
}

Esta funcion recibe la figura ya con los cambios que el usuario deseo, y lo que realiza es el proceso de mostrar en la matriz de 8x8, esto mediante la funcion sendSPI().

Funcion sendSPI

void sendSPI(uint8_t d1, uint8_t d2)
{
    deviceM.unlock();
    ssel=0;
    deviceM.write(d1); 
    deviceM.write(d2);  
    ssel=1;
    deviceM.lock(); 
}

Esta funcion recibe la Figura selecionada y lo que ejecuta es una trama que en este caso lo que envia es, valor donde se inicia y que debo mostrar en ese valor. De la manera siguiente:

sendSPI(1,0b11100000);

Get Started

  • 1. Conectar el módulo de la Matriz a la tarjeta de desarrollo
  • 2. Conectar la tarjeta de desarrollo al PC
  • 3. Una vez conectado estos dos se procede a abrir el terminal del PC, donde lograremos enviar los datos por serial a la tarjeta de desarrollo. Para esto se utilizará CoolTerm

Uso de CoolTerm:

/media/uploads/Nicolas_11/coolterm.png

En este programa se debe conectar la tarjeta de desarrollo con el CoolTerm, para esto se configura el puerto al que esta conectada la tarjeta, mediante el icono de options para definir el puerto; luego seleccionar el icono de connect para enlazar la terminal serial de la tarjeta .

para poder enviar datos desde el computador a la tarjeta STM32F411 , se debe ir al menu conection, y buscar la opcion send string, se desplegara una ventana con la cual se podra ingresar los datos.

NOTA: para este proyecto se trabajaron los datos en hexadecimal, la cual ya viene siendo una de las opciones en CoolTerm.

/media/uploads/Nicolas_11/sendstring.png

/media/uploads/Nicolas_11/hex.png

los datos deben ser ingresados de la siguiente manera:

/media/uploads/Nicolas_11/ejemhex.png

Donde :

- 3C es el equivalente en hexadecimal a "<".

- 3E es el equivalente en hexadecimal a ">".

- 01 , 01, 01 son los valores para elegir la figura, posicion y el giro respectivamente.


Please log in to post comments.