Brazo robotico jugando trique

Publicado el: 21 de julio de 2019
Intermedio
Acerca de este proyecto
Brazo rob贸tico que a trav茅s de arduino y visual basic juega contra el usuario el famoso juego de tres en l铆nea o trique.
robot juego
Publicidad
DETALLES

Quiero compartir este proyecto realizado de un brazo rob贸tico que juega el famoso juego de triqui como es llamado en Colombia, tatet铆 en Argentina tres en l铆nea en Espa帽a y juego del gato en otros pa铆ses, contra un humano.

El brazo es controlado por un arduino uno el cual recibe comandos de un programa en visual basic a trav茅s del puerto serial.

LISTA DE MATERIALES


  • 1 Brazo rob贸tico con pinza.
  • Camara web de buena resoluci贸n.
  • Arduino uno o equivalente.
  • Tablero de 3 x 3 cuadrados.
  • Piezas o fichas rojas y blancas.

FUNCIONAMIENTO

Las fichas de color rojo son para el jugador humano y las de color blanco son las fichas del computador, el jugador es quien tiene el primer turno.

La c谩mara web conectada al computador captura la imagen del tablero de 3脳3 y esta imagen es procesada por el programa en visual basic net, que hace uso de la librer铆a web cam, ( en el enlace se incluye la librer铆a ). La imagen capturada se divide en nueve cuadros iguales de 60 pixeles y luego es recorrida por un bucle para determinar la cantidad de pixeles rojos que contiene cada cuadro. Si el pixel es de color rojo se marca con un punto del mismo color y la imagen es pasada a un control picture.

Luego en la imagen del control picture tambi茅n se recorre cada cuadro para contar la cantidad de pixeles rojos, si la cantidad de pixeles rojos de cada cuadro es igual o superior al umbral establecido, se asume que en esa posici贸n hay una ficha de color rojo que corresponde al movimiento del jugador humano.

Despu茅s que el jugador haya colocado su ficha, presiona un bot贸n para indicarle al robot que es su turno de jugar. Este bot贸n llama a un procedimiento que es el encargado de recorrer los pixeles mencionados en el p谩rrafo anterior, y de llamar a una funci贸n encargada de decidir en que posici贸n jugar el computador, gracias a un algoritmo usado en juegos de turnos de dos personas llamado minimax. Despu茅s de haber escogido en que posici贸n jugar, se env铆a a trav茅s del puerto serial al Arduino un string con el n煤mero de la posici贸n escogida por el algoritmo y el arduino mueve el brazo hacia dicha posici贸n.

A continuaci贸n se muestra el video del proyecto en funcionamiento:


Podemos dividir el proyecto en cuatro partes:

  1. El brazo rob贸tico.
  2. La captura de la imagen.
  3. La l贸gica del juego.
  4. Movimiento del brazo.

1 - EL BRAZO ROB脫TICO.


l brazo rob贸tico utilizado en este proyecto fue comprado el kit para armar, pero si desea puedes armarte tu propio brazo. Est谩 construido en acr铆lico de alta resistencia ,tiene 3 + 1 grados de libertad y contiene los siguientes servomotores:

  • Base (servomotor futaba S3003 con un rango de movimiento de 0掳 a 180掳)
  • Hombro (servomotor futaba S3003 con un rango de movimiento de 0掳 a 180掳)
  • Mu帽eca (servomotor futaba S3003 con un rango de movimiento de 0掳 a 180掳)
  • Pinza (servomotor tower pro Sg90 con un rango de movimiento de 60掳 a 120掳)

Brazo robotico

El servomotor de la base se conecta al pin n煤mero 5 del arduino.

El servomotor del hombro se conecta al pin n煤mero 6 del arduino.

El servomotor de la mu帽eca  se conecta al pin n煤mero 9 del arduino.

El servomotor de la pinza se conecta al pin n煤mero 10 del arduino.

Diagrama


2 - CAPTURA DE LA IMAGEN.


Para el proceso de captura de la imagen en el programa de visual basic, se usa la librer铆a web cam; esta se encarga del manejo de la web cam conectada a nuestro computador. Al agregar la referencia a esta librer铆a nos inserta un control en el formulario donde se mostrar谩 la imagen que visualiza la c谩mara. Un control timer se encuentra monitoreando cada 50 ms el tablero cada 5 pixeles ( se hace un escaneo de cada 5 pixeles con el fin de reducir el tiempo de b煤squeda ), se obtiene el color del pixel examinado y si corresponde a un color rojo, este p铆xel se marca con un punto del mismo color.

