Robot Arm Tic-Tac-Toe: Now Picking Its Own Pieces

Thumbnail from the Robot arm plays tic tac toe video on the CIAOPS Labs YouTube channel

I’ve posted a short video of my robot arm playing tic-tac-toe, and it’s a good snapshot of where the project sits right now. It runs a little over three minutes and shows the arm playing crosses against a human. You can watch it here:

What the arm is doing now

The big step since my earlier posts is that the arm now picks up each of its pieces from a tray at the side of the board. For each move it collects its own piece from that tray, carries it over and places it in the chosen square.

The rest of the setup will be familiar if you have followed along:

  • An Arduino UNO R4 runs the arm code and drives the servos.
  • A web page served by the arm shows each move as the game progresses, and lets the human pick their move.
  • Gemini handles the decision about where the arm moves next.
  • Calibration options on the same web page let me fine-tune positions when the arm isn’t quite where it should be.

I covered the early groundwork in teaching the arm where the board is and the decision logic in playing a full game with minimax and Gemini. In the current project code, minimax works out the equally best moves and Gemini chooses among those. That keeps the move choice sensible. It doesn’t make the mechanics perfect, as the video shows.

The web page matters more than it might seem. It gives the human a simple way to choose their move, and it shows each move as the game goes along. When something goes wrong on the board, having the game state visible on a screen makes it much easier to tell whether the problem was the decision or the mechanics.

The missed pickup

If you watch closely, you’ll notice the arm misses picking up the last piece from the tray. That’s the honest state of a hobby build. The game logic can choose a perfectly good square and the arm can still come up empty if the gripper doesn’t close on the piece properly.

The fix is a minor adjustment so the gripper actually grabs the piece. This is exactly why the calibration options exist on the arm’s web page. Small changes to positions and gripper settings are what turn a mostly working arm into a reliable one.

Why the tray matters

Picking from a tray changes the arm’s job. Placing a piece on the board is only half the move. The arm also has to reach the piece, grip it securely, lift it clear and carry it across without dropping it. Each of those steps adds another place where a few millimetres or a few degrees matter.

That is also what makes it satisfying. When the arm collects its own piece and drops it into the right square, the whole loop feels much closer to playing a real opponent.

Code and next steps

The firmware, the companion camera project and the 3D models for the board and pieces are all in my tic-tac-toe project on GitHub. The immediate job is tuning that gripper so every pickup from the tray is clean. After that, it’s about running more games and seeing where else small calibration tweaks pay off.

If you are building something similar, my advice is simple: expect the logic to be the easy part. Getting a physical arm to grab a small piece the same way every time is where most of the real work hides.

ACEBOTT ESP32 Smart Car Starter Kit with Mecanum Wheel

Screenshot 2025-08-28 080437

In my on going quest to get a camera working on a robot car and failing with an Arducam, I cam across an existing kit that has an add on extra of a camera. It is the:

ACEBOTT ESP32 Smart Car Starter Kit with Mecanum Wheel

with

ACEBOTT ESP32 Camera Expansion pack for Smart Car

which is going to make achieving my goal much, much easier.

To get the Smart car working you’ll need to nuy some batteries:

1 x CR2025 for the Infra Red Controller

2 x 18650 to the motors and controller board

Assembling the car is pretty straight forward and the kit give you a few spare items for those that you invariably drop on the floor and lose, which is nice. The main challenge I had was with the wiriing. It is always a good idea of take a photo of the components , both sides, BEFORE you assemble them so you can read the pin settings. Case in point, here is the Ultrasonic senor after I had to disassemble it to get the pin settings.

Screenshot 2025-08-28 081429

Hopefully, that saves someone else having to do same.

Here are some more I took of the motor shield board because reading the numbers for the connectors was challenging.

Screenshot 2025-08-28 081600

Screenshot 2025-08-28 081753

With everything finally assembled and powered up I wanted to wire some code to test all the sensors were working correctly. I used this for my tests:

https://github.com/directorcia/Azure/blob/master/Iot/Acebott/Smartcar/diag.cpp

It will flash the LEDs, move the servo for the ultrasonic sensor, test the IR receiver, play tunes on the buzzer and test all the wheels, forwards and backwards for you.

All teh driver files and the instructions can be downloaded here. This will give you everything you need for all the Smartcar kits and add ons.

My next step will be to code the Smartcar so that it moves in response to commands sent to it via the Infra Red controller. Stay tunes.

Robot with distance

As I detailed in a previous post:

Mecanum motion

I had my robot moving and taking commands from an Internet based dashboard. The missing piece was to get the distance sensor operational, which I have now achieved.

I firstly need to print a mount to allow the distance sensor to be mounted to the buggy frame. I have uploaded that to the CIAOPSLabs repo here:

https://github.com/directorcia/ciaopslabs/blob/main/3dprint/mounts/VL53L0X-distance.stl

image

With the VL53L0X sensor now mounted and connected to the processor the layout now looked like the above image.

Basically, the motor controller, distance sensor and LCD display all communicate with the ESP32-S2 processor via the SDA/SCL bus. They achieve this by all being on a different address.

It was also important to ensure that I connected up the wheel in a know sequence because to drive the mecanum motion I needed to turn different wheels to make it move in certain directions per:

I’ve uploaded the initial code with it all working here:

https://github.com/directorcia/ciaopslabs/blob/main/Projects/14/moveanddistance-v1.c

The commands on the keyboard are:

image

1 = Left forward 45

2 = Forward

3 = Right forward 45

4 = Left 90

5 = Stop/Start

6 = Right 90

7 = Left back 45

8 = Back

9 = Right back 45

* = Slower

0 = Spin on the spot

# = Faster

As the robot moves it displays the distance on the LCD display like so:

image

The robot starts with speed = 0 (i.e. stationery). You press 5 to set the speed to 100 but it will not yet move until you give it a direction. If you now press 2, the robot will move forward at a speed of 100. You can then happy go along changing directions via the keypad. If you press 5 again, the robot will stop moving.

With all this now working, the next update will be for the robot to use the distance sensor to determine how far away it is from object (at the front), slow and stop if necessary to avoid hitting these objects.

I want to also optimise the code to make it more responsive if I can and I’ll post the updates here and to the CIAOPSLabs repo when I get it all working.

Beyond that I’m still trying to decide what to get the robot to do? If you have any suggestions, let me know but I’m kind of thinking that the robot needs to have ‘vision’ next!

New chassis

image

I’ve invested in a new chassis for my robot creations. This is the one I opted for:

Mecanum Wheel Chassis Car Kit with TT Motor, Aluminum Alloy Frame, Smart Car Kit for DIY Education Robot Car Kit

from Amazon. It is great quality, strong and well made. Has lots of connection options and the right size for what I want. It is also robust enough to survive the inevitable ‘incidents’ it will no doubt have along the way. In short, I think it is great value for money and very professionally made.

As you can see from the above picture, I have managed to put it together, even though it didn’t come with assembly instructions. Those I found here:

https://www.hiwonder.com/products/mecanum-wheel-chassis-car

and specifically on this YouTube video – https://youtu.be/WMQ-PyM-PNE

The motor connections are JST 2-pin female connectors so I have also ordered these:

JST PH 2-Pin Cable – Male Header 200mm

to allow easy connection to the motor driver I’ve already played with here:

https://blog.ciaops.com/2023/07/12/iot-motors/

Once I get all that I can start putting together the controllers and then start writing the code to make it actually move about.

Stay tuned.