Components and supplies
Robotic Arm with 6DOF - Lewansoul model X-Arm
Arduino Mega 2560
Nylon spacers (for board mounting)
Enclosure Plastic 5.5" (L) x 3.25" (W) x 1/5" (H)
Nylon nuts (for mounting board)
Connector DB9 - Female Plug
BSIRI TicTacToe Classic Board Games Noughts and Crosses
Female Header 4 position 0.1" spacing
Nylon screws 4-40 size (for mounting board)
4 x 4 Matrix Array 16 Key Membrane Switch Keypad Keyboard for Arduino
Connector - DB9 Male Socket
Tools and machines
Soldering iron (generic)
Project description
Code
tic-tac-toe sketch with robotic arm and keypad input
arduino
1// 2//BobN2Tech 03-22-18 add Xarm code for robotic control and Keypad input code 3//Thanks to https://github.com/klauscam/ArduinoTicTacToe for the tic-tac-toe algorithm 4//this code requires mega2560 which uses serial port 3 (serial3) to control the Lewansoul xarm 5//note: actiongroups 0-8 must be downloaded to the xarm controller prior 6//to using this program. Action group numbers 0 to 8 represent the board positions that 7//will be placed the moved piece. Initially has to be done manually (train the x-arm) to determine each board position 8//where the xarm will place the computer move piece. 9//action group 100 is preloaed for the initial position of the arm (recommend standing up) 10//action group 9 is for moving the arm as computer winning game - does some fancy gyration 11//optional action group 10 is for a draw - does some gyration 12//optional action group 11 is for a losing - does some humble gesture. 13//action group 12 is places arm into position where it will get the "O" pieces 14//The computer will never lose! 15// 16int difficulty=8; 17//xarm 18#include <LobotServoController.h> 19//Not using software serial 20//#define rxPin 2 //software serial 21//#define txPin 3 //software serial 22 23 24//SoftwareSerial mySerial(rxPin, txPin); 25//LobotServoController myse(mySerial); 26 27//hardware serial - use only if not using serial0 ow it conflicts 28 LobotServoController myse(Serial3); 29 30 const int speed = 100; //percent of action speed set in group. 100 = 100% = same speed as programmed, 50 = 1/2 speed, 200 = twice speed 31 int lastComputerMove = -1; 32 bool xarmConnected = false; 33 34//keypad 35#include <Keypad.h> 36 37const byte ROWS = 4; //four rows 38const byte COLS = 4; //four columns 39//define the cymbols on the buttons of the keypads 40char hexaKeys[ROWS][COLS] = { 41 {'1','2','3','A'}, 42 {'4','5','6','B'}, 43 {'7','8','9','C'}, 44 {'*','0','#','D'} 45}; 46byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad 47byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad 48char customKey; 49//initialize an instance of class NewKeypad 50Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 51// 52 53void setup(){ 54 Serial.begin(9600); 55 while(!Serial); 56 digitalWrite(13,HIGH); 57 Serial3.begin(9600); 58 while(!Serial3); 59 //xarm code 60// 61 int moveNo = 0; 62 pinMode(13,OUTPUT); 63 // mySerial.begin(9600); 64 // while(!mySerial); 65 // digitalWrite(13,HIGH); 66 67 68//check if xarm is connected - send the initial positon 69 myse.runActionGroup(100,1); 70 71 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 72 { 73 Serial.println("Xarm is connected"); 74 digitalWrite(13, LOW); 75 xarmConnected = true; 76 } 77 else 78 Serial.println("X-Arm not connected"); 79 80 //test - change to loop for 9 positions 81 82 if (xarmConnected) 83 { 84 85 86 for (int i = 0;i <9; i++) 87 { 88 myse.setActionGroupSpeed(i,speed); //Set the running speed of i action group at % speed of programmed 89 delay (1000); 90 //optional test all action groups are working 91 // Serial.println("xarm move to position " + String(i)); 92 // myse.runActionGroup(i,1); 93 // delay(3000); 94 95 } 96 //optional 97 // myse.setActionGroupSpeed(100,speed); //Set the running speed of No.100 action group at 1 sec 98 // delay(1000); 99 100 //put arm back into stand up as initial position (assume group 100) 101 102 // myse.runActionGroup(100,1); 103 104 // delay(2000); 105 106 xarmMove (12); //put arm into position for getting the pieces 107 108 delay (5000); 109// 110 } 111} 112 113 114 115char displayChar(int c) { 116 switch(c) { 117 case -1: 118 return 'X'; 119 case 0: 120 return ' '; 121 case 1: 122 return 'O'; 123 } 124} 125 126void draw(int board[9]) { 127 Serial.print(" ");Serial.print(displayChar(board[0])); Serial.print(" | ");Serial.print(displayChar(board[1])); Serial.print(" | ");Serial.print(displayChar(board[2])); Serial.println(" "); 128 Serial.println("---+---+---"); 129 Serial.print(" ");Serial.print(displayChar(board[3])); Serial.print(" | ");Serial.print(displayChar(board[4])); Serial.print(" | ");Serial.print(displayChar(board[5])); Serial.println(" "); 130 Serial.println("---+---+---"); 131 Serial.print(" ");Serial.print(displayChar(board[6])); Serial.print(" | ");Serial.print(displayChar(board[7])); Serial.print(" | ");Serial.print(displayChar(board[8])); Serial.println(" "); 132} 133 134int win(const int board[9]) { 135 //list of possible winning positions 136 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}}; 137 int winPos; 138 for(winPos = 0; winPos < 8; ++winPos) { 139 if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]] && board[wins[winPos][0]] == board[wins[winPos][2]]) 140 return board[wins[winPos][2]]; 141 } 142 return 0; 143} 144 145int minimax(int board[9], int player, int depth) { 146 //check the positions for players 147 int winner = win(board); 148 if(winner != 0) return winner*player; 149 150 int move = -1; 151 int score = -2; 152 int i; 153 for(i = 0; i < 9; ++i) { 154 155 if(board[i] == 0) { 156 board[i] = player; 157 int thisScore=0; 158 if (depth<difficulty){ 159 thisScore = -minimax(board, player*-1,depth+1); 160 } 161 162 if(thisScore > score) { 163 score = thisScore; 164 move = i; 165 166 167 } 168 //choose the worst move for opponent 169 board[i] = 0; 170 } 171 } 172 if(move == -1) return 0; 173 return score; 174 175} 176 177void computerMove(int board[9]) 178 { 179 int move = -1; 180 int score = -2; 181 int i; 182 for(i = 0; i < 9; ++i) { 183 if(board[i] == 0) { 184 board[i] = 1; 185 int tempScore = -minimax(board, -1, 0); 186 board[i] = 0; 187 if(tempScore > score) { 188 score = tempScore; 189 move = i; 190 lastComputerMove = i; 191 } 192 } 193 } 194 //returns a score based on minimax tree at a given node. 195 board[move] = 1; 196} 197 198void playerMove(int board[9]) 199 { 200 int move = 0; 201 int bmove =0; 202 String smove; 203 204 do { 205 206 207 208 // Get value from custom keypad but start with keypad 1 = board 0; 209 Serial.println("\ 210Input move ([1..9]): "); 211 while ((customKey = customKeypad.getKey())== NO_KEY) 212 {delay(100);} 213 214 Serial.println(customKey); 215 //convert to string so can convert char to integer - 216 smove = (String)customKey; 217 bmove = smove.toInt()-1; //use keypad so will start with numbers 1-9 to correspond to physical board layout 218 move = bmove; 219 // 220 221 Serial.println("\ 222"); 223 } while ((move >= 9 || move < 0) || board[move] != 0); 224 board[move] = -1; 225} 226 227void xarmMove (int action) 228{ 229 if (!xarmConnected) 230 return; 231 232 myse.runActionGroup(action,1); //run action group once for each move 233 234//test to get status while its running and do other things 235 Serial.println("Start RUNNING at " + String(millis())); //show total time 236 237 while (myse.isRunning()) //RAC 238 { 239 240 // Serial.println("IS STILL RUNNING" + String(millis())); //show total time 241 myse.receiveHandle(); //must include this, otherwise will never leave this loop 242 243 } 244 245 Serial.println("Action Completed at " + String(millis())); 246 247 248 249 Serial.println("FINISH XARM MOVE"); 250 251} 252 253 254void loop(){ 255 int board[9] = {0,0,0,0,0,0,0,0,0}; 256 //x-arm Play only 1, playing 2 does not work correctly 257 // Serial.println("Would you like to play X(1) or O(2)?"); 258 Serial.println("Press 1 to start playing - you are 'X' and Computer is 'O'"); 259/* get input from computer keyboard 260 while(Serial.available()==0) 261 { 262 delay(100); 263 } 264 265 266 int player=Serial.parseInt(); 267 Serial.println(player); 268*/ 269 270 271 // Get value from custom keypad ; 272 int player; 273 String s; 274 while ((customKey = customKeypad.getKey())== NO_KEY) 275 {delay(100);} 276 277 Serial.println(customKey); 278 //convert to string so can convert char to integer 279 s = (String)customKey; 280 player = s.toInt(); 281 // 282 283 284 unsigned turn; 285 for(turn = 0; turn < 9 && win(board) == 0; ++turn) { 286 if((turn+player) % 2 == 0) 287 { 288 computerMove(board); 289 290 291 Serial.println("xarm move is " + String(lastComputerMove)); 292 293 if (lastComputerMove != -1 & lastComputerMove < 9) 294 xarmMove (lastComputerMove); //action groups index start at 0 295 } 296 else 297 { 298 draw(board); 299 playerMove(board); 300 } 301 } 302 switch(win(board)) { 303 case 0: 304 Serial.println("It's a draw.\ 305"); 306 //send the initial positon 307 xarmMove (12); 308 break; 309 case 1: 310 draw(board); 311 Serial.println("You lose.\ 312"); 313 xarmMove (9); 314 break; 315 case -1: 316 Serial.println("You win!\ 317"); 318 xarmMove (11); 319 break; 320 } 321} 322
tic-tac-toe sketch with robotic arm and keypad input
arduino
1// 2//BobN2Tech 03-22-18 add Xarm code for robotic control and Keypad input code 3//Thanks to https://github.com/klauscam/ArduinoTicTacToe for the tic-tac-toe algorithm 4//this code requires mega2560 which uses serial port 3 (serial3) to control the Lewansoul xarm 5//note: actiongroups 0-8 must be downloaded to the xarm controller prior 6//to using this program. Action group numbers 0 to 8 represent the board positions that 7//will be placed the moved piece. Initially has to be done manually (train the x-arm) to determine each board position 8//where the xarm will place the computer move piece. 9//action group 100 is preloaed for the initial position of the arm (recommend standing up) 10//action group 9 is for moving the arm as computer winning game - does some fancy gyration 11//optional action group 10 is for a draw - does some gyration 12//optional action group 11 is for a losing - does some humble gesture. 13//action group 12 is places arm into position where it will get the "O" pieces 14//The computer will never lose! 15// 16int difficulty=8; 17//xarm 18#include <LobotServoController.h> 19//Not using software serial 20//#define rxPin 2 //software serial 21//#define txPin 3 //software serial 22 23 24//SoftwareSerial mySerial(rxPin, txPin); 25//LobotServoController myse(mySerial); 26 27//hardware serial - use only if not using serial0 ow it conflicts 28 LobotServoController myse(Serial3); 29 30 const int speed = 100; //percent of action speed set in group. 100 = 100% = same speed as programmed, 50 = 1/2 speed, 200 = twice speed 31 int lastComputerMove = -1; 32 bool xarmConnected = false; 33 34//keypad 35#include <Keypad.h> 36 37const byte ROWS = 4; //four rows 38const byte COLS = 4; //four columns 39//define the cymbols on the buttons of the keypads 40char hexaKeys[ROWS][COLS] = { 41 {'1','2','3','A'}, 42 {'4','5','6','B'}, 43 {'7','8','9','C'}, 44 {'*','0','#','D'} 45}; 46byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad 47byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad 48char customKey; 49//initialize an instance of class NewKeypad 50Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 51// 52 53void setup(){ 54 Serial.begin(9600); 55 while(!Serial); 56 digitalWrite(13,HIGH); 57 Serial3.begin(9600); 58 while(!Serial3); 59 //xarm code 60// 61 int moveNo = 0; 62 pinMode(13,OUTPUT); 63 // mySerial.begin(9600); 64 // while(!mySerial); 65 // digitalWrite(13,HIGH); 66 67 68//check if xarm is connected - send the initial positon 69 myse.runActionGroup(100,1); 70 71 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 72 { 73 Serial.println("Xarm is connected"); 74 digitalWrite(13, LOW); 75 xarmConnected = true; 76 } 77 else 78 Serial.println("X-Arm not connected"); 79 80 //test - change to loop for 9 positions 81 82 if (xarmConnected) 83 { 84 85 86 for (int i = 0;i <9; i++) 87 { 88 myse.setActionGroupSpeed(i,speed); //Set the running speed of i action group at % speed of programmed 89 delay (1000); 90 //optional test all action groups are working 91 // Serial.println("xarm move to position " + String(i)); 92 // myse.runActionGroup(i,1); 93 // delay(3000); 94 95 } 96 //optional 97 // myse.setActionGroupSpeed(100,speed); //Set the running speed of No.100 action group at 1 sec 98 // delay(1000); 99 100 //put arm back into stand up as initial position (assume group 100) 101 102 // myse.runActionGroup(100,1); 103 104 // delay(2000); 105 106 xarmMove (12); //put arm into position for getting the pieces 107 108 delay (5000); 109// 110 } 111} 112 113 114 115char displayChar(int c) { 116 switch(c) { 117 case -1: 118 return 'X'; 119 case 0: 120 return ' '; 121 case 1: 122 return 'O'; 123 } 124} 125 126void draw(int board[9]) { 127 Serial.print(" ");Serial.print(displayChar(board[0])); Serial.print(" | ");Serial.print(displayChar(board[1])); Serial.print(" | ");Serial.print(displayChar(board[2])); Serial.println(" "); 128 Serial.println("---+---+---"); 129 Serial.print(" ");Serial.print(displayChar(board[3])); Serial.print(" | ");Serial.print(displayChar(board[4])); Serial.print(" | ");Serial.print(displayChar(board[5])); Serial.println(" "); 130 Serial.println("---+---+---"); 131 Serial.print(" ");Serial.print(displayChar(board[6])); Serial.print(" | ");Serial.print(displayChar(board[7])); Serial.print(" | ");Serial.print(displayChar(board[8])); Serial.println(" "); 132} 133 134int win(const int board[9]) { 135 //list of possible winning positions 136 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}}; 137 int winPos; 138 for(winPos = 0; winPos < 8; ++winPos) { 139 if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]] && board[wins[winPos][0]] == board[wins[winPos][2]]) 140 return board[wins[winPos][2]]; 141 } 142 return 0; 143} 144 145int minimax(int board[9], int player, int depth) { 146 //check the positions for players 147 int winner = win(board); 148 if(winner != 0) return winner*player; 149 150 int move = -1; 151 int score = -2; 152 int i; 153 for(i = 0; i < 9; ++i) { 154 155 if(board[i] == 0) { 156 board[i] = player; 157 int thisScore=0; 158 if (depth<difficulty){ 159 thisScore = -minimax(board, player*-1,depth+1); 160 } 161 162 if(thisScore > score) { 163 score = thisScore; 164 move = i; 165 166 167 } 168 //choose the worst move for opponent 169 board[i] = 0; 170 } 171 } 172 if(move == -1) return 0; 173 return score; 174 175} 176 177void computerMove(int board[9]) 178 { 179 int move = -1; 180 int score = -2; 181 int i; 182 for(i = 0; i < 9; ++i) { 183 if(board[i] == 0) { 184 board[i] = 1; 185 int tempScore = -minimax(board, -1, 0); 186 board[i] = 0; 187 if(tempScore > score) { 188 score = tempScore; 189 move = i; 190 lastComputerMove = i; 191 } 192 } 193 } 194 //returns a score based on minimax tree at a given node. 195 board[move] = 1; 196} 197 198void playerMove(int board[9]) 199 { 200 int move = 0; 201 int bmove =0; 202 String smove; 203 204 do { 205 206 207 208 // Get value from custom keypad but start with keypad 1 = board 0; 209 Serial.println("\ 210Input move ([1..9]): "); 211 while ((customKey = customKeypad.getKey())== NO_KEY) 212 {delay(100);} 213 214 Serial.println(customKey); 215 //convert to string so can convert char to integer - 216 smove = (String)customKey; 217 bmove = smove.toInt()-1; //use keypad so will start with numbers 1-9 to correspond to physical board layout 218 move = bmove; 219 // 220 221 Serial.println("\ 222"); 223 } while ((move >= 9 || move < 0) || board[move] != 0); 224 board[move] = -1; 225} 226 227void xarmMove (int action) 228{ 229 if (!xarmConnected) 230 return; 231 232 myse.runActionGroup(action,1); //run action group once for each move 233 234//test to get status while its running and do other things 235 Serial.println("Start RUNNING at " + String(millis())); //show total time 236 237 while (myse.isRunning()) //RAC 238 { 239 240 // Serial.println("IS STILL RUNNING" + String(millis())); //show total time 241 myse.receiveHandle(); //must include this, otherwise will never leave this loop 242 243 } 244 245 Serial.println("Action Completed at " + String(millis())); 246 247 248 249 Serial.println("FINISH XARM MOVE"); 250 251} 252 253 254void loop(){ 255 int board[9] = {0,0,0,0,0,0,0,0,0}; 256 //x-arm Play only 1, playing 2 does not work correctly 257 // Serial.println("Would you like to play X(1) or O(2)?"); 258 Serial.println("Press 1 to start playing - you are 'X' and Computer is 'O'"); 259/* get input from computer keyboard 260 while(Serial.available()==0) 261 { 262 delay(100); 263 } 264 265 266 int player=Serial.parseInt(); 267 Serial.println(player); 268*/ 269 270 271 // Get value from custom keypad ; 272 int player; 273 String s; 274 while ((customKey = customKeypad.getKey())== NO_KEY) 275 {delay(100);} 276 277 Serial.println(customKey); 278 //convert to string so can convert char to integer 279 s = (String)customKey; 280 player = s.toInt(); 281 // 282 283 284 unsigned turn; 285 for(turn = 0; turn < 9 && win(board) == 0; ++turn) { 286 if((turn+player) % 2 == 0) 287 { 288 computerMove(board); 289 290 291 Serial.println("xarm move is " + String(lastComputerMove)); 292 293 if (lastComputerMove != -1 & lastComputerMove < 9) 294 xarmMove (lastComputerMove); //action groups index start at 0 295 } 296 else 297 { 298 draw(board); 299 playerMove(board); 300 } 301 } 302 switch(win(board)) { 303 case 0: 304 Serial.println("It's a draw.\ 305"); 306 //send the initial positon 307 xarmMove (12); 308 break; 309 case 1: 310 draw(board); 311 Serial.println("You lose.\ 312"); 313 xarmMove (9); 314 break; 315 case -1: 316 Serial.println("You win!\ 317"); 318 xarmMove (11); 319 break; 320 } 321} 322
Downloadable files
Tic-tac-toe schematic
Tic-tac-toe schematic
Tic-tac-toe schematic
Tic-tac-toe schematic
Tic-Tac-toe Breadboard
Tic-Tac-toe Breadboard
Comments
Only logged in users can leave comments
bobn2tech
0 Followers
•0 Projects
Table of contents
Intro
5
0