Camara web

Juego


Despu茅s que el jugador haya colocado su ficha de color rojo en la posici贸n deseada, se presiona un bot贸n para indicarle al robot que es su turno de jugar. En este proceso, se transfiere la imagen del control web Cam hacia un control picture, se divide la imagen en 9 cuadros y a trav茅s de un ciclo For se realiza la b煤squeda de p铆xeles de color rojo, cada vez que se encuentre un pixel de color rojo se incrementa un contador que lleva la cuenta de la cantidad de pixeles rojos hallados en ese cuadro. Si la cantidad de pixeles rojos es igual o mayor al umbral establecido ( en este proyecto se compara con el n煤mero 75 ), entonces se asume que en ese cuadro se encuentra una ficha de color rojo, y se marca dicho cuadro con una 鈥x鈥 en la grilla de juego.

Cuando la grilla detecta que el jugador ha movido su ficha, se ejecuta una funci贸n que es la encargada de decidir en que posici贸n debe jugar el robot. Esta l贸gica de juego ser谩 explicada en el pr贸ximo bloque.


3 - LA L脫GICA DEL JUEGO.


El programa utiliza un algoritmo llamado minimax, el cual es un algoritmo utilizado en l贸gica de juegos especialmente en aquellos de turnos de dos jugadores. De manera general, consiste en recorrer todo el 谩rbol de soluciones del juego a partir de un estado dado, es decir, seg煤n las casillas que ya han sido rellenadas. Por tanto, minimax se ejecutar谩 cada vez que le toque mover a la IA. Si desea aprender m谩s sobre el algoritmo minimax recomienda ler la informaci贸n albergada en wikipedia.

Como se mencionaba en el p谩rrafo anterior, cuando la grilla detecta que se marc贸 con una 鈥x鈥 alguna posici贸n, se activa la inteligencia artificial del juego, el algoritmo minimax selecciona el mejor movimiento para el robot, tratando en todo lo posible de evitar que el jugador humano sea el ganador. Al habr seleccionado su posici贸n, marca el cuadro seleccionado en la grilla con una 鈥o鈥, al tiempo que env铆a a trav茅s del puerto serial al arduino un String con la posici贸n seleccionada por el algoritmo.


Logica del juego


Descargue el c贸digo fuente del programa en visual basic haciendo clic aca.

4- MOVIMIENTO DEL BRAZO.


Cuando el arduino recibe a trav茅s del puerto serial la posici贸n escogida por el computador para jugar, dependiendo de la posici贸n se ejecuta un procedimiento encargado de mover el servo hacia la posici贸n especificada. Como son nueve posiciones, son nueve procedimientos, cada uno con valores de 谩ngulos diferentes seg煤n la posici贸n.

Puede descargar el c贸digo fuente del programa en arduino haciendo clic ac谩.


Si tienes dudas, sugerencias o inquietudes, dejalas en los comentarios.






CODIFICACI脫N
Codigo arduino-
Este es el c贸digo que se carga al arduino.
#include <Servo.h>
int i,j;

Servo base;
Servo hombro;
Servo codo;
Servo pinza;

int angulo=0;
char dato;

int anguloBase;
int anguloHombro;
int anguloCodo;
int anguloPinza;
int anguloAgarrePinza;


  void setup() 
  {
    Serial.begin(9600);
    
     
    base.attach(5);
    hombro.attach(6);
    codo.attach(9);
    pinza.attach(10);

    anguloBase=90;
    anguloHombro=90;
    anguloCodo=90;
    anguloPinza=70;
    anguloAgarrePinza=130;
    
    
    base.write(90);
    delay(300);
    hombro.write(90);
    delay(300);
    codo.write(90);
    delay(300);
    pinza.write(70);
    delay(300);
    
    
  }
void girarBaseDerecha()
{
  anguloBase=anguloBase+2;
  base.write(anguloBase);
}

void girarBaseIzquierda()
{
  anguloBase = anguloBase-2;
  base.write(anguloBase);
}

