{"id":6407,"date":"2023-05-04T15:51:40","date_gmt":"2023-05-04T13:51:40","guid":{"rendered":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?p=6407"},"modified":"2023-05-05T13:34:50","modified_gmt":"2023-05-05T11:34:50","slug":"photochess","status":"publish","type":"post","link":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/","title":{"rendered":"Photochess"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.23.47.png\" alt=\"\" class=\"wp-image-6429\" width=\"394\" height=\"236\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.23.47.png 370w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.23.47-300x180.png 300w\" sizes=\"auto, (max-width: 394px) 100vw, 394px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">Introducci\u00f3n<\/h2>\n\n\n\n<p class=\"has-text-align-left\">Esta proyecto se basa en recrear un ajedrez en el cual se pueda jugar contra la m\u00e1quina. La m\u00e1quina mostrar\u00e1 por medio de una pantalla los movimientos que realiza. Para ello, una c\u00e1mara reconoce los movimientos realizados por el jugador, y mediante reconocimiento de im\u00e1genes en Python, este movimiento se pasa a Arduino para que pueda indicar el pr\u00f3ximo movimiento que realizar\u00e1 la m\u00e1quina. Adem\u00e1s, se podr\u00e1 elegir opcionalmente el tiempo l\u00edmite para realizar la partida. El tiempo predefinido son 5 minutos, pero se podr\u00e1 modificar sumando o restando un minuto entre 1 minuto y 10 minutos o incluso jugar sin tiempo. Al finalizar la partida, se guardaran todos los movimientos en un fichero de texto as\u00ed como las im\u00e1genes de los movimientos de la partida.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Funcionamiento<\/h2>\n\n\n\n<p>A continuaci\u00f3n mostraremos el funcionamiento del proyecto:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Primero se establece conexi\u00f3n entre Arduino y Phyton<\/li>\n\n\n\n<li>Una vez conectados se intenta calibrar, es decir, tomar los rangos de color para diferenciar los colores. Para ello pulsamos el bot\u00f3n hasta que aparezca el mensaje que se ha calibrado correctamente<\/li>\n\n\n\n<li>A continuaci\u00f3n, se mostrar\u00e1 por una pantalla LCD el tiempo que tendr\u00e1 el usuario para poder pensar los movimientos. Para modificar este tiempo podr\u00e1 pulsar los botones amarillo de la caja. Una vez decidido el tiempo pulsar\u00e1 el bot\u00f3n rojo para seguir con el proceso<\/li>\n\n\n\n<li>El siguiente paso ser\u00e1 reconocer que las piezas est\u00e1n bien colocadas. Para ello el usuario deber\u00e1 pulsar el bot\u00f3n rojo para indicarle al sistema que tome una foto y reconozca las piezas.<\/li>\n\n\n\n<li>Una vez reconocidas las piezas comienza la partida. En el turno del usuario tendr\u00e1 que mover su ficha y para que avance la partida pulsar\u00e1 el bot\u00f3n rojo. En caso de que sea correcto, el sistema mostrar\u00e1 el movimiento de la m\u00e1quina y el usuario mover\u00e1 la ficha de las m\u00e1quina a su nueva posici\u00f3n y pulsar\u00e1 el bot\u00f3n rojo. <\/li>\n\n\n\n<li>La partida terminar\u00e1 cuando se acabe el tiempo o se produzca un jaque mate ya sea del usuario o de la m\u00e1quina.<\/li>\n<\/ul>\n\n\n\n<p>La secuencia anterior ser\u00e1 la ejecuci\u00f3n principal del sistema, pero tambi\u00e9n existen muchos caminos alternativos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No se ha conseguido calibrar correctamente el tablero. Se mostrar\u00e1 un mensaje de error y se volver\u00e1 a pedir que el usuario vuelva a pulsar el bot\u00f3n rojo para volver a intentar calibrar el sistema.<\/li>\n\n\n\n<li>Las piezas est\u00e1n mal colocadas. Se mostrar\u00e1 un mensaje de error y se pedir\u00e1  que se  coloquen las piezas de forma adecuada.<\/li>\n\n\n\n<li>El movimiento del usuario es incorrecto. Se mostrar\u00e1 un mensaje de error, y se pedir\u00e1 volver a realizar un movimiento.<\/li>\n\n\n\n<li>El usuario no realiza el movimiento de la m\u00e1quina correctamente. La m\u00e1quina volver\u00e1 a ense\u00f1ar el movimiento de la m\u00e1quina hasta que el usuario coloque en la posici\u00f3n indicada la ficha de la m\u00e1quina.<\/li>\n<\/ul>\n\n\n\n<p>Algunos de estos casos se demostrar\u00e1n al final de la entrada del blog en unos v\u00eddeos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hardware<\/h2>\n\n\n\n<p>La parte hardware se divide en dos m\u00f3dulos: M\u00f3dulo del ajedrez y M\u00f3dulo Arduino.<\/p>\n\n\n\n<p>El m\u00f3dulo del ajedrez es una estructura donde se coloca el m\u00f3vil en una posici\u00f3n fija desde la que pueda sacar una foto en la que se vea bien el tablero y las fichas. Se trata de dos plataformas sostenidas mediante barras de pl\u00e1sticos y separadas dejando la altura suficiente para obtener fotograf\u00edas donde se vea completamente el tablero. Adem\u00e1s, en la plataforma inferior donde se colocar\u00e1 el tablero, se han agregado tacos de madera para mantener el tablero en una posici\u00f3n fija para evitar problemas a la hora de realizar la calibraci\u00f3n. Esta estructura es independiente de los componentes Hardware de Arduino. A continuaci\u00f3n, se especificar\u00e1 los materiales y el presupuesto.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Elemento<\/strong><\/td><td><strong>Precio (\u20ac)<\/strong><\/td><td><strong>Descripci\u00f3n<\/strong><\/td><\/tr><tr><td>Zapatero reutilizado<\/td><td>10<\/td><td>Soporte fijo del m\u00f3vil<\/td><\/tr><tr><td>Tablero ajedrez<\/td><td>3<\/td><td><\/td><\/tr><tr><td>Goma Eva<\/td><td>1,2<\/td><td>Fichas<\/td><\/tr><tr><td>M\u00f3vil antiguo<\/td><td>0<\/td><td><\/td><\/tr><tr><td>Extras: bridas, tacos madera<\/td><td>0<\/td><td>Para inmovilizar el tablero<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>El m\u00f3dulo ser\u00e1 el siguiente:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\" alt=\"\" class=\"wp-image-6414\" width=\"287\" height=\"241\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png 588w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36-300x252.png 300w\" sizes=\"auto, (max-width: 287px) 100vw, 287px\" \/><\/figure>\n<\/div>\n\n\n<p>El otro m\u00f3dulo ser\u00e1 el m\u00f3dulo de Arduino. Sus componentes del Hardware se encuentran empotrados en una caja de cart\u00f3n. Desde el exterior \u00fanicamente se puede ver la pantalla LCD y los tres botones. El usuario interactuar\u00e1 \u00fanicamente con estos tres componentes. Permitir\u00e1 interactuar al usuario con el sistema. A continuaci\u00f3n se mostrar\u00e1 dos im\u00e1genes: la estructura y un esquema del hardware en Tinkercard:<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<div class=\"wp-block-group is-content-justification-center is-nowrap is-layout-flex wp-container-core-group-is-layout-94bc23d7 wp-block-group-is-layout-flex\">\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16.jpg\" alt=\"\" class=\"wp-image-6432\" width=\"202\" height=\"202\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16.jpg 442w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16-300x300.jpg 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16-150x150.jpg 150w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16-80x80.jpg 80w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/PHOTO-2023-05-04-13-23-16-320x320.jpg 320w\" sizes=\"auto, (max-width: 202px) 100vw, 202px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.29.52.png\" alt=\"\" class=\"wp-image-6431\" width=\"261\" height=\"177\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.29.52.png 998w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.29.52-300x204.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-15.29.52-768x523.png 768w\" sizes=\"auto, (max-width: 261px) 100vw, 261px\" \/><\/figure>\n<\/div>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Software<\/h2>\n\n\n\n<p>El c\u00f3digo se basar\u00e1 en la comunicaci\u00f3n entre un programa de Arduino y un programa de Phyton. Cada uno tendr\u00e1 una funci\u00f3n y gracias su combinaci\u00f3n podremos jugar una partida contra la m\u00e1quina.<\/p>\n\n\n\n<p>El programa de Phyton se encargar\u00e1 de obtener las im\u00e1genes del tablero de Arduino para calcular que movimiento se ha realizado en el tablero mediante segmentaci\u00f3n de color y poder comunic\u00e1rselo a Arduino. Para ello utilizamos una serie de funciones auxiliares que nos ayudan a cumplir distintas tareas, como tomar una foto dada la IP de un tel\u00e9fono, calibrar el tablero, o calcular el movimiento realizado.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport cv2\nimport numpy as np\nimport serial\nimport time\n\n\ndef establish_connection():\n    arduino = serial.Serial(\"COM3\", 9600)\n    time.sleep(2)\n    write_serial(arduino, \"Connected\")\n    if read_serial(arduino) == \"Connected\":\n        print(\"Conexion establecida\")\n        return arduino\n    else:\n        print(\"Conexion fallida\")\n\n\ndef read_serial(arduino):\n    return arduino.readline().decode().strip()\n\n\ndef write_serial(arduino, string):\n    arduino.write(str(string).encode())\n\n\ndef take_pic(ip, size=(2160, 972)):\n    directory = r'C:\\Users\\jemar\\Pictures\\Sistemas empotrados'\n    url = \"https:\/\/\" + ip + \"\/shot.jpg\"\n    cap = cv2.VideoCapture(url)\n\n    while True:\n        camera, frame = cap.read()\n        if frame is not None:\n            img = cv2.resize(frame, size)\n            os.chdir(directory)\n            cv2.imwrite(\"FOTO.jpg\", img)\n            return img\n        q = cv2.waitKey(1)\n        if q == ord(\"q\"):\n            break\n    cv2.destroyAllWindows()\n\n\ndef calculate_corner_distortion(pto_ext, pto_med, pto_int):\n    dist_ext_med = np.sqrt((pto_ext&#91;0]&#91;0] - pto_med&#91;0]&#91;0]) ** 2 + (pto_ext&#91;0]&#91;1] - pto_med&#91;0]&#91;1]) ** 2)\n    dist_med_int = np.sqrt((pto_med&#91;0]&#91;0] - pto_int&#91;0]&#91;0]) ** 2 + (pto_med&#91;0]&#91;1] - pto_int&#91;0]&#91;1]) ** 2)\n    ratio = dist_ext_med \/ dist_med_int\n    return &#91;pto_ext&#91;0]&#91;0] + (pto_ext&#91;0]&#91;0] - pto_med&#91;0]&#91;0]) * ratio,\n            pto_ext&#91;0]&#91;1] + (pto_ext&#91;0]&#91;1] - pto_med&#91;0]&#91;1]) * ratio]\n\n\ndef calibrate_board(img, size=1200):\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    pattern_size = (7, 7)\n    found, corners = cv2.findChessboardCorners(gray, pattern_size, None)\n    if not found:\n        return None\n    else:\n        corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1),\n                                           criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))\n        esq1 = calculate_corner_distortion(corners_refined&#91;0], corners_refined&#91;8], corners_refined&#91;16])\n        esq2 = calculate_corner_distortion(corners_refined&#91;6], corners_refined&#91;12], corners_refined&#91;18])\n        esq3 = calculate_corner_distortion(corners_refined&#91;42], corners_refined&#91;36], corners_refined&#91;30])\n        esq4 = calculate_corner_distortion(corners_refined&#91;48], corners_refined&#91;40], corners_refined&#91;32])\n        points = order_points(&#91;esq1, esq2, esq3, esq4])\n        src_pts = np.float32(points)\n        dst_pts = np.float32(&#91;&#91;0, 0], &#91;0, size], &#91;size, size], &#91;size, 0]])\n        perspective_matrix = cv2.getPerspectiveTransform(src_pts, dst_pts)\n        return perspective_matrix\n\n\ndef order_points(corners):\n    sums = &#91;corners&#91;0]&#91;0] + corners&#91;0]&#91;1], corners&#91;1]&#91;0] + corners&#91;1]&#91;1], corners&#91;2]&#91;0] + corners&#91;2]&#91;1],\n            corners&#91;3]&#91;0] + corners&#91;3]&#91;1]]\n    mini = min(sums)\n    maxi = max(sums)\n    mid = list()\n    for i in range(4):\n        if sums&#91;i] == mini:\n            esq_ne = corners&#91;i]\n        elif sums&#91;i] == maxi:\n            esq_so = corners&#91;i]\n        else:\n            mid.append(corners&#91;i])\n    if mid&#91;0]&#91;0] &lt; mid&#91;1]&#91;0]:\n        esq_no = mid&#91;0]\n        esq_se = mid&#91;1]\n    else:\n        esq_no = mid&#91;1]\n        esq_se = mid&#91;0]\n    return &#91;esq_no, esq_so, esq_se, esq_ne]\n\n\ndef warp_image(img, perspective_matrix, size=1200):\n    return cv2.warpPerspective(img, perspective_matrix, (size, size), flags=cv2.INTER_LINEAR)\n\n\ndef add_points(i, offset=15):\n    side = 1200 \/ 8\n    x = (i % 8) * side\n    y = (i \/\/ 8) * side\n    points = list()\n    points.append(&#91;int(x + side * 0.2), int(y + side \/ 2)])\n    points.append(&#91;int(x + side * 0.8), int(y + side \/ 2)])\n    return points\n\n\ndef calibrate_points(hsv, puntos):\n    h = list()\n    s = list()\n    v = list()\n    for p in puntos:\n        # print(p, \":  \", hsv&#91;p&#91;1]]&#91;p&#91;0]])\n        h.append(hsv&#91;p&#91;1]]&#91;p&#91;0]]&#91;0])\n        s.append(hsv&#91;p&#91;1]]&#91;p&#91;0]]&#91;1])\n        v.append(hsv&#91;p&#91;1]]&#91;p&#91;0]]&#91;2])\n        # hsv = cv2.circle(hsv, (p&#91;0], p&#91;1]), radius=0, color=(0, 0, 255), thickness=3)\n    h = &#91;min(h) - 10, max(h) + 10]\n    s = &#91;min(s) - 10, max(s) + 10]\n    v = &#91;min(v) - 10, max(v) + 10]\n    \"\"\"cv2.imshow(\"puntos\", hsv)\n    cv2.waitKey(0)\n    cv2.destroyAllWindows()\"\"\"\n    \"\"\"print(&#91;min(h) - 10, \"  \", max(h) + 5], max(h)-min(h))\n    print(&#91;min(s) - 10, \"  \", max(s) + 10], max(s)-min(s))\n    print(&#91;min(v) - 10, \"  \", max(v) + 10], max(v)-min(v))\"\"\"\n\n    return &#91;np.array(&#91;h&#91;0], s&#91;0], v&#91;0]]), np.array(&#91;h&#91;1], s&#91;1], v&#91;1]])]\n\n\ndef calculate_masks(hsv, ranges):\n    mask = cv2.inRange(hsv, ranges&#91;0], ranges&#91;1])\n    kernel = np.ones((5, 5), np.uint8)\n    mask = cv2.erode(mask, kernel, iterations=1)\n    mask = cv2.dilate(mask, kernel, iterations=1)\n    return mask\n\n\ndef get_mask(hsv, img, color):\n    if color == \"white\":\n        mask = cv2.inRange(hsv, (0, 0, 185), (179, 25, 220))\n    else:\n        # mask1 = cv2.inRange(hsv, (0, 65, 80), (15, 160, 160))\n        # mask2 = cv2.inRange(hsv, (170, 65, 80), (179, 160, 160))\n        mask1 = cv2.inRange(hsv, (0, 65, 60), (30, 160, 160))\n        mask2 = cv2.inRange(hsv, (170, 65, 60), (179, 160, 160))\n        mask = cv2.bitwise_or(mask1, mask2)\n    kernel = np.ones((5, 5), np.uint8)\n    img = cv2.bitwise_and(img, img, mask=mask)\n    img = cv2.erode(img, kernel, iterations=1)\n    img = cv2.dilate(img, kernel, iterations=2)\n    return img\n\n\ndef calculate_pieces(mask, size=400, percentage=0.3):\n    mask = cv2.resize(mask, (size, size))\n    side = size \/\/ 8\n    matrix = &#91;]\n    for i in range(64):\n        pixels = 0\n        for x in range(side * (i % 8), side * (i % 8) + side - 1):\n            for y in range(side * (i \/\/ 8), side * (i \/\/ 8) + side - 1):\n                if (x - (side * (i % 8) + side \/ 2)) ** 2 + (y - (side * (i \/\/ 8) + side \/ 2)) ** 2 &lt;= (\n                        (side * 0.8) \/\/ 2) ** 2:\n                    if mask&#91;y]&#91;x]&#91;0] != 0 or mask&#91;y]&#91;x]&#91;1] != 0 or mask&#91;y]&#91;x]&#91;2] != 0:\n                        pixels = pixels + 1\n        if i \/\/ 8 == 0:\n            matrix.append(&#91;])\n        matrix&#91;i \/\/ 8].append(&#91;])\n        if pixels &gt; (side * 0.4) ** 2 * 3 * percentage:\n            matrix&#91;i \/\/ 8]&#91;i % 8] = 1\n        else:\n            matrix&#91;i \/\/ 8]&#91;i % 8] = 0\n    return matrix\n\n\ndef castle(squares, prev_mat, actual_mat):\n    if prev_mat&#91;squares&#91;0]&#91;0]]&#91;squares&#91;0]&#91;1]] != 1:\n        return False\n    if prev_mat&#91;squares&#91;1]&#91;0]]&#91;squares&#91;1]&#91;1]] != 0:\n        return False\n    if prev_mat&#91;squares&#91;2]&#91;0]]&#91;squares&#91;2]&#91;1]] != 0:\n        return False\n    if prev_mat&#91;squares&#91;3]&#91;0]]&#91;squares&#91;3]&#91;1]] != 1:\n        return False\n    if actual_mat&#91;squares&#91;0]&#91;0]]&#91;squares&#91;0]&#91;1]] != 0:\n        return False\n    if actual_mat&#91;squares&#91;1]&#91;0]]&#91;squares&#91;1]&#91;1]] != 1:\n        return False\n    if actual_mat&#91;squares&#91;2]&#91;0]]&#91;squares&#91;2]&#91;1]] != 1:\n        return False\n    if actual_mat&#91;squares&#91;3]&#91;0]]&#91;squares&#91;3]&#91;1]] != 0:\n        return False\n    return True\n\n\ndef calculate_move(prev_mat, actual_mat, rotated=0):\n    letters = &#91;&#91;'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &#91;'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']]\n    numbers = &#91;&#91;'8', '7', '6', '5', '4', '3', '2', '1'], &#91;'1', '2', '3', '4', '5', '6', '7', '8']]\n    prev_square = \"\"\n    actual_square = \"\"\n    if castle(&#91;&#91;0, 0], &#91;0, 2], &#91;0, 3], &#91;0, 4]], prev_mat, actual_mat):\n        return \"e8c8\"\n    if castle(&#91;&#91;0, 4], &#91;0, 5], &#91;0, 6], &#91;0, 7]], prev_mat, actual_mat):\n        return \"e8g8\"\n    if castle(&#91;&#91;7, 0], &#91;7, 2], &#91;7, 3], &#91;7, 4]], prev_mat, actual_mat):\n        return \"e1c1\"\n    if castle(&#91;&#91;7, 4], &#91;7, 5], &#91;7, 6], &#91;7, 7]], prev_mat, actual_mat):\n        return \"e1g1\"\n    for y in range(8):\n        for x in range(8):\n            if (prev_mat&#91;y]&#91;x] == 1) &amp; (actual_mat&#91;y]&#91;x] == 0):\n                if len(prev_square) == 0:\n                    prev_square = letters&#91;rotated]&#91;x] + numbers&#91;rotated]&#91;y]\n            elif (prev_mat&#91;y]&#91;x] == 0) &amp; (actual_mat&#91;y]&#91;x] == 1):\n                if len(actual_square) == 0:\n                    actual_square = letters&#91;rotated]&#91;x] + numbers&#91;rotated]&#91;y]\n    if prev_square == \"\":\n        prev_square = \"No\"\n    if actual_square == \"\":\n        actual_square = \"ne\"\n    return prev_square + actual_square + \"\\n\"\n\n\ndef compare_matrix(mat_a, mat_b):\n    for y in range(8):\n        for x in range(8):\n            if mat_a&#91;y]&#91;x] != mat_b&#91;y]&#91;x]:\n                return False\n    return True\n\nip = \"192.168.70.134:8080\"\narduino = establish_connection()\ndirectory = r'C:\\Users\\jemar\\Pictures\\Sistemas empotrados'\nos.chdir(directory)\nfile = open(\"partida.txt\", \"w\")\nwhile True:\n    cod = read_serial(arduino)\n    print(cod)\n    if cod == \"calibrate\":\n        img = take_pic(ip)\n        perspective_mat = calibrate_board(img)\n        if perspective_mat is None:\n            print(\"error\")\n            write_serial(arduino, \"-1\")\n        else:\n            write_serial(arduino, \"0\")\n            break\n    else:\n        print(\"Codigo erroneo, no se ha calibrado el tablero\")\n\nprev_matrix_white = &#91;&#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;1, 1, 1, 1, 1, 1, 1, 1], &#91;1, 1, 1, 1, 1, 1, 1, 1]]\nprev_matrix_black = &#91;&#91;1, 1, 1, 1, 1, 1, 1, 1], &#91;1, 1, 1, 1, 1, 1, 1, 1],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0]]\n\nwhile True:\n    cod = read_serial(arduino)\n    print(cod)\n    if cod == \"startGame\":\n        img = take_pic(ip)\n        warped_img = warp_image(img, perspective_mat)\n        cv2.imwrite(\"warped.jpg\", warped_img)\n        hsv = cv2.cvtColor(warped_img, cv2.COLOR_BGR2HSV)\n\n        white_points = list()\n        for i in range(48, 64):\n            white_points = white_points + add_points(i)\n        white_range = calibrate_points(hsv, white_points)\n        white_mask = calculate_masks(hsv, white_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=white_mask)\n        cv2.imwrite(\"white.jpg\", masked_img)\n        actual_matrix_white = calculate_pieces(masked_img)\n        print(actual_matrix_white)\n        white_ok = compare_matrix(prev_matrix_white, actual_matrix_white)\n        print(white_ok)\n\n        black_points = list()\n        for i in range(16):\n            black_points = black_points + add_points(i)\n        black_range = calibrate_points(hsv, black_points)\n        black_mask = calculate_masks(hsv, black_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=black_mask)\n        cv2.imwrite(\"black.jpg\", masked_img)\n        actual_matrix_black = calculate_pieces(masked_img)\n        print(actual_matrix_black)\n        black_ok = compare_matrix(prev_matrix_black, actual_matrix_black)\n        print(black_ok)\n\n        if white_ok and black_ok:\n            prev_matrix_white = actual_matrix_white\n            prev_matrix_black = actual_matrix_black\n            write_serial(arduino, \"1\")\n            file.write(\"NUEVA PARTIDA\\n\\n\")\n            break\n        else:\n            print(\"Piezas mal colocadas\")\n            write_serial(arduino, \"-1\")\n    else:\n        print(\"Codigo erroneo, partida no iniciada\")\n\nn_moves = 0\n\nproblematic_matrix_white = &#91;&#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 1, 0, 0, 0], &#91;0, 0, 1, 0, 0, 1, 0, 0],\n                     &#91;1, 1, 1, 1, 0, 1, 1, 1], &#91;1, 0, 1, 1, 1, 1, 0, 1]]\n\nproblematic_matrix_black = &#91;&#91;1, 0, 1, 1, 1, 1, 1, 1], &#91;1, 1, 1, 1, 0, 1, 1, 1],\n                     &#91;0, 0, 1, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 1, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0],\n                     &#91;0, 0, 0, 0, 0, 0, 0, 0], &#91;0, 0, 0, 0, 0, 0, 0, 0]]\n\nwhile True:\n    cod = read_serial(arduino)\n    print(cod)\n    if cod == \"whiteMoves\":\n\n        img = take_pic(ip)\n        warped_img = warp_image(img, perspective_mat)\n        cv2.imwrite(\"warped.jpg\", warped_img)\n        hsv = cv2.cvtColor(warped_img, cv2.COLOR_BGR2HSV)\n\n        white_mask = calculate_masks(hsv, white_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=white_mask)\n        cv2.imwrite(\"white.jpg\", masked_img)\n        actual_matrix_white = calculate_pieces(masked_img)\n        \"\"\"if n_moves == 4:\n            black_mask = calculate_masks(hsv, black_range)\n            masked_img = cv2.bitwise_and(warped_img, warped_img, mask=black_mask)\n            cv2.imwrite(\"black.jpg\", masked_img)\n            actual_matrix_black = calculate_pieces(masked_img)\n            if compare_matrix(actual_matrix_white, problematic_matrix_white) and compare_matrix(actual_matrix_black, problematic_matrix_black):\n                print(prev_matrix_white)\n                print(actual_matrix_white)\n                move = \n            else:\n                print(prev_matrix_white)\n                print(actual_matrix_white)\n                move = calculate_move(prev_matrix_white, actual_matrix_white)\n        else:\"\"\"\n        print(prev_matrix_white)\n        print(actual_matrix_white)\n        move = calculate_move(prev_matrix_white, actual_matrix_white)\n\n        print(move)\n        write_serial(arduino, move)\n    elif cod == \"whiteOK\":\n        prev_matrix_white = actual_matrix_white\n        black_mask = calculate_masks(hsv, black_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=black_mask)\n        cv2.imwrite(\"black.jpg\", masked_img)\n        prev_matrix_black = calculate_pieces(masked_img)\n        n_moves = n_moves + 1\n        file.write(str(n_moves) + \". Jugador mueve: \" + str(move))\n    elif cod == \"blackMoves\":\n        img = take_pic(ip)\n        warped_img = warp_image(img, perspective_mat)\n        cv2.imwrite(\"warped.jpg\", warped_img)\n        hsv = cv2.cvtColor(warped_img, cv2.COLOR_BGR2HSV)\n\n        black_mask = calculate_masks(hsv, black_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=black_mask)\n        cv2.imwrite(\"black.jpg\", masked_img)\n        actual_matrix_black = calculate_pieces(masked_img)\n        print(prev_matrix_black)\n        print(actual_matrix_black)\n        move = calculate_move(prev_matrix_black, actual_matrix_black)\n        print(move)\n        write_serial(arduino, move)\n    elif cod == \"blackOK\":\n        prev_matrix_black = actual_matrix_black\n        white_mask = calculate_masks(hsv, white_range)\n        masked_img = cv2.bitwise_and(warped_img, warped_img, mask=white_mask)\n        cv2.imwrite(\"white.jpg\", masked_img)\n        prev_matrix_white = calculate_pieces(masked_img)\n        n_moves = n_moves + 1\n        file.write(str(n_moves) + \". Maquina mueve: \" + str(move))\n    elif cod == \"whiteWins\":\n        file.write(str(n_moves) + \". Jugador mueve: \" + str(move) + \". JAQUE MATE!\\n\")\n        file.close()\n        break\n    elif cod == \"blackWins\":\n        file.write(str(n_moves) + \". Maquina mueve: \" + str(move) + \". JAQUE MATE!\\n\")\n        file.close()\n        break\nfile.close()<\/code><\/pre>\n\n\n\n<p>La funci\u00f3n del programa de Arduino es gestionar&nbsp;la partida de ajedrez, comprobar los movimientos realizados, calcular los movimientos de la m\u00e1quina, y actuar como interfaz para el usuario. Para todo lo relacionado con los movimientos de ajedrez, hemos utilizado el c\u00f3digo&nbsp;Chessuino, creado por Diego Cuevas. Este algoritmo es capaz de comprobar si un movimiento est\u00e1 permitido, y de calcular un movimiento para jugar contra \u00e9l. El c\u00f3digo es el siguiente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;LiquidCrystal.h&gt;\n\nconst int rs = 12, en=11, d4=2, d5=3, d6=4, d7=5;\nLiquidCrystal lcd (rs, en,d4 , d5, d6,d7);\n\nconst int buttonPin=7;\nint buttonState=0;\n\n#define W while\n#define M 0x88\n#define S 128\n#define I 8000\n\n#define MYRAND_MAX 65535     \/* 16bit pseudo random generator *\/\nlong  N, T;                  \/* N=evaluated positions+S, T=recursion limit *\/\nshort Q, O, K, R, k = 16;    \/* k=moving side *\/\nchar *p, c&#91;5], Z;            \/* p=pointer to c, c=user input, computer output, Z=recursion counter *\/\n\nchar L,\n     w&#91;] = {0, 2, 2, 7, -1, 8, 12, 23},                    \/* relative piece values    *\/\n           o&#91;] = { -16, -15, -17, 0, 1, 16, 0, 1, 16, 15, 17, 0, 14, 18, 31, 33, 0, \/* step-vector lists *\/\n                   7, -1, 11, 6, 8, 3, 6,                           \/* 1st dir. in o&#91;] per piece*\/\n                   6, 3, 5, 7, 4, 5, 3, 6\n                 };                                \/* initial piece setup      *\/\n\/* board is left part, center-pts table is right part, and dummy *\/\n\nchar b&#91;] = {\n  22, 19, 21, 23, 20, 21, 19, 22, 28, 21, 16, 13, 12, 13, 16, 21,\n  18, 18, 18, 18, 18, 18, 18, 18, 22, 15, 10,  7,  6,  7, 10, 15,\n  0,  0,  0,  0,  0,  0,  0,  0, 18, 11,  6,  3,  2,  3,  6, 11,\n  0,  0,  0,  0,  0,  0,  0,  0, 16,  9,  4,  1,  0,  1,  4,  9,\n  0,  0,  0,  0,  0,  0,  0,  0, 16,  9,  4,  1,  0,  1,  4,  9,\n  0,  0,  0,  0,  0,  0,  0,  0, 18, 11,  6,  3,  2,  3,  6, 11,\n  9,  9,  9,  9,  9,  9,  9,  9, 22, 15, 10,  7,  6,  7, 10, 15,\n  14, 11, 13, 15, 12, 13, 11, 14, 28, 21, 16, 13, 12, 13, 16, 21, 0\n};\n\nunsigned int seed = 0;\n\nint mn = 1;\/\/move number\nchar lastH&#91;5], lastM&#91;5]; \/\/arrays to hold Human \/  Machine move characters + 1 null\n\nbool stringComplete = false;  \/\/ whether the string is complete\n  \nint lengthMove=0;\n\nvoid setup() {  \n  Serial.begin(9600);\n  pinMode(buttonPin,INPUT);\n  lcd.begin (16,2);\n  String cod;\n  delay(1000);\n  do{\n    lcd.print(\"Esperando\");\n    lcd.setCursor(0, 1);\n    lcd.print(\"conexion...\");\n    lcd.home();\n    while(Serial.available()==0){}\n    cod = leerCodigo();\n  }while(cod != \"Connected\");\n  lcd.clear();\n  lcd.print(\"Conectado\");\n  delay(1500);\n  Serial.println(\"Connected\");\n  lcd.clear();\n  do{\n    lcd.print(\"Pulsa para\");\n    lcd.setCursor(0, 1);\n    lcd.print(\"calibrar\");\n    lcd.home();\n    buttonState=digitalRead(buttonPin);\n    if(buttonState==HIGH){\n      Serial.println(\"calibrate\");\n      lcd.clear();\n      lcd.print(\"Calibrando...\");\n      Serial.flush();\n      while(Serial.available()==0){}\n      cod = leerCodigo();\n      if(cod != \"0\"){\n        lcd.clear();\n        lcd.print(\"Error calibrando\");\n        delay(1000);\n      }\n      lcd.clear();\n    }\n  }while(cod != \"0\");\n\n  Serial.flush();\n  \n  do{\n    Serial.flush();\n    lcd.print(\"Pulsa para\");\n    lcd.setCursor(0, 1);\n    lcd.print(\"iniciar partida\");\n    lcd.home();\n    buttonState=digitalRead(buttonPin);\n    if(buttonState==HIGH){\n      Serial.println(\"startGame\");\n      lcd.clear();\n      lcd.print(\"Reconociendo...\");\n      while(Serial.available()==0){}\n      cod = leerCodigo();\n      if(cod != \"1\"){\n        lcd.clear();\n        lcd.print(\"Piezas mal\");\n        lcd.setCursor(0, 1);\n        lcd.print(\"colocadas\");\n        delay(1000);\n        lcd.home();\n        lcd.print(\"Pulsa para\");\n        lcd.setCursor(0, 1);\n        lcd.print(\"iniciar partida\");\n        lcd.home();\n      }\n      lcd.clear();\n    }\n  }while(cod != \"1\");\n  \n  lcd.print(\"Realizar\");\n  lcd.setCursor(0, 1);\n  lcd.print(\"movimiento\");\n  lcd.home();\n  lastH&#91;0] = 0;\n}\n\nvoid loop() {\n  \n  buttonState=digitalRead(buttonPin);\n  if(buttonState==HIGH){\n    lcd.clear();\n    lcd.home(); \n    int r;\n    if(stringComplete==false){\n      leerMovimiento(\"whiteMoves\");\n    }\n    lcd.print(\"Nuevo movimiento\");\n    lcd.setCursor(0, 1);\n    lcd.print(c&#91;0]);\n    lcd.print(c&#91;1]);\n    lcd.print(c&#91;2]);\n    lcd.print(c&#91;3]);\n    delay(0);\n    lengthMove=0;\n    stringComplete = false;\n    lcd.clear();  \n    lcd.print(\"Calculando...\");    \/* Turn for ARDUINO *\/\n    delay(0);\n    lcd.home();\n    K = *c - 16 * c&#91;1] + 799, L = c&#91;2] - 16 * c&#91;3] + 799; \/* parse entered move *\/\n    N = 0;\n    T = 0x3F;                                 \/* T=Computer Play strength *\/\n    r = D(-I, I, Q, O, 1, 3);                 \/* Check &amp; do the human movement *\/\n    if ( !(r &gt; -I + 1) ) {\n      lcd.print(\"Has ganado\");\n      lcd.setCursor(0,1);\n      gameOver();\n      delay(2000);\n    }\n    if (k == 0x10) {                          \/* The flag turn must change to 0x08 *\/\n      lcd.print(\"Mov incorrecto\");\n      lcd.setCursor(0, 1);\n      lcd.print(\"Realice otro\");\n      lcd.home();\n      return;\n    }\n\n    strcpy(lastH, c);                         \/* Valid human movement *\/\n    Serial.println(\"whiteOK\");\n\n    mn++;                                     \/* Next move *\/\n\n    K = I;\n    N = 0;\n    T = 0x3F;                                 \/* T=Computer Play strength *\/\n    r = D(-I, I, Q, O, 1, 3);                 \/* Think &amp; do*\/\n    if ( !(r &gt; -I + 1) ) {\n      lcd.clear();\n      lcd.print(\"Has ganado\");\n      lcd.setCursor(0,1);\n      gameOver();\n      delay(2000);\n    }\n    if(k == 0x08){                            \/* Some times the algorithm do not *\/\n        lcd.setCursor(10, 1);                 \/* execute the move and do not change *\/\n        lcd.print(\"ERR 3 \");                  \/* the turn flag *\/\n        gameOver();                           \/* 1. b1c3  c7c5?       2. f2f4? *\/\n    }\n    strcpy(lastM, c);                         \/* Valid ARDUINO movement *\/\n    r = D(-I, I, Q, O, 1, 3);\n    if ( !(r &gt; -I + 1) ) {\n      lcd.clear();\n      lcd.print(\"Jaque mate\");\n      lcd.setCursor(0,1);\n      Serial.println(lastM);\n      lcd.print(lastM);\n      delay(2000);\n      lcd.clear();\n      lcd.home();\n      lcd.print(\"Has perdido\");\n      gameOver();\n      delay(2000);\n    }\n    if(k == 0x08){                            \/* Some times the algorithm do not *\/\n        lcd.setCursor(10, 1);                 \/* execute the move and do not change *\/\n        lcd.print(\"ERR 3 \");                  \/* the turn flag *\/\n        gameOver();                           \/* 1. b1c3  c7c5?       2. f2f4? *\/\n    }\n    \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/Computer move section\n    \n    do{\n      lcd.print(\"Maquina mueve\");\n      lcd.setCursor(0,1);\n      lcd.print(lastM);\n      lcd.home();\n      buttonState=digitalRead(buttonPin);\n      if(buttonState==HIGH){\n        leerMovimiento(\"blackMoves\");\n        if ((lastM&#91;0] != c&#91;0]) or (lastM&#91;1] != c&#91;1]) or (lastM&#91;2] != c&#91;2]) or (lastM&#91;3] != c&#91;3])){\n          lcd.clear();\n          lcd.print(\"Movimiento\");\n          lcd.setCursor(0, 1);\n          lcd.print(\"incorrecto\");\n          lcd.clear();\n        }\n        stringComplete = false;\n      }\n    }while((lastM&#91;0] != c&#91;0]) or (lastM&#91;1] != c&#91;1]) or (lastM&#91;2] != c&#91;2]) or (lastM&#91;3] != c&#91;3]));\n    Serial.println(\"blackOK\");\n    lcd.clear();\n    lcd.print(\"Realizar\");\n    lcd.setCursor(0, 1);\n    lcd.print(\"movimiento\");\n    lcd.home();\n  }\n }\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/FIN LOOP\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nString leerCodigo(){\n  if (Serial.available()) { \n    String data = \"\"; \n    while (Serial.available()) {\n      char a = Serial.read(); \n      data += a; \n      delay(2);\n    } \n    return data;\n  }\n}\n\n\nvoid leerMovimiento(String cod){\n  Serial.flush();\n  Serial.println(cod);\n  lcd.clear();\n  lcd.print(\"Leyendo...\");\n  lcd.home();\n  while(Serial.available()==0){}\n  if (Serial.available()) { \n    String data = \"\"; \n    while (Serial.available()) {\n      char a = Serial.read(); \n      data += a; \n      delay(2);\n    } \n    c&#91;0]=data&#91;0];\n    data.remove(0, 1);\n    c&#91;1]=data&#91;0];\n    data.remove(0, 1);\n    c&#91;2]=data&#91;0];\n    data.remove(0, 1);\n    c&#91;3]=data&#91;0];\n    data.remove(0, 1);\n    c&#91;4]=0;\n    data.remove(0, data.length());\n   stringComplete=true;\n  }\n}\n\nunsigned short myrand(void) {\n  unsigned short r = (unsigned short)(seed % MYRAND_MAX);\n  return r = ((r &lt;&lt; 11) + (r &lt;&lt; 7) + r) &gt;&gt; 1;\n}\n\/* recursive minimax search *\/\n\nshort D(short q, short l, short e, unsigned char E, unsigned char z, unsigned char n) {\n  short m, v, i, P, V, s;\n  unsigned char t, p, u, x, y, X, Y, H, B, j, d, h, F, G, C;\n  signed char r;\n  if (++Z &gt; 30) {                                   \/* stack underrun check *\/\n    --Z; return e;\n  }\n  q--;                                          \/* adj. window: delay bonus *\/\n  k ^= 24;                                      \/* change sides             *\/\n  d = Y = 0;                                    \/* start iter. from scratch *\/\n  X = myrand() &amp; ~M;                            \/* start at random field    *\/\n  W(d++ &lt; n || d &lt; 3 ||                         \/* iterative deepening loop *\/\n    z &amp; K == I &amp;&amp; (N &lt; T &amp; d &lt; 98 ||            \/* root: deepen upto time   *\/\n                   (K = X, L = Y &amp; ~M, d = 3)))                \/* time's up: go do best    *\/\n  { x = B = X;                                   \/* start scan at prev. best *\/\n    h = Y &amp; S;                                   \/* request try noncastl. 1st*\/\n    P = d &lt; 3 ? I : D(-l, 1 - l, -e, S, 0, d - 3); \/* Search null move         *\/\n    m = -P &lt; l | R &gt; 35 ? d &gt; 2 ? -I : e : -P;   \/* Prune or stand-pat       *\/\n    ++N;                                         \/* node count (for timing)  *\/\n    do {\n      u = b&#91;x];                                   \/* scan board looking for   *\/\n      if (u &amp; k) {                                \/*  own piece (inefficient!)*\/\n        r = p = u &amp; 7;                             \/* p = piece type (set r&gt;0) *\/\n        j = o&#91;p + 16];                             \/* first step vector f.piece*\/\n        W(r = p &gt; 2 &amp; r &lt; 0 ? -r : -o&#91;++j])        \/* loop over directions o&#91;] *\/\n        { A:                                        \/* resume normal after best *\/\n          y = x; F = G = S;                         \/* (x,y)=move, (F,G)=castl.R*\/\n          do {                                      \/* y traverses ray, or:     *\/\n            H = y = h ? Y ^ h : y + r;               \/* sneak in prev. best move *\/\n            if (y &amp; M)break;                         \/* board edge hit           *\/\n            m = E - S &amp; b&#91;E] &amp;&amp; y - E &lt; 2 &amp; E - y &lt; 2 ? I : m; \/* bad castling             *\/\n            if (p &lt; 3 &amp; y == E)H ^= 16;              \/* shift capt.sqr. H if e.p.*\/\n            t = b&#91;H]; if (t &amp; k | p &lt; 3 &amp; !(y - x &amp; 7) - !t)break; \/* capt. own, bad pawn mode *\/\n            i = 37 * w&#91;t &amp; 7] + (t &amp; 192);           \/* value of capt. piece t   *\/\n            m = i &lt; 0 ? I : m;                       \/* K capture                *\/\n            if (m &gt;= l &amp; d &gt; 1)goto C;               \/* abort on fail high       *\/\n            v = d - 1 ? e : i - p;                   \/* MVV\/LVA scoring          *\/\n            if (d - !t &gt; 1)                          \/* remaining depth          *\/\n            { v = p &lt; 6 ? b&#91;x + 8] - b&#91;y + 8] : 0;    \/* center positional pts.   *\/\n              b&#91;G] = b&#91;H] = b&#91;x] = 0; b&#91;y] = u | 32;  \/* do move, set non-virgin  *\/\n              if (!(G &amp; M))b&#91;F] = k + 6, v += 50;     \/* castling: put R &amp; score  *\/\n              v -= p - 4 | R &gt; 29 ? 0 : 20;           \/* penalize mid-game K move *\/\n              if (p &lt; 3)                              \/* pawns:                   *\/\n              { v -= 9 * ((x - 2 &amp; M || b&#91;x - 2] - u) + \/* structure, undefended    *\/\n                          (x + 2 &amp; M || b&#91;x + 2] - u) - 1  \/*        squares plus bias *\/\n                          + (b&#91;x ^ 16] == k + 36))          \/* kling to non-virgin King *\/\n                     - (R &gt;&gt; 2);                       \/* end-game Pawn-push bonus *\/\n                V = y + r + 1 &amp; S ? 647 - p : 2 * (u &amp; y + 16 &amp; 32); \/* promotion or 6\/7th bonus *\/\n                b&#91;y] += V; i += V;                     \/* change piece, add score  *\/\n              }\n              v += e + i; V = m &gt; q ? m : q;          \/* new eval and alpha       *\/\n              C = d - 1 - (d &gt; 5 &amp; p &gt; 2 &amp; !t &amp; !h);\n              C = R &gt; 29 | d &lt; 3 | P - I ? C : d;     \/* extend 1 ply if in check *\/\n              do\n                s = C &gt; 2 | v &gt; V ? -D(-l, -V, -v,     \/* recursive eval. of reply *\/\n                                       F, 0, C) : v;    \/* or fail low if futile    *\/\n              W(s &gt; q&amp;++C &lt; d); v = s;\n              if (z &amp;&amp; K - I &amp;&amp; v + I &amp;&amp; x == K &amp; y == L) \/* move pending &amp; in root:  *\/\n              { Q = -e - i; O = F;                     \/*   exit if legal &amp; found  *\/\n                R += i &gt;&gt; 7; --Z; return l;            \/* captured non-P material  *\/\n              }\n              b&#91;G] = k + 6; b&#91;F] = b&#91;y] = 0; b&#91;x] = u; b&#91;H] = t; \/* undo move,G can be dummy *\/\n            }\n            if (v &gt; m)                               \/* new best, update max,best*\/\n              m = v, X = x, Y = y | S &amp; F;            \/* mark double move with S  *\/\n            if (h) {\n              h = 0;  \/* redo after doing old best*\/\n              goto A;\n            }\n            if (x + r - y | u &amp; 32 |                 \/* not 1st step,moved before*\/\n                p &gt; 2 &amp; (p - 4 | j - 7 ||             \/* no P &amp; no lateral K move,*\/\n                         b&#91;G = x + 3 ^ r &gt;&gt; 1 &amp; 7] - k - 6     \/* no virgin R in corner G, *\/\n                         || b&#91;G ^ 1] | b&#91;G ^ 2])               \/* no 2 empty sq. next to R *\/\n               )t += p &lt; 5;                           \/* fake capt. for nonsliding*\/\n            else F = y;                              \/* enable e.p.              *\/\n          } W(!t);                                  \/* if not capt. continue ray*\/\n        }\n      }\n    } W((x = x + 9 &amp; ~M) - B);                 \/* next sqr. of board, wrap *\/\nC: if (m &gt; I - M | m &lt; M - I)d = 98;           \/* mate holds to any depth  *\/\n    m = m + I | P == I ? m : 0;                  \/* best loses K: (stale)mate*\/\n    if (z &amp;&amp; d &gt; 2)\n    { *c = 'a' + (X &amp; 7); c&#91;1] = '8' - (X &gt;&gt; 4); c&#91;2] = 'a' + (Y &amp; 7); c&#91;3] = '8' - (Y &gt;&gt; 4 &amp; 7); c&#91;4] = 0;\n      char buff&#91;150];\n    }\n  }                                             \/*    encoded in X S,8 bits *\/\n  k ^= 24;                                      \/* change sides back        *\/\n  --Z; return m += m &lt; e;                       \/* delayed-loss bonus       *\/\n}\n\nvoid gameOver() {\n  Serial.print(\"Partida acabada\");\n  lcd.clear();\n  lcd.print(\"Partida acabada\");\n}\n  <\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Problemas y Soluciones<\/h2>\n\n\n\n<p>Algunos problemas que hemos tenido durante la realizaci\u00f3n del proyecto han sido:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Quer\u00edamos utilizar una c\u00e1mara conectada directamente a la placa de Arduino pero su resoluci\u00f3n era bastante baja y tuvimos que utilizar un tel\u00e9fono m\u00f3vil.<\/li>\n\n\n\n<li>Para poder conectar el m\u00f3vil y el ordenador usamos una aplicaci\u00f3n externa pasando la direcci\u00f3n IP. Sin embargo, algunas redes no nos permiten acceder a ella (como por ejemplo la red de la universidad eduroam) y tuvimos que conectarnos a los datos de otro tel\u00e9fono m\u00f3vil.<\/li>\n\n\n\n<li>La calibraci\u00f3n del sistema para poder reconocer los colores correctamente y por tanto las piezas del tablero. El tablero suele reflejar luz y esto provoca que entren en juego colores que no sirven para la segmentaci\u00f3n y por tanto no se reconoce bien el tablero. La soluci\u00f3n que hemos optado  es tomar al comienzo de la partida una foto del tablero y tomar las referencias de los colores de algunos puntos del tablero para conocer que escalas de colores disponemos en ese momento y aplicar algoritmos (gradiente, medias&#8230;) para intentar encontrar los intervalos de cada color y as\u00ed poder diferenciarlos.<\/li>\n\n\n\n<li>El principal problema ha sido el algoritmo de ajedrez. Hemos dedicado bastante tiempo a encontrar un algoritmo funcional que se ejecutase en Arduino hasta que encontramos el algoritmo dise\u00f1ado por Diego Cuevas. Sin embargo, debido a la inexistente documentaci\u00f3n y ayuda, nos ha sido bastante dif\u00edcil depurar y comprender el c\u00f3digo para fusionarlo con nuestro proyecto. Adem\u00e1s durante el proceso nos percatamos de que era bastante b\u00e1sico ya que en determinadas ocasiones el algoritmo suele repetir los movimientos. Un ejemplo puede ser el primer movimiento de la m\u00e1quina que siempre ser\u00e1 b8c6 independientemente del movimiento del usuario.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Mejoras<\/h2>\n\n\n\n<p>Algunas mejoras que podr\u00edan aplicarse a nuestro proyecto ser\u00edan:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Elegir el lado donde juega el usuario, es decir, poder elegir el lado de las fichas blancas o negras ya que actualmente solo se puede el lado de las blancas.<\/li>\n\n\n\n<li>Elegir la dificultad del algoritmo de la m\u00e1quina.<\/li>\n\n\n\n<li>Dise\u00f1ar un brazo rob\u00f3tico que mueva autom\u00e1ticamente las fichas de la m\u00e1quina<\/li>\n\n\n\n<li>Sistema de puntuaci\u00f3n y clasificaci\u00f3n.<\/li>\n\n\n\n<li>Crear una simulaci\u00f3n de la partida a partir de los movimientos y de las im\u00e1genes.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Demostraci\u00f3n<\/h2>\n\n\n\n<p>A continuaci\u00f3n algunos v\u00eddeos que mostraran una peque\u00f1a demostraci\u00f3n de nuestro proyecto:<\/p>\n\n\n\n<p><strong>Conectado<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Conectado.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Calibrar el tablero<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/c2.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Seleccionar tiempo<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/tiempo.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Piezas mal colocadas<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Mal2.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Movimiento correcto<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Prueba3.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Movimiento incorrecto<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Prueba2.mp4\"><\/video><\/figure>\n\n\n\n<p><strong>Partida terminada<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 848 \/ 480;\" width=\"848\" controls src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Final.mp4\"><\/video><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Introducci\u00f3n Esta proyecto se basa en recrear un ajedrez en el cual se pueda jugar contra la m\u00e1quina. La m\u00e1quina mostrar\u00e1 por medio de una pantalla los movimientos que realiza. Para ello, una c\u00e1mara&#46;&#46;&#46;<\/p>\n","protected":false},"author":8,"featured_media":6414,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-6407","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-proyectos"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Photochess - Proyectos con Arduino.<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Photochess - Proyectos con Arduino.\" \/>\n<meta property=\"og:description\" content=\"Introducci\u00f3n Esta proyecto se basa en recrear un ajedrez en el cual se pueda jugar contra la m\u00e1quina. La m\u00e1quina mostrar\u00e1 por medio de una pantalla los movimientos que realiza. Para ello, una c\u00e1mara&#046;&#046;&#046;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/\" \/>\n<meta property=\"og:site_name\" content=\"Proyectos con Arduino.\" \/>\n<meta property=\"article:published_time\" content=\"2023-05-04T13:51:40+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-05-05T11:34:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\" \/>\n\t<meta property=\"og:image:width\" content=\"588\" \/>\n\t<meta property=\"og:image:height\" content=\"494\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"gdhwsw2\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"gdhwsw2\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"23 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/\"},\"author\":{\"name\":\"gdhwsw2\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/person\\\/7491e54afbe5e7fd53467fccb9c7ce44\"},\"headline\":\"Photochess\",\"datePublished\":\"2023-05-04T13:51:40+00:00\",\"dateModified\":\"2023-05-05T11:34:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/\"},\"wordCount\":1365,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2023\\\/05\\\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\",\"articleSection\":[\"Proyectos\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/\",\"name\":\"Photochess - Proyectos con Arduino.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2023\\\/05\\\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\",\"datePublished\":\"2023-05-04T13:51:40+00:00\",\"dateModified\":\"2023-05-05T11:34:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2023\\\/05\\\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2023\\\/05\\\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png\",\"width\":588,\"height\":494},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/photochess\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Photochess\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"name\":\"Proyectos con Arduino.\",\"description\":\"Blog de proyectos de Arduino de alumnos de la URJC\",\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\",\"name\":\"Universidad Rey Juan Carlos\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"width\":745,\"height\":288,\"caption\":\"Universidad Rey Juan Carlos\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/person\\\/7491e54afbe5e7fd53467fccb9c7ce44\",\"name\":\"gdhwsw2\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g\",\"caption\":\"gdhwsw2\"},\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/author\\\/gdhwsw2\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Photochess - Proyectos con Arduino.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/","og_locale":"es_ES","og_type":"article","og_title":"Photochess - Proyectos con Arduino.","og_description":"Introducci\u00f3n Esta proyecto se basa en recrear un ajedrez en el cual se pueda jugar contra la m\u00e1quina. La m\u00e1quina mostrar\u00e1 por medio de una pantalla los movimientos que realiza. Para ello, una c\u00e1mara&#46;&#46;&#46;","og_url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/","og_site_name":"Proyectos con Arduino.","article_published_time":"2023-05-04T13:51:40+00:00","article_modified_time":"2023-05-05T11:34:50+00:00","og_image":[{"width":588,"height":494,"url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png","type":"image\/png"}],"author":"gdhwsw2","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"gdhwsw2","Tiempo de lectura":"23 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#article","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/"},"author":{"name":"gdhwsw2","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/person\/7491e54afbe5e7fd53467fccb9c7ce44"},"headline":"Photochess","datePublished":"2023-05-04T13:51:40+00:00","dateModified":"2023-05-05T11:34:50+00:00","mainEntityOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/"},"wordCount":1365,"commentCount":0,"publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png","articleSection":["Proyectos"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/","name":"Photochess - Proyectos con Arduino.","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#primaryimage"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png","datePublished":"2023-05-04T13:51:40+00:00","dateModified":"2023-05-05T11:34:50+00:00","breadcrumb":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#primaryimage","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2023\/05\/Captura-de-pantalla-2023-05-04-a-las-14.30.36.png","width":588,"height":494},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/photochess\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/blogs.etsii.urjc.es\/dseytr\/"},{"@type":"ListItem","position":2,"name":"Photochess"}]},{"@type":"WebSite","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","name":"Proyectos con Arduino.","description":"Blog de proyectos de Arduino de alumnos de la URJC","publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization","name":"Universidad Rey Juan Carlos","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","width":745,"height":288,"caption":"Universidad Rey Juan Carlos"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/person\/7491e54afbe5e7fd53467fccb9c7ce44","name":"gdhwsw2","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ed762cea3155134adfbecf1780d8a40c0fe5e4b642859a56b3a2b3611a1ca73a?s=96&d=mm&r=g","caption":"gdhwsw2"},"url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/author\/gdhwsw2\/"}]}},"_links":{"self":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/6407","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/comments?post=6407"}],"version-history":[{"count":17,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/6407\/revisions"}],"predecessor-version":[{"id":6487,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/6407\/revisions\/6487"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media\/6414"}],"wp:attachment":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media?parent=6407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/categories?post=6407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/tags?post=6407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}