Project tutorial
Electronic Chessboard (4x4 Demo Prototype)

Electronic Chessboard (4x4 Demo Prototype) © GPL3+

Creative approach to building electronic chessboard upon RFID technology, Hall effect sensors, and Arduino Mega.

  • 1,016 views
  • 6 comments
  • 7 respects

Components and supplies

Necessary tools and machines

plexiglass
Glossy paper
wooden planks
Acrylic paint (dark green and creme) x2
10 mm round magnets
Pawn and Queen chess pieces
Soldering iron and soldering materials

Apps and online services

About this project

Hi makers,

I am Tahir Miriyev, 2018 graduate from Middle East Technical University, Ankara/ Turkey. I majored in Applied Mathematics, but I always loved making stuff, especially when it involved some handwork with electronics, design and programming. Thanks to a unique course on prototyping, offered at our department of Industrial Design, I got a chance to make something really interesting. The project can be treated as a Term Project, lasted for the duration of a whole semester (4 months). Students were assigned a task to find a creative approach to designing already existed products/demos and realize their ideas using Arduino microcontrollers and sensors. I was thinking about chess, and after doing some research on successful projects, I noticed that in previous projects makers basically used ready-set chess engines (where all moves of each figure were programmed in the core), along with Raspberry Pi, some MUXes, LEDs and reed switches. In my project, although, I decided to get rid of any external software in terms of a chess engine, and to find a creative solution for the Figure Recognition problem, using RFID reader, Hall effect sensors and Arduino Mega.

To put it simply, suppose you have a chessboard with a "brain"=microcontroller, and you have to make your board understand which figure you held in your hand and where you've placed it. This is the problem of Figure Recognition. Solution to this problem is trivial when you have a chess engine with all pieces standing on their initial positions on the board. Before I explain why it's so, let me make some remarks.

For those who are enthusiastic about how things work here, I have to make a clarification on why we need reed switches (or in my case, I used Hall effect sensors): if you place a magnet under each piece and pick it up from a square on the board (assuming that there is a reed switch under every square) due to the existence/non existence of the magnetic field above the sensor, you can make your controller understand whether there is/is not a piece standing on the square. However, it still doesn't tell microcontroller anything about exactly which piece is standing on the square. It only tells that there is/not a piece on a square. At this point, we are face to face with a Figure Recognition problem, which can be solved using a chess engine, with all pieces placed on their initial positions when the chess game starts. This way microcontroller "knows" where every piece stands right from the beginning, with all addresses fixed in the memory. Nevertheless, this brings us a huge limitation: you can't select, let's say, any number of pieces and place them randomly anywhere on the board and start analyzing the game. You always have to start from the beginning, all pieces should be on the board originally, as this is the only way for the microcontroller to track their locations once you lifted a piece and placed on some other square. In essence, this was the problem I noticed and decided to work toward.