void subirHombro()
{
  anguloHombro=anguloHombro-2;
  hombro.write(anguloHombro);
  Serial.println(anguloHombro);  
}
void bajarHombro()
{
  anguloHombro=anguloHombro+2;
  hombro.write(anguloHombro);
  Serial.println(anguloHombro);  
}

void levantarCodo()
{
  anguloCodo=anguloCodo+2;
  codo.write(anguloCodo);
}

void bajarCodo()
{
  anguloCodo=anguloCodo-2;
  codo.write(anguloCodo);
}

void abrirPinza()
{
  anguloPinza=anguloPinza-5;
  pinza.write(anguloPinza);
}

void cerrarPinza()
{
  anguloPinza=anguloPinza+5;
  pinza.write(anguloPinza);
}

void posicionInicial()
{
  for(i=90;i<=180;i++)
  {
    base.write(i);
  }  
  delay(300);
  hombro.write(90);
  delay(300);
  codo.write(90);
  delay(300);
  pinza.write(70);
}

void recogerFicha()
{
  for(i=90;i<=174;i++)
  {
    hombro.write(i);
    delay(20);
  }  
  delay(200);
  
  for(i=90;i<=114;i++)
  {
    codo.write(i);
        delay(20);
  }  
  delay(200);
  
  for(i=70;i<=anguloAgarrePinza;i++)
  {
    pinza.write(i);
    delay(20);
  }
  delay(200);
  
  for(i=176;i>=140;i--)
  {
    hombro.write(i);
        delay(20);
  }    
}
//************************************************************************++
void primeraPosicion()
{
   for(i=180;i>=92;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=114;i<=124;i++)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=170;i<=176;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=124;i<=130;i++)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=105;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=176;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}


void segundaPosicion()
{
  //Muevo la base
  for(i=180;i>=88;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);

  //Muevo el codo hasta 90
  for(i=114;i>=90;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);


  //Muevo el hombro  hasta 160
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);

//Muevo el codo  
  for(i=90;i<=102;i++)
  {
    codo.write(i);
    delay(20);
  }  
  
  delay(200);
    
  //Abro la pinza
  for(i=110;i>=90;i--)
  {
    pinza.write(i);
    delay(20);
  }

  delay(200);

  //Subo el hombro  
  for(i=170;i>=140;i--)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  posicionInicial();
  
}

