内容目录

跟一个用Arduino Mega 2560控制的机械臂下XO棋(`・ω・´)

关于这个项目:

我想用 Lewansoul’s 机械臂 (X-arm) ( www.lewansoul.com ) 做个真实版的XO棋, 以说明手臂的运动,以及在游戏环境中的拾取和放置物体位置的控制。

机器人臂由Arduino Mega 2560控制,玩家(“X”)的输入由使用键盘1-9的膜键盘确认,以表示棋盘位置1-9中的其中一个。

我在Github上找到一个XO棋的项目, 它使用Mimax算法来确定玩家在每次移动后计算机应该做什么动作。我在这个程序中添加了使用X-arm控制制器中存储的动作组来控制X臂位置的代码,用于棋盘1-9上每个可能的位置。

因此,对于进行下一个位置(例如,位置4)的特定动作,X-arm将被发送一个动作组命令“4”来拾取棋子(X-arm棋子“O”),并将其放置在棋盘上”4″的位置。见下面的视频:

机械臂控制电路图:

 机械臂控制输入代码:

机械臂控制输入 (下载81 )
//
//BobN2Tech 03-22-18 add Xarm code for robotic control and Keypad input code
//Thanks to https://github.com/klauscam/ArduinoTicTacToe for the tic-tac-toe algorithm
//this code requires mega2560 which uses serial port 3 (serial3) to control the Lewansoul xarm
//note: actiongroups 0-8 must be downloaded to the xarm controller prior
//to using this program. Action group numbers 0 to 8 represent the board positions that
//will be placed the moved piece. Initially has to be done manually (train the x-arm) to determine each board position
//where the xarm will place the computer move piece.
//action group 100 is preloaed for the initial position of the arm (recommend standing up)
//action group 9 is for moving the arm as computer winning game - does some fancy gyration
//optional action group 10 is for a draw - does some gyration
//optional action group 11 is for a losing - does some humble gesture. 
//action group 12 is places arm into position where it will get the "O" pieces
//The computer will never lose!
//
int difficulty=8;
//xarm
#include <LobotServoController.h>
//Not using software serial
//#define rxPin 2  //software serial
//#define txPin 3 //software serial


//SoftwareSerial mySerial(rxPin, txPin);
//LobotServoController myse(mySerial);

//hardware serial - use only if not using serial0 ow it conflicts
 LobotServoController myse(Serial3);
 
 const int speed = 100; //percent of action speed set in group. 100 = 100% = same speed as programmed, 50 = 1/2 speed, 200 = twice speed
 int lastComputerMove = -1;
 bool xarmConnected = false;

//keypad
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
char customKey;
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 
//
 
void setup(){
  Serial.begin(9600);
   while(!Serial);
     digitalWrite(13,HIGH);
  Serial3.begin(9600); 
   while(!Serial3);
 //xarm code
//
 int moveNo = 0;
  pinMode(13,OUTPUT);
 // mySerial.begin(9600);
 //  while(!mySerial);
  //   digitalWrite(13,HIGH);


//check if xarm is connected - send the initial positon
    myse.runActionGroup(100,1);
 
   if(myse.waitForStopping(5000))  //Waiting for the action group is completed, or be stopped or timeout. The unit of the parameter(timeout) is milliscond. finish or stop, you will get a true. timeout, you will get a false
     {
       Serial.println("Xarm is connected");
       digitalWrite(13, LOW);
       xarmConnected = true;
     }
     else
      Serial.println("X-Arm not connected"); 
  
  //test - change to loop for 9 positions
 
  if (xarmConnected)
  {
  
  
  for (int i = 0;i <9; i++)
  {
      myse.setActionGroupSpeed(i,speed); //Set the running speed of i action group at % speed of programmed
      delay (1000);
   //optional test all action groups are working
   //   Serial.println("xarm move to position " + String(i));       
   //  myse.runActionGroup(i,1);
   // delay(3000);
 
  }
  //optional
   // myse.setActionGroupSpeed(100,speed); //Set the running speed of No.100 action group at 1 sec
   // delay(1000);
  
  //put arm back into stand up as initial position (assume group 100)

  //  myse.runActionGroup(100,1);

 //  delay(2000);

     xarmMove (12);   //put arm into position for getting the pieces

   delay (5000);
//
 }
}



char displayChar(int c) {
    switch(c) {
        case -1:
            return 'X';
        case 0:
            return ' ';
        case 1:
            return 'O';
    }
}

void draw(int board[9]) {
    Serial.print(" ");Serial.print(displayChar(board[0])); Serial.print(" | ");Serial.print(displayChar(board[1])); Serial.print(" | ");Serial.print(displayChar(board[2])); Serial.println(" ");
    Serial.println("---+---+---");
    Serial.print(" ");Serial.print(displayChar(board[3])); Serial.print(" | ");Serial.print(displayChar(board[4])); Serial.print(" | ");Serial.print(displayChar(board[5])); Serial.println(" ");
    Serial.println("---+---+---");
    Serial.print(" ");Serial.print(displayChar(board[6])); Serial.print(" | ");Serial.print(displayChar(board[7])); Serial.print(" | ");Serial.print(displayChar(board[8])); Serial.println(" ");
}

int win(const int board[9]) {
    //list of possible winning positions
    unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
    int winPos;
    for(winPos = 0; winPos < 8; ++winPos) {
        if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]] && board[wins[winPos][0]] == board[wins[winPos][2]])
            return board[wins[winPos][2]];
    }
    return 0;
}

int minimax(int board[9], int player, int depth) {
    //check the positions for players
    int winner = win(board);
    if(winner != 0) return winner*player;

    int move = -1;
    int score = -2;
    int i;
    for(i = 0; i < 9; ++i) {
     
        if(board[i] == 0) {
            board[i] = player;
            int thisScore=0;
            if (depth<difficulty){
              thisScore = -minimax(board, player*-1,depth+1);
            }
            
            if(thisScore > score) {
                score = thisScore;
                move = i; 
    
                
            }
            //choose the worst move for opponent
            board[i] = 0;
        }
    }
    if(move == -1) return 0;
    return score;
   
}

void computerMove(int board[9]) 
  {
    int move = -1;
    int score = -2;
    int i;
    for(i = 0; i < 9; ++i) {
        if(board[i] == 0) {
            board[i] = 1;
            int tempScore = -minimax(board, -1, 0);
            board[i] = 0;
            if(tempScore > score) {
                score = tempScore;
                move = i;
                lastComputerMove = i;
            }
        }
    }
    //returns a score based on minimax tree at a given node.
    board[move] = 1;
}

void playerMove(int board[9])
  {
    int move = 0;
    int bmove =0;
    String smove;
    
    do {


        
      // Get value from custom keypad but start with keypad 1 = board 0;
       Serial.println("\nInput move ([1..9]): ");
       while ((customKey = customKeypad.getKey())== NO_KEY)
       {delay(100);} 
      
      Serial.println(customKey);
      //convert to string so can convert char to integer -  
      smove = (String)customKey;
      bmove = smove.toInt()-1; //use keypad so will start with numbers 1-9 to correspond to physical board layout   
      move = bmove;
	//
	
     Serial.println("\n");
    } while ((move >= 9 || move < 0) || board[move] != 0);
    board[move] = -1;
}

void xarmMove (int action)
{
    if (!xarmConnected)
      return;
   
    myse.runActionGroup(action,1);  //run action group once for each move
 
//test to get status while its running and do other things
   Serial.println("Start RUNNING at " + String(millis()));  //show total time
   
   while (myse.isRunning()) //RAC 
   {
    
   // Serial.println("IS STILL RUNNING" + String(millis()));  //show total time
     myse.receiveHandle();       //must include this, otherwise will never leave this loop
     
   }

    Serial.println("Action Completed at " + String(millis()));  

 
     
     Serial.println("FINISH XARM MOVE");

}


void loop(){
    int board[9] = {0,0,0,0,0,0,0,0,0};
  //x-arm Play only 1, playing 2 does not work correctly
   // Serial.println("Would you like to play X(1) or O(2)?");
    Serial.println("Press 1 to start playing - you are 'X' and Computer is 'O'");  
/*  get input from computer keyboard
     while(Serial.available()==0)
    {
    delay(100);
     }

      
     int player=Serial.parseInt();
     Serial.println(player);
*/
    

    // Get value from custom keypad ;
       int player;
       String s;
       while ((customKey = customKeypad.getKey())== NO_KEY)
       {delay(100);} 
      
      Serial.println(customKey);
      //convert to string so can convert char to integer  
      s  = (String)customKey;
      player = s.toInt();
  //

    
    unsigned turn;
    for(turn = 0; turn < 9 && win(board) == 0; ++turn) {
        if((turn+player) % 2 == 0)
        {
            computerMove(board);
            
            
           Serial.println("xarm move is " + String(lastComputerMove));  
                         
           if (lastComputerMove != -1 & lastComputerMove < 9) 
              xarmMove (lastComputerMove);  //action groups index start at 0
        }
        else 
        {
            draw(board);
            playerMove(board);
        }
    }
    switch(win(board)) {
        case 0:
            Serial.println("It's a draw.\n");
            //send the initial positon
             xarmMove (12);
            break;
        case 1:
            draw(board);
            Serial.println("You lose.\n");
             xarmMove (9);
             break;
        case -1:
            Serial.println("You win!\n");
            xarmMove (11);
            break;
    }
}

原文链接: Arduino Project Hub

翻译: DaStudio

dastudio

By dastudio

You are not special.

发表评论