My solution was quite simple, although creative. I placed an RFID reader on the front side of a board. Meanwhile, I attached not only a magnet under pieces but also an RFID tag, with each piece having a unique ID. Hence, before you place a figure on any desired square, you can first hold the piece close to the RFID reader and let it read the ID, identify the piece, save it in the memory, and then you can place it wherever you want. Also, instead of using reed switches, in order to simplify the circuit design, I used Hall effect sensors, which work similarly, with the only difference of sending 0 or 1 to a microcontroller as a digital data, which signifies "there is" or "there is not" any piece on the square, respectively. I added LEDs as well (unfortunately not of the same color, didn't have ones), so that when you lift the piece, all square locations, where a lifted piece could be placed, will light on. Think of it as an educational practice for chess learners:)

Lastly, I would like to note that despite the fact I used several techniques, the project remains simple and understandable, not deeply worked out or over complicated. I didn't have enough time to proceed with 8x8 chessboard (also because 64 Hall effect sensors are costly in Turkey, I covered all expenses related to the projec), that's why I did 4x4 demo version with only two pieces tested: Pawn and Queen. Instead of using a chess engine, I wrote a source code for Arduino, which generates everything.

Before we pass to the step-by-step explanation of how the project was done, I would recommend to watch an illustrative video and get some intuitive idea on what I am talking about.

Note #1: One of the red LEDs (first in the row/ from left to right) burnt out, never mind.

Note #2: Although widely used, from my experience I can say that the RFID technology is not the best idea to use in DIY applications (of course if you have alternatives). Before everything worked, I did many trials with placing chess pieces close to the reader and waiting until it correctly reads the ID. Serial port should be set up for that because the way RFID reader reads the ID is just a headache. One should try by himself/herself in order to understand the issue.

Here is the list of all the tools I used for the project:

Electronic components:

  • Breadboard (x1)
  • Omnidirectional A1126LUA-T (IC-1126 SW OMNI 3-SIP ALLEGRO) Hall effect sensors (x16)
  • Basic 5 mm LEDs (x16)
  • Jumper wires
  • 125 kHz RFID Reader and Antenna (x1)
  • Arduino Mega (x1)
  • RFID 3M Tags (x2)

Other materials:

  • Plexiglass
  • Glossy paper
  • short Planks (wooden)
  • Acrylic paint (dark green and creme) x2
  • Thin cardboard
  • 10 mm round magnets (x2)
  • Pawn and Queen pieces
  • Soldering iron and soldering materials

Time to explain how things were made. Please follow the step-by-step description:

1. Take a 21x21 cm cardboard, as well as some extra cardboard to cut and glue the walls of the upper part of the board, in order to make 16 squares with A B C D 1 2 3 4 enumerated. Since cardboard is thin, you can stick 16 Hall effect sensors into each square, with 3 legs each and 16 LEDs with 2 legs each.

2. After you set components, you will need to do some soldering, to solder legs of Hall effect sensors and LEDs to jumper wires. At this point, I would recommend selecting colored wires in a smart way, so that you won't get confused with the + and - legs of LEDs, also VCC, GND and PIN legs of Hall effect sensors. Of course, one might print a PCB with sensors and even WS2812 type of LEDs already soldered, but I decided to keep the project simple and do some more "handwork". At this point, all you have to do is to prepare cords and sensors, on later stages following from Fritzing scheme you can see where you should attach the end of each wire. Shortly, some of them will go directly to the PINs on the Arduino Mega (there is enough of them on the Arduino), others to the breadboard and all GNDs can be soldered to a single piece of cord(making common ground) which later on should be connected to the GND on the Arduino board. One important note here: Hall effect sensors are OMNIDIRECTIONAL, which means it doesn't matter which pole of a magnet will be held close to the sensor, it will send 0 data while there is some magnetic field nearby and 1 when there is not, namely, magnet is away (further than lets say 5 sm) from the sensor.

3. Prepare similar 21x21 cm cardboard and fix the Arduino Mega and a long breadboard onto it. You can also cut 4 walls of any desired height from cardboard again, and glue them vertically with those two layers of 21x21 cm square boards. Then follow Fritzing Schematics to set things up. You can also set the RFID reader after you're done with LEDs and Hall effect sensors.

4. Test whether all LEDs and sensors work, by sending signals using basic codes. Don't avoid this step as it will let you test out whether everything works properly and pass to further construction of the board.

5. Prepare Pawn and Queen, with two magnets of a 10 cm radius attached below, as well as round RFID tags. Later on, you'll need to read IDs of those tags from Serial Screen on Arduino IDE.

6. If everything works great, you may start the main code and try things out!

7 (optional). You may do some artistic work with wood which will give your demo a more natural view. That's up to your will and imagination.

Here are some videos and photos from different stages:

Thank you for your attention! Test everything and be free to write in the comments about any kind of mistakes I missed, improvements, suggestions etc. Looking forward to hearing some opinions about the project.If you need any kind of assistance with the project, mail me (miriyevt@gmail.com) or add on Skype (tahir.miriyev9r1), so that we can schedule a conversation and discuss things in details. Best of luck!

Code

thinK_code.inoArduino
I tried to leave as many comments as I could, in order to make the process of code analysis understandable. To be honest, the logic might seem a bit complex from the first sight, but if you dig deeper into the logic of the code, it will look more comprehensive.

Note: Similar to the real chessboard, I abstractly numerated squares as A1, A2, A3, A4, B1, ..., C1, ... ,D1,.., D4. However, in the code, it's not practical to use this notation. Therefore I used arrays and represented squares as 00, 01, 02, 03,10,11,12,13,..., 32,33 respectively.
#include <SoftwareSerial.h>
SoftwareSerial RFID(11, 12);
//----------------------------------------------------------- START ---------------------------------------------------------------------------------------------
int empty_pos[2] ;
int figure_pos[2][2]; //thinking of a figure position as a matrix of two vectors(queen and pawn) with three entries(x pos, y pos, and value 1(queen), 2(pawn)
int new_id[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int id_type_matrix[4][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
int temp = 0;
int queen_id[14] = {2, 53, 65, 48, 48, 56, 51, 49, 55, 70, 65, 51, 52, 3};
int pawn_id[14] = {2, 53, 65, 48, 48, 56, 51, 56, 67, 49, 56, 52, 68, 3};
int temp_vect[2];
int count = 0;
int ID = 0;
int yeni_id[14]; 

//initial array matrix for hall-effect sensors
int hes_bool_matrix[4][4] ;


// list of Hall-effect sensors pins on Arduino
const int hes_00 = 44;
const int hes_01 = 45;
const int hes_02 = 46;
const int hes_03 = 47;
const int hes_10 = 48;
const int hes_11 = 49;
const int hes_12 = 50;
const int hes_13 = 2;
const int hes_20 = 3;
const int hes_21 = 4;
const int hes_22 = 5;
const int hes_23 = 6;
const int hes_30 = 7;
const int hes_31 = 8;
const int hes_32 = 9;
const int hes_33 = 10;


int hes_pin_matrix[4][4] =

{ {hes_00, hes_01, hes_02, hes_03},

  {hes_10, hes_11, hes_12, hes_13},

  {hes_20, hes_21, hes_22, hes_23},

  {hes_30, hes_31, hes_32, hes_33}
};

//LED pins
const int led_00 = 22;
const int led_01 = 23;
const int led_02 = 24;
const int led_03 = 25;
const int led_10 = 26;
const int led_11 = 27;
const int led_12 = 28;
const int led_13 = 29;
const int led_20 = 30;
const int led_21 = 31;
const int led_22 = 32;
const int led_23 = 33;
const int led_30 = 34;
const int led_31 = 35;
const int led_32 = 36;
const int led_33 = 37;


int led_matrix[4][4] =
{ {led_00, led_01, led_02, led_03},

  {led_10, led_11, led_12, led_13},

  {led_20, led_21, led_22, led_23},

  {led_30, led_31, led_32, led_33}
};


//----------------------------------------------------- SETUP AREA ---------------------------------------------------------------------------------

void setup() {

  RFID.begin(9600);
  Serial.begin(9600);


  //reading(input) modes for hall-effect sensors
  pinMode(hes_01, INPUT);
  pinMode(hes_02, INPUT);
  pinMode(hes_03, INPUT);
  pinMode(hes_00, INPUT);
  pinMode(hes_10, INPUT);
  pinMode(hes_11, INPUT);
  pinMode(hes_12, INPUT);
  pinMode(hes_13, INPUT);
  pinMode(hes_20, INPUT);
  pinMode(hes_21, INPUT);
  pinMode(hes_22, INPUT);
  pinMode(hes_23, INPUT);
  pinMode(hes_30, INPUT);
  pinMode(hes_31, INPUT);
  pinMode(hes_32, INPUT);
  pinMode(hes_33, INPUT);

  //writing(output) modes for LED pins
  pinMode(led_00, OUTPUT);
  pinMode(led_01, OUTPUT);
  pinMode(led_02, OUTPUT);
  pinMode(led_03, OUTPUT);
  pinMode(led_10, OUTPUT);
  pinMode(led_11, OUTPUT);
  pinMode(led_12, OUTPUT);
  pinMode(led_13, OUTPUT);
  pinMode(led_20, OUTPUT);
  pinMode(led_21, OUTPUT);
  pinMode(led_22, OUTPUT);
  pinMode(led_23, OUTPUT);
  pinMode(led_30, OUTPUT);
  pinMode(led_31, OUTPUT);
  pinMode(led_32, OUTPUT);
  pinMode(led_33, OUTPUT);
  
  read_tags(); delay(1000); 
  first_figure(); delay(1000);
  Serial.end(); 
  RFID.end(); delay(5000);
  Serial.begin(9600); delay(1000);
  RFID.begin(9600); delay(1000);  
  read_tags(); delay(5000);
  //RFID.flush(); // stops multiple reads
  second_figure(); delay(1000);
//  id_type_matrix[0][2] = 2;
//  id_type_matrix[2][1] = 1;
}
//---------------------------------------------------FUNCTIONS AREA------------------------------------------------------------
//----------------------------------------RFID ID Tracking and Figure Recognition-----------------------------------------------


boolean compare_ID(int aa[14], int bb[14])
{
  boolean ff = false;
  int fg = 0;
  for (int cc = 0 ; cc < 14 ; cc++)
  { if (aa[cc] == bb[cc])
    {
      fg++;
    }
  } if (fg == 14) {
    ff = true;
  }

  return ff;
}

int read_tags()
{
  Serial.println("Place the figure near to RFID reader");
  delay(5000);

  RFID.flush(); // stops multiple reads
  if (RFID.available() > 0) 
  {
    delay(300);
    for (int z = 0 ; z < 14 ; z++)
    {
      ID = RFID.read();
      new_id[z] = ID;
      Serial.println(new_id[z], DEC);
      delay(500);

    }  
  }

  Serial.println("ID reading is done ");
  
  ++count;
  delay(5000); //time to place the figure onto a board and the second one in front of a RFID reader

return new_id;
}

void first_figure() {

  if (compare_ID(new_id, queen_id) == true) {
    Serial.println("QUEEN IS DETECTED");
    for (int s = 0; s <= 3; s++) {
      for (int t = 0; t <= 3; t++) {
       
        if (digitalRead(hes_pin_matrix[s][t]) == 0) {
          id_type_matrix[s][t] = 1;
          temp_vect[0] = s;
          temp_vect[1] = t;
          Serial.print("Queen is placed onto:");
          Serial.print(s);
          Serial.println(t);
          digitalWrite(led_matrix[s][t],HIGH); delay(1000);
          digitalWrite(led_matrix[s][t],LOW);
          
        }
      }
    }
  }

  else if (compare_ID(new_id, pawn_id) == true) {
    Serial.println("PAWN IS DETECTED");
    for (int s = 0; s <= 3; s++) {
      for (int t = 0; t <= 3; t++) {
        if (digitalRead(hes_pin_matrix[s][t]) == 0) {
          id_type_matrix[s][t] = 2;
          temp_vect[0] = s;
          temp_vect[1] = t;
          Serial.print("Pawn is placed onto:");
          Serial.print(s);
          Serial.println(t);
          digitalWrite(led_matrix[s][t],HIGH); delay(1000);
          digitalWrite(led_matrix[s][t],LOW);
        }
      }
    }

  }
  else {
    Serial.println("Undefined figure ");
  }
}

void second_figure() {

  if (compare_ID(new_id, queen_id) == true) {
     Serial.println("QUEEN IS DETECTED");
    for (int s = 0; s <= 3; s++) {
      for (int t = 0; t <= 3; t++) {
        if (digitalRead(hes_pin_matrix[s][t]) == 0 && (s != temp_vect[0] || t != temp_vect[1])) {
          id_type_matrix[s][t] = 1;
          Serial.print("Queen is placed onto:");
          Serial.print(s);
          Serial.println(t);
          digitalWrite(led_matrix[s][t],HIGH); delay(1000);
          digitalWrite(led_matrix[s][t],LOW);
        }
      }
    }
  }

  else if (compare_ID(new_id, pawn_id) == true) {
    Serial.println("PAWN IS DETECTED");
    for (int s = 0; s <= 3; s++) {
      for (int t = 0; t <= 3; t++) {
        if (digitalRead(hes_pin_matrix[s][t]) == 0 && (s != temp_vect[0] || t != temp_vect[1])) {
          id_type_matrix[s][t] = 2;
          Serial.print("Pawn is placed onto:");
          Serial.print(s);
          Serial.println(t);
          digitalWrite(led_matrix[s][t],HIGH); delay(1000);
          digitalWrite(led_matrix[s][t],LOW);
        }
      }
    }
  }
}


//----------------------------------------------- FINDING FIGURES-------------------------------------------------------------------------

//extra function for turning leds off only when you place back the figure onto the board
void leds_off() {
  int i, j;
  for (i = 0; i <= 3; i++) {
    for (j = 0; j <= 3; j++) {
      digitalWrite(led_matrix[i][j], LOW);
    }
  }
}

//-------------------------------------------------MOVING QUEEN------------------------------------------------------------------------------------------------
void move_queen() {

  int i, j ;

  for (i = empty_pos[0]; i < 3;) {
    digitalWrite(led_matrix[++i][empty_pos[1]], HIGH); //light along a vertical line
  }   for (i = empty_pos[0]; i > 0;) {
    digitalWrite(led_matrix[--i][empty_pos[1]], HIGH);
  } for (i = empty_pos[1]; i < 3;) {
    digitalWrite(led_matrix[empty_pos[0]][++i], HIGH); //light along a horizontal line
  }
  for (i = empty_pos[1]; i > 0;) {
    digitalWrite(led_matrix[empty_pos[0]][--i], HIGH);
  }

  i = empty_pos[0];
  j = empty_pos[1];
  for (i = i - 3, j = j - 3; i <= 3, j <= 3; i++, j++) {
    if (i >= 0 && j >= 0 && i != empty_pos[0]) {
      Serial.print(i);
      Serial.println(j);
      digitalWrite(led_matrix[i][j], HIGH);
    }
  }
  i = empty_pos[0];
  j = empty_pos[1];
  for (i = i + 3, j = j - 3; i >= 0, j <= 3; i--, j++)
  {
    if (i >= 0 && i <= 3 && j >= 0 && j <= 3 && i != empty_pos[0]) {
      Serial.print(i);
      Serial.println(j);
      digitalWrite(led_matrix[i][j], HIGH);
    }
  }
 
}

//-------------------------------------start reading number of figures and saving positions for each of them--------------------------

void figure_reading() {
  //read all positions in a loop to detect the position of a pawn
  int i, j, found_figure = 0;
start: found_figure = 0 ;

  //read all occupied(0) and empty(1) positions on the board
  //assign 0(=empty square), 1(=occupied square) to a variable

  hes_bool_matrix[0][0] = digitalRead(hes_00);
  hes_bool_matrix[0][1] = digitalRead(hes_01);
  hes_bool_matrix[0][2] = digitalRead(hes_02);
  hes_bool_matrix[0][3] = digitalRead(hes_03);
  hes_bool_matrix[1][0] = digitalRead(hes_10);
  hes_bool_matrix[1][1] = digitalRead(hes_11);
  hes_bool_matrix[1][2] = digitalRead(hes_12);
  hes_bool_matrix[1][3] = digitalRead(hes_13);
  hes_bool_matrix[2][0] = digitalRead(hes_20);
  hes_bool_matrix[2][1] = digitalRead(hes_21);
  hes_bool_matrix[2][2] = digitalRead(hes_22);
  hes_bool_matrix[2][3] = digitalRead(hes_23);
  hes_bool_matrix[3][0] = digitalRead(hes_30);
  hes_bool_matrix[3][1] = digitalRead(hes_31);
  hes_bool_matrix[3][2] = digitalRead(hes_32);
  hes_bool_matrix[3][3] = digitalRead(hes_33);


  for (i = 0; i <= 3; i++) {
    for (j = 0; j <= 3; j++) {
      if (hes_bool_matrix[i][j] == 0) {
        found_figure++ ;

        if (found_figure == 1) {
          if (id_type_matrix[i][j] == 0) {
            id_type_matrix[i][j] = temp;
            temp = 0; }
         
          if(id_type_matrix[i][j]==1){
          Serial.print("Queen is standing on:");
          Serial.print(i);
          Serial.println(j);
          figure_pos[0][0] = i;
          figure_pos[0][1] = j;

         
          
          } else if(id_type_matrix[i][j]==2){
          Serial.print("Pawn is standing on:");
          Serial.print(i);
          Serial.println(j);
          figure_pos[0][0] = i;
          figure_pos[0][1] = j;
          
          //if (id_type_matrix[i][j] == 0) {
          //id_type_matrix[i][j] = temp;
          //temp = 0; }}
        } }
        
        else if (found_figure == 2)
        { if (id_type_matrix[i][j] == 0) {
            id_type_matrix[i][j] = temp;
            temp = 0; }
          
          if(id_type_matrix[i][j]==1){ Serial.print("Queen is standing on:");
          Serial.print(i);
          Serial.println(j);
          figure_pos[1][0] = i;
          figure_pos[1][1] = j;

         //if (id_type_matrix[i][j] == 0) {
         //id_type_matrix[i][j] = temp;
         //temp = 0; }
        
        } else if(id_type_matrix[i][j]==2){Serial.print("Pawn is standing on:");
          Serial.print(i);
          Serial.println(j);
          figure_pos[1][0] = i;
          figure_pos[1][1] = j;

//          if (id_type_matrix[i][j] == 0) {
//          id_type_matrix[i][j] = temp;
//          temp = 0; }
          
          //goto out;
        }
        }
      }
    }
} out:
  if (found_figure == 0 || found_figure ==1) {
    goto start;
  }
  else if (found_figure == 2) {
    leds_off();
  }

  //---------------------------------------------- we choose which figure to pick -----------------------------------------------------------------

  empty_pos[0] = -1;

  delay(2000);

  if (digitalRead(hes_pin_matrix[figure_pos[0][0]][figure_pos[0][1]]) == 1) {
    empty_pos[0] = figure_pos[0][0];
    empty_pos[1] = figure_pos[0][1];
    temp = id_type_matrix[empty_pos[0]][empty_pos[1]];
    id_type_matrix[empty_pos[0]][empty_pos[1]] = 0;
  }


  else if (digitalRead(hes_pin_matrix[figure_pos[1][0]][figure_pos[1][1]]) == 1) {
    empty_pos[0] = figure_pos[1][0];
    empty_pos[1] = figure_pos[1][1];
    temp = id_type_matrix[empty_pos[0]][empty_pos[1]];
    id_type_matrix[empty_pos[0]][empty_pos[1]] = 0;
  }

  //------------------------------------------- MOVING PAWN or QUEEN----------------------------------------------------------------------------------------------------

if(temp==1){
  if ( empty_pos[0] != -1) 
  {
    move_queen();
    goto start;
    }
    
  } else if(temp==2){if ( empty_pos[0] != -1) {
    if (empty_pos[0] < 2) {
      digitalWrite(led_matrix[empty_pos[0] + 1][empty_pos[1]], HIGH);
      digitalWrite(led_matrix[empty_pos[0] + 2][empty_pos[1]], HIGH);
    } else if (empty_pos[0] == 2) {
      digitalWrite(led_matrix[empty_pos[0] + 1][empty_pos[1]], HIGH);
    }
    else;
  } delay(100);}
  
 figure_reading();
}

//--------------------------------------------------------------------- loop starts ------------------------------------------------------------------------------------

void loop() {

  figure_reading();
}

Schematics

4x4demo_q0nvG3T3nS.fzz
Schematics are a little bit complicated, I know, but the idea should be clear. It was the first time I used Fritzing (highly recommended by the way), probably connections could be drawn more accurately. Anyway, I noted down everything inside the schematics.

Note: I couldn't find the exact model of RDIF Reader among components in the database of Fritzing. The model I used is 125Khz RFID module - UART. You can find tutorials on Youtube about how to set this module with Arduino.
4x4demo_q0nvG3T3nS.fzz

Comments

Similar projects you might like

Electronic Check-In

Project tutorial by Gergely Imreh

  • 5,519 views
  • 9 comments
  • 30 respects

Android App-Based Home Automation System Using IOT

Project tutorial by Team Autoshack

  • 24,853 views
  • 17 comments
  • 75 respects

Electronic Playground With Arduino and Scratch 2

Project tutorial by MJRoBot

  • 4,205 views
  • 0 comments
  • 16 respects

Alexa Controlled Door Sign Demo

Project tutorial by 3magku

  • 1,707 views
  • 0 comments
  • 5 respects

Electronic Piano Keyboard With Preset Songs

Project tutorial by Lindsay Fox

  • 77,989 views
  • 60 comments
  • 150 respects

Fidget Spinner RPM Counter

by Andriy Baranov

  • 42,948 views
  • 30 comments
  • 106 respects
Add projectSign up / Login