void terceraPosicion()
{
  //Muevo la base hasta los 90 grados
  for(i=180;i>=90;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
   //Muevo el codo hasta los 70 grados
  for(i=114;i>=70;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  //Muevo el hombro hasta 170 grados
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
   //Muevo el codo hasta los 80 grados
  for(i=70;i<=80;i++)
  {
    codo.write(i);
    delay(20);
  }
   
  delay(200);
  
  //Abro la pinza  
  for(i=105;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
    
  for(i=170;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}


void cuartaPosicion()
{
  //Muevo la base
  for(i=180;i>=104;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);

  //Muevo el hombro  
  for(i=140;i<=172;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo  
  for(i=114;i<=122;i++)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
    
 //Muevo el hombro  
  for(i=172;i<=176;i++)
  {
    hombro.write(i);
    delay(20);
  } 
  
  delay(200);

//Muevo el codo  
  for(i=122;i<=132;i++)
  {
    codo.write(i);
    delay(20);
  }  
  
  delay(200);
    
  //Abro la pinza
  for(i=110;i>=90;i--)
  {
    pinza.write(i);
    delay(20);
  }

  delay(200);

  //Subo el hombro  
  for(i=170;i>=140;i--)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  posicionInicial();
  
}

void quintaPosicion()
{
  //Muevo la base 
  for(i=180;i>=106;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo
  for(i=114;i>=104;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el hombro
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
   
  for(i=105;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=170;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}

void sextaPosicion()
{
  //Muevo la base 
  for(i=180;i>=108;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo
  for(i=114;i>=74;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el hombro
  for(i=140;i<=160;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
   
  for(i=105;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=160;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}


void septimaPosicion()
{
  //Muevo la base
  for(i=180;i>=116;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);

  //Muevo el hombro  
  for(i=140;i<=164;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo  
  for(i=114;i<=120;i++)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
    
 //Muevo el hombro  
  for(i=164;i<=172;i++)
  {
    hombro.write(i);
    delay(20);
  } 
  
  delay(200);

//Muevo el codo  
  for(i=120;i<=138;i++)
  {
    codo.write(i);
    delay(20);
  }  
  
  delay(200);
    
  //Abro la pinza
  for(i=110;i>=90;i--)
  {
    pinza.write(i);
    delay(20);
  }

  delay(200);

  //Subo el hombro  
  for(i=172;i>=140;i--)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  posicionInicial();
  
}

void octavaPosicion()
{
  //Muevo la base hasta los 120 grados
  for(i=180;i>=120;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el hombro hasta los 170 grados
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo hasta los 94 grados
  for(i=114;i>=112;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Abro la pinza  
  for(i=anguloAgarrePinza;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=170;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}

void novenaPosicion()
{
  //Muevo la base hasta 132 grados
  for(i=180;i>=132;i--)
  {
    base.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el codo hasta los 94 grados
  for(i=114;i>=94;i--)
  {
    codo.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Muevo el hombro hasta los 170 grados
  for(i=140;i<=170;i++)
  {
    hombro.write(i);
    delay(20);
  }
  
  delay(200);
  
  //Abro la pinza  
  for(i=anguloAgarrePinza;i>=70;i--)
  {
    pinza.write(i);
    delay(20);
  }
  
  delay(200);
  
  for(i=170;i>=140;i--);
  {
    hombro.write(i);
    delay(20);
  }
  
  posicionInicial();
  
}

void happy()
{
  //Muevo el codo hacia arriba
  for(i=90;i<=180;i++);
  {
    codo.write(i);
  }
  
  delay(200);
  
  for(j=0;j<=10;j++)
  {
    
        for(i=180;i>=120;i--);
        {
          base.write(i);
        }
        
        delay(100);
        
        for(i=120;i<=180;i++);
        {
          base.write(i);
        }
        
        delay(100);
        
        for(i=180;i>=120;i--);
        {
          base.write(i);
        }
        
        delay(100);
        
        for(i=120;i<=180;i++);
        {
          base.write(i);
        }
        
        delay(100);
  }
  
  //Muevo la pinza
  for(j=0;j<=10;j++)
  
  {
  
      for(i=70;i<=140;i++);
      {
        pinza.write(i);
      }
      
      delay(200);
      
      for(i=140;i<=120;i--);
      {
        pinza.write(i);
      }
      
      delay(200);
      
      for(i=100;i<=120;i++);
      {
        pinza.write(i);
      }
      
      delay(200);
      
      for(i=140;i<=100;i--);
      {
        pinza.write(i);
      }
      
  }
  
  
}

  void loop() 
  {
    
    
    if(Serial.available()>0)
      {
        char dato= Serial.read();
          
          if(dato=='B')
            {
              girarBaseDerecha();
            }
            
          if(dato=='b')
            {
              girarBaseIzquierda();
            }
          
          if(dato=='H')
            {
              subirHombro();
            }
            
           if(dato=='h')
            {
             bajarHombro(); 
            }
            
           if(dato=='C')
             {
               levantarCodo();
             }
            
           if(dato=='c')
             {
               bajarCodo();
             }
  
          if(dato=='P')
             {
               abrirPinza();
             }
            
           if(dato=='p')
             {
               cerrarPinza();
             }
             
           if(dato=='i')
             {
               posicionInicial();
             }
             
            if(dato=='r')
             {
               recogerFicha();
             }
             
            if(dato=='1')
             {
               primeraPosicion();
             }
             
              if(dato=='2')
             {
               segundaPosicion();
             }
             
              if(dato=='3')
             {
               terceraPosicion();
             }
                          
             if(dato=='4')
             {
               cuartaPosicion();
             }
             
              if(dato=='5')
             {
              quintaPosicion();
             }
             
              if(dato=='6')
             {
              sextaPosicion();
             }
             
             if(dato=='7')
             {
               septimaPosicion();
             }

             if(dato=='8')
             {
               octavaPosicion();
             }
             
              if(dato=='9')
             {
               novenaPosicion();
             }
             
             if(dato=='w')
             {
               happy();
             }
        
        
      }
  }

Download me
Autor: sistemasymicros
25 proyectos 1 seguidores 0 siguiendo

Ingeniero en electronica, desarrollador de software. Desarrollo de proyectos con microcontroladores.

COMENTARIOS
Para publicar un comentario debes