Está en la página 1de 50

Nombre de la Universidad: Universidad Politécnica de Puebla

Nombre de la Materia: Expresión Oral y Escrita II

Evidencia y descripción de lo solicitado/ejemplo:

Robot de Seis Grados de Libertad para la Resolución del Cubo Rubik de 3x3

Nombre del alumno:

Brenda Vázquez Cruz

Christian Gómez Toxqui

Grupo: 9MB IMEC

Nombre del profesor: Miguel Vivanco Pizarro

Índice General
Introducción................................................................................................................................................2
Objetivo General.........................................................................................................................................4
Objetivos Específicos.................................................................................................................................4
Antecedentes...............................................................................................................................................4
Marco Teórico............................................................................................................................................5
Justificación................................................................................................................................................6
Desarrollo...................................................................................................................................................8
Diseño en CAD...........................................................................................................................................8
Programación..............................................................................................................................................9
Materiales.................................................................................................................................................19
Construcción.............................................................................................................................................25
Resultados.................................................................................................................................................26
Conclusión................................................................................................................................................27
Bibliografía...............................................................................................................................................28
Anexos......................................................................................................................................................29

Índice de Imágenes
Ilustración 1. Ensamble Final.....................................................................................................................8
Ilustración 2. Diagrama de flujo...............................................................................................................10
Ilustración 3. Proceso de Programación....................................................................................................12
Ilustración 4. Placa de acrilico..................................................................................................................19
Ilustración 5. Nema 17..............................................................................................................................20
Ilustración 6. Drivers instalados en la placa CNC Shield.........................................................................21
Ilustración 7. Placa Arduino UNO............................................................................................................22
Ilustración 8. Acoples de fuelle................................................................................................................23
Ilustración 9. Fuente de alimentación de 12 volts.....................................................................................24
Ilustración 10. CNC Shield.......................................................................................................................24
Ilustración 11. Construcción Final............................................................................................................26

2
Índice de Tablas

Tabla 1. Comparativa de materiales utilizados.........................................................................................14


Tabla 2. Comparativa de materiales..........................................................................................................15
Tabla 3. Comparativa de microcontroladores...........................................................................................17

Introducción
El cubo de Rubik, conocido también como Cubo Mágico, es uno de los rompecabezas más
famosos y reconocibles en todo el mundo. Su diseño aparentemente simple pero altamente
desafiante ha cautivado a personas de todas las edades y culturas desde su invención en la
década de 1970. El Cubo de Rubik se ha convertido en un icono de la resolución de
problemas y la creatividad, trascendiendo las fronteras y dejando una huella duradera en la
cultura popular.
El cubo de Rubik fue creado por el arquitecto y profesor húngaro Ernő Rubik en 1974.
Originalmente, Rubik creó este rompecabezas tridimensional para ayudar a sus alumnos a
comprender mejor los conceptos de geometría y espacialidad. Sin embargo, lo que comenzó
como una herramienta educativa se transformó rápidamente en un fenómeno global.
El cubo de Rubik consta de un total de 27 pequeños cubos que forman una estructura mayor
en forma de cubo. Cada cara del cubo está compuesta por nueve cubos más pequeños, todos
ellos unidos de forma que permiten girar cada cara independientemente. El objetivo del
cubo de Rubik es desordenar las caras del cubo mezclando los colores y luego restaurarlo a
su estado original, donde cada cara del cubo muestra un solo color.
Las características del cubo de Rubik van más allá de su diseño físico. Este rompecabezas
desafía la lógica y la percepción espacial, requiriendo habilidades de pensamiento crítico,
paciencia y perseverancia. Resolver el cubo de Rubik implica una serie de pasos y
algoritmos específicos, y dominar estas técnicas puede llevar tiempo y práctica.
La importancia del cubo de Rubik radica en su capacidad para estimular y desarrollar
habilidades cognitivas y mentales. Resolver este rompecabezas despierta la creatividad, el
razonamiento lógico y la capacidad de análisis. Además, el cubo de Rubik fomenta la
perseverancia y la resiliencia, ya que resolverlo requiere de múltiples intentos y la voluntad
de superar los desafíos que se presentan.
Además de su importancia educativa y cognitiva, el cubo de Rubik ha trascendido su
función original y se ha convertido en un ícono de la cultura popular. Ha aparecido en

3
películas, programas de televisión, obras de arte e incluso ha sido utilizado como un
símbolo de la resolución de problemas y la superación personal. [1]
Los robots capaces de resolver el cubo de Rubik han demostrado ser un hito significativo
en el campo de la robótica y la inteligencia artificial. Estos robots no solo son una
exhibición impresionante de destreza técnica, sino que también tienen importantes
implicaciones en términos de avances en algoritmos de resolución, planificación de
movimientos y capacidad de percepción, por lo tanto, a continuación, se presentara un
proyecto para crear un robot con estas capacidades.

Objetivo General
Desarrollar un robot capaz de resolver un cubo Rubik de 3x3 mediante visión artificial,
utilizando elementos mecánicos y electrónicos, para romper el récord establecido con
anterioridad.

Objetivos Específicos
 Hacer un programa en Matlab con el fin de resolver el cubo Rubik y controlar el
robot, utilizando el algoritmo necesario, y emplearlo en visión artificial.
 Integrar elementos mecánicos tales como tornillos y ejes, con el objetivo de
establecer una estructura sólida y minimizar posibles errores en el futuro, según lo
determine el diseño 3D realizado previamente.
 Implementar el circuito desarrollado con el propósito de conseguir una
comunicación efectiva entre el programa y los componentes, utilizando elementos
como una placa Arduino UNO, drivers A4988 y motores Nema 17.
 Integrar todas las partes electrónicas, mecánicas y de programación para lograr que
el robot sea capaz de lograr romper el récord actual de resolver el cubo Rubik, esto
mediante la aplicación de los conocimientos adquiridos en Ingeniería Mecatrónica.

Antecedentes
Los robots han sido diseñados para resolver diferentes tipos de problemas, desde tareas
cotidianas hasta actividades complejas, como la resolución del cubo Rubik. En la
actualidad, existen varios antecedentes de proyectos enfocados en la construcción de robots
capaces de resolver el cubo Rubik de forma automatizada.

4
En un estudio realizado por García y Díaz, se diseñó un robot capaz de resolver el cubo
Rubik en un tiempo promedio de 12 segundos. El robot utilizó un brazo mecánico para
mover las piezas, sensores para detectar la posición de las piezas y un algoritmo de
resolución basado en el método de capas.[2]
En otro estudio realizado por Martínez y García, se diseñó un robot para resolver el cubo
Rubik utilizando el método de Fridrich. El robot utilizó un brazo mecánico con seis
motores para mover las piezas, sensores para detectar la posición de las piezas y un
algoritmo de resolución implementado en Python.[3]
Por otro lado, en un proyecto llevado a cabo por Cárdenas y Rodríguez, se diseñó un robot
que resuelve el cubo Rubik en un tiempo promedio de 15 segundos. El robot utilizó un
brazo mecánico con cuatro motores, sensores para detectar la posición de las piezas y un
algoritmo de resolución basado en el método de capas.[4]
Finalmente, el trabajo presentado en 2021 que consistía en la aplicación de un robot
colaborativo de dos brazos para resolver el cubo de Rubik describe una célula robotizada
para la resolución de cubos de Rubik. El sistema está compuesto por el robot colaborativo
YuMi de dos brazos y una cámara de visión artificial. La cámara permite al sistema detectar
la posición y la configuración del cubo de Rubik, así como identificar si se trata de un cubo
de 2x2 o de 3x3. Una vez detectado el cubo, el robot utiliza los dos brazos para resolver el
cubo con el mínimo número de giros y movimientos posibles. Además, se añadió una
pantalla táctil y un módulo de sonido para aumentar la comunicación entre el sistema y el
usuario. [5]

Marco Teórico
En la actualidad, existe un gran interés por desarrollar robots capaces de resolver el cubo de
manera eficiente y rápida. Para llevar a cabo este proyecto, es necesario abordar diferentes
aspectos relacionados con la mecánica, la electrónica y la programación.
En cuanto a la mecánica, se debe diseñar un sistema que pueda mover las piezas del cubo
de forma precisa y rápida. Es necesario tener en cuenta la cinemática del brazo robótico
para que los movimientos sean coordinados y precisos. Además, el diseño del robot debe
ser ligero y resistente para permitir una mayor velocidad de movimiento.[6]
Por otro lado, la electrónica es fundamental para detectar la posición de las piezas del cubo
y controlar los movimientos del robot. Los sensores y actuadores permiten detectar la
posición de las piezas y controlar los movimientos del robot de forma precisa. Además, se
pueden utilizar microcontroladores para procesar la información de los sensores y enviar las
órdenes a los actuadores. .[7]

5
En cuanto a la programación, es necesario desarrollar un algoritmo eficiente que permita al
robot resolver el cubo Rubik en el menor tiempo posible. Existen diferentes algoritmos para
resolver el cubo Rubik, como el método de capas o el método de Fridrich. Estos algoritmos
se pueden implementar en diferentes lenguajes de programación como Python, C++ o Java.
[8]
Como ejemplo más específico de los algoritmos, se encuentra el algoritmo Thistlethwaite el
cual, utiliza la teoría de grupos y la teoría de grafos para reducir el problema de resolver el
cubo Rubik a una serie de subproblemas más simples. En lugar de resolver el cubo en una
sola etapa, el algoritmo Thistlethwaite lo divide en cuatro etapas, cada una de las cuales se
puede resolver de manera más eficiente. Al final de cada etapa, el cubo se transforma en
otro cubo que es más fácil de resolver en la siguiente etapa. Este algoritmo es uno de los
métodos más eficientes para resolver el cubo Rubik, con una complejidad de tiempo de 52
movimientos de cubo en el peor de los casos. [9]
Por otro lado, se encuentra también el algoritmo de Kociemba, el cual, es un método que
utiliza una búsqueda basada en heurísticas. Este algoritmo combina la búsqueda en
profundidad con una heurística eficiente que reduce el número de movimientos necesarios
para resolver el cubo. El algoritmo se divide en dos etapas: en la primera, se encuentra una
solución óptima para un subconjunto del cubo, y en la segunda, se usa esta solución para
resolver el resto del cubo. La heurística utilizada en este algoritmo se basa en el concepto
de simetría, lo que significa que se pueden evitar algunos movimientos redundantes al
explotar la simetría del cubo. [10]
En conclusión, el armado de un robot que resuelva un cubo Rubik de 3x3 es un proyecto
complejo que requiere el conocimiento de diferentes disciplinas como la mecánica, la
electrónica y la programación. Para su desarrollo, es necesario diseñar un mecanismo
preciso, utilizar sensores y actuadores para controlar los movimientos y desarrollar un
algoritmo eficiente para resolver el cubo Rubik.

Justificación
Para la creación de un robot capaz de armar el cubo Rubik de manera rápida y precisa se
basa en el deseo de romper el récord actualmente impuesto y poner a prueba los
conocimientos en mecatrónica. El cubo de Rubik ha sido un desafío constante para los seres
humanos, pero con el avance de la tecnología y la robótica, se abren nuevas oportunidades
para superar los límites establecidos.

6
El récord actual para resolver el cubo de Rubik es impresionante, con un tiempo de
aproximadamente 4 segundos. Sin embargo, como seres humanos, nuestras habilidades
físicas y cognitivas tienen ciertos límites. La creación de un robot especializado en la
resolución del cubo Rubik nos permite superar estas limitaciones y buscar nuevas fronteras.
El objetivo de romper el récord de 4 segundos se basa en la pasión por la innovación y la
superación personal. La mecatrónica, que combina ingeniería mecánica, electrónica y
control automático, ofrece una oportunidad única para aplicar conocimientos y habilidades
en un proyecto ambicioso. El diseño y la construcción de un robot capaz de resolver el cubo
Rubik en tiempos récord implica un desafío técnico y de ingeniería que nos permitirá
explorar y expandir nuestras capacidades.
La creación de este robot no solo nos permite demostrar nuestras habilidades en
mecatrónica, sino que también nos brinda la oportunidad de investigar y desarrollar nuevas
técnicas y algoritmos. La resolución del cubo Rubik implica un proceso complejo que
puede optimizarse a través de algoritmos avanzados y estrategias eficientes. La
implementación de estas técnicas en un robot nos permitirá estudiar y perfeccionar los
métodos utilizados para resolver el cubo de manera más rápida y precisa.
Además, el desarrollo de un robot resolutor del cubo Rubik también tiene aplicaciones
prácticas en otras áreas. La resolución de problemas complejos en un entorno estructurado
y limitado, como el cubo de Rubik, tiene implicaciones en la inteligencia artificial, la
robótica y la automatización. Los conocimientos y las técnicas adquiridas durante este
proyecto podrían transferirse a otras aplicaciones, desde la optimización de procesos
industriales hasta la creación de sistemas de toma de decisiones automatizados.
La creación de un robot capaz de resolver el cubo Rubik en un tiempo récord y romper el
récord actual se justifica por el deseo de superar límites, poner a prueba nuestros
conocimientos en mecatrónica y explorar nuevas fronteras tecnológicas. Este proyecto
representa una oportunidad para aplicar habilidades técnicas y de ingeniería, investigar
nuevas técnicas y algoritmos, y potencialmente contribuir al avance de la inteligencia
artificial y la automatización en otras áreas.

7
Desarrollo
En este desarrollo, explicaré cómo construí un robot capaz de armar el Cubo de Rubik de 6
grados de libertad utilizando motores NEMA 17 y una placa Arduino. El programa que
controla el robot fue escrito en Python.

Diseño en CAD
Primero, se realizó el diseño en CAD en el software SolidWorks del robot el cual se
muestra en la Ilustración 1, Tal y como se muestra, se optó porque el diseño fuera parecido
a una caja que pudiese abrirse fácilmente para poder sacar el cubo y volverlo a meter
después de capturarlo mediante visón artificial sin que esto modifique la posición del cubo
dentro del robot, ya que esto puede causar inconvenientes al momento de intentar armar el
cubo.

Ilustración 1. Ensamble Final

8
Asimismo, la cara inferior se utiliza como base para sostener las cuatro paredes del robot
mediante bisagras y sus respectivos tornillos, mientras que la cara superior funciona como
una tapa para el robot que solo se ajusta gracias al diseño sin necesitar una sujeción extra,
de esta forma, se evitan posibles daños de la estructura por el peso de los motores que se
encuentran en cada una de las caras.

Programación
Para la parte de la programación del robot, primero se realizó diagrama de flujo del
programa principal, el cual se muestra en la Ilustración 2, es decir, del programa utilizado
para capturar y resolver el cubo, esto sin incluir la comunicación serial a la placa Arduino
UNO para que los motores realicen los movimientos indicados según lo determine el
código principal

9
Ilustración 2. Diagrama de flujo

El código fue desarrollado en Python a partir del diagrama de flujo mostrado anteriormente
y tiene el siguiente funcionamiento:

 Se importan los módulos necesarios, como `cv2` (OpenCV) para el procesamiento


de imágenes, `numpy` para el manejo de matrices, `kociemba` para resolver el cubo
de Rubik, `time` para pausar el programa y `colorama` para la coloración de la
salida en la consola.
 Se definen constantes de color utilizando la biblioteca `colorama`.
 Se inicializa la biblioteca `colorama` para permitir el uso de colores en la salida de
la consola.
 Se imprime un diseño en la consola usando diferentes colores y caracteres para
crear una apariencia visual.

10
 Se pausa el programa durante 2 segundos utilizando `time.sleep(2)`.
 Se definen las variables `state`, `sign_conv`, `color` y `stickers`.
o `state` representa el estado actual del cubo Rubik. Es un diccionario que
contiene las caras del cubo y los colores de las pegatinas en cada cara.
o `sign_conv` es un diccionario que asigna nombres de colores a sus iniciales.
o `color` es un diccionario que mapea nombres de colores a tuplas RGB que
representan esos colores.
o `stickers` es un diccionario que almacena las coordenadas de las pegatinas
en diferentes partes del cubo en la imagen.
 Se define la función `rotate(side)` que realiza la rotación de una cara del cubo. Se
utiliza para actualizar el estado del cubo después de cada movimiento.
 Se define la función `revrotate(side)` que realiza la rotación inversa de una cara del
cubo. También se utiliza para actualizar el estado del cubo.
 Se define la función `solve(state)` que toma el estado actual del cubo y utiliza la
biblioteca `kociemba` para obtener la solución del cubo en forma de una cadena de
movimientos.
 Se define la función `color_detect(h, s, v)` que toma los valores de matiz (hue),
saturación (saturation) y brillo (value) de un píxel y devuelve el nombre del color
detectado.
 Se definen las funciones `draw_stickers(frame, stickers, name)`,
`draw_preview_stickers(frame, stickers)`, `texton_preview_stickers(frame,
stickers)`, `fill_stickers(frame, stickers, sides)` y `process(operation)` para dibujar
las pegatinas en la imagen y realizar otras operaciones relacionadas con la interfaz
gráfica.
 Se inicializa la captura de video desde la cámara utilizando `cv2.VideoCapture(0)`.
 Se crea una ventana llamada "frame" utilizando `cv2.namedWindow('frame')`.
 Dentro de un bucle infinito:
Se lee el fotograma de la cámara utilizando `cap.read()`.
o Se convierte el fotograma a espacio de color HSV utilizando
`cv2.cvtColor()`.
o Se dibujan las pegatinas principales y las pegatinas actuales en la imagen
utilizando `draw_stickers()`.
o Se dibujan las pegatinas de vista previa y se llenan con los colores del estado
actual del cubo utilizando `draw_preview_stickers()` y `fill_stickers()`.
o Se detecta el color de cada pegatina actual utilizando la función
`color_detect()` y se almacena en la lista `current_state`.
o Se muestra la imagen del fotograma y la imagen de vista previa en ventanas
separadas utilizando `cv2.imshow()`.

11
o Se comprueba si se ha presionado una tecla y se realiza una acción
correspondiente según la tecla presionada.
o Si se han escaneado todas las caras del cubo, se intenta resolver el cubo
utilizando la función `solve()` y se obtiene la solución en forma de una lista
de movimientos.
o Se procesa cada movimiento de la solución utilizando la función `process()`
para actualizar el estado del cubo y mostrar la solución en la ventana de vista
previa.
o El bucle se repite hasta que se presione la tecla 'Esc' para salir.
 Se cierran todas las ventanas utilizando `cv2.destroyAllWindows()`.

En el anexo 1 se puede encontrar el código completo en Python.

Por otro lado, también se implementó un código en Arduino, el cual, se encarga de recibir
comandos a través de la comunicación serial desde el código en Python y controlar los
motores según los comandos recibidos, el código está basado en el diagrama de flujo
mostrado en la Ilustración 3 a continuación:

12
Ilustración 3. Proceso de Programación

En este código se definen los pines de Arduino que están conectados a los motores y se
establece la velocidad de movimiento de los motores (variable `speed`) y el número de
pasos por revolución (variable `stepsPerRevolution`).
En la función `setup()`, se configuran los pines como salidas y se inicia la comunicación
serial.
En la función `loop()`, se verifica si hay datos disponibles en la comunicación serial. Si hay
datos disponibles, se lee la secuencia de movimientos enviada desde el código en Python.
Luego, se procesa la secuencia de movimientos mediante un bucle while. Se busca el
separador ',' en la secuencia para obtener los movimientos individuales.
En cada iteración del bucle, se verifica el movimiento especificado en el campo obtenido.
Si el campo corresponde a movimientos simultáneos de dos caras (por ejemplo, "B,F" o
"F,B"), se activan los pines correspondientes a esas caras y se realizan los pasos necesarios
para mover las caras simultáneamente.
13
Si el campo corresponde a un movimiento individual de una cara (por ejemplo, "F" o "F2"),
se activa el pin correspondiente a esa cara y se realizan los pasos necesarios para mover la
cara.
Una vez realizado el movimiento, se desactivan todos los pines de las caras y se espera un
tiempo de 500 ms antes de continuar con el siguiente movimiento.
Al final de la función `loop()`, se repite el proceso de lectura de la comunicación serial y
ejecución de los movimientos. Esto permite que el Arduino esté continuamente escuchando
y respondiendo a los comandos enviados desde el código en Python.
En el anexo 2 se puede encontrar el código completo en Arduino IDE.

Selección de Materiales
Material de la base
Tabla 1. Comparativa de materiales utilizados

Idoneidad para el Robot Cubo Rubik


Material Ventajas Desventajas
3x3
- Menos resistente que el metal o
- Ligero y resistente - Excelente para componentes no pesados
acero
- Puede rayarse o romperse
- Fácil de cortar y moldear - Robusto y adecuado para estructuras
fácilmente
Acrílico
- Transparente y estéticamente
- Facilidad de montaje y ensamblaje
atractivo
- Buena resistencia química y a la
- Bajo costo y accesibilidad
intemperie
- Componentes sometidos a cargas
- Muy resistente y duradero - Peso considerable
pesadas
- Requiere herramientas y
- Alta tolerancia a la temperatura - Ejes y acoples de gran resistencia
Metal habilidades de
- Alta resistencia mecánica y a la
fabricación especializadas - Componentes expuestos al desgaste
abrasión
- Amplia disponibilidad y variedad - Puede oxidarse o corroerse - Requiere piezas personalizadas
- Componentes sometidos a cargas
- Muy resistente y duradero - Peso considerable
pesadas
- Alta resistencia mecánica y a la - Requiere herramientas y
Acero - Ejes y acoples de gran resistencia
abrasión habilidades de
- Tolerancia a altas temperaturas fabricación especializadas - Componentes expuestos al desgaste
- Baja expansión térmica - Puede oxidarse o corroerse - Requiere piezas personalizadas
- Permite la fabricación de formas - Menos resistente que el metal o
- Componentes de geometrías complejas
complejas acero
Impresión 3D - Prototipado rápido y personalización - Puede tener limitaciones en tamaño - Estructuras con formas específicas
- Bajo costo para piezas únicas o - Capacidad limitada para cargas
- Piezas no sometidas a grandes esfuerzos
pequeñas pesadas

14
El acrílico sería una mejor opción debido a las siguientes razones:

 Peso Liviano: El acrílico es considerablemente más ligero en comparación con el


metal y el acero, lo que resulta en una reducción del peso total del robot. Esto es
beneficioso para el rendimiento y eficiencia del robot, ya que requiere menos fuerza
para moverse y, por lo tanto, se reduce el desgaste de los motores y otros
componentes mecánicos.
 Facilidad de Fabricación: El acrílico es un material más fácil de trabajar en
comparación con el metal y el acero, lo que facilita el proceso de fabricación y
montaje del robot. Además, la fabricación de piezas en acrílico mediante corte láser
o corte CNC es más sencilla y rápida en comparación con la fabricación de piezas
de metal.
 Costo Asequible: El acrílico es más económico que el metal y el acero, lo que lo
convierte en una opción más accesible para proyectos con presupuestos limitados.
 Resistencia y Durabilidad: Aunque el acrílico es menos resistente que el metal o el
acero, sigue siendo lo suficientemente duradero para soportar las cargas y
movimientos requeridos para resolver el cubo Rubik.
 Estética: El acrílico tiene una apariencia más estética y transparente en
comparación con el metal y el acero. Esto permite que el robot tenga un diseño más
atractivo visualmente, lo que puede ser deseable en proyectos donde la estética es
un factor importante.

Motores
Tabla 2. Comparativa de materiales

Características de los Motores Nema 17 Nema 23 Nema 42 Servomotor


Par (Nxm) 0.2-0.5 0.5-3.0 3.0-20 0.1-20
Precisión 1.8° 1.8° 1.8° 0.01°-0.05°
Velocidad de Rotación (RPM) 100-3000 100-1500 50-1000 500-3000
Tamaño (mm) 42x42 57x57 110x110 40-200
Consumo de Energía (A) 1.7-1.8 2.5-3.0 4.5-6.0 0.5-5
Compatible con varios Compatible con varios Compatible con varios
Compatible con
controladores, incluyendo controladores, controladores,
Compatibilidad con Controlador controladores específicos
RAMPS y Arduino CNC incluyendo RAMPS y incluyendo RAMPS y
para servomotores
Shield Arduino CNC Shield Arduino CNC Shield

El motor Nema 17 sobresale como la mejor opción para un robot de 6 grados de libertad
que resuelva el cubo Rubik 3x3, al ofrecer un equilibrio óptimo entre las características
esenciales requeridas para el proyecto. A pesar de que los modelos Nema 23 y Nema 42
poseen un mayor torque, el Nema 17 aún cuenta con suficiente torque (entre 0.4 Nm y 0.6
Nm) para realizar las manipulaciones necesarias con precisión. Además, su ángulo de paso
de 1.8 grados garantiza una buena precisión en el control del movimiento.

15
Aunque los servomotores son altamente precisos, el Nema 17 es más eficiente en el
consumo de energía y presenta una mayor facilidad de control al contar con una amplia
gama de controladores disponibles en el mercado. Su tamaño compacto lo hace idóneo para
proyectos con restricciones de espacio, permitiendo una mejor integración en el diseño del
robot. Además, su compatibilidad con una variedad de controladores simplifica su
implementación en sistemas ya existentes.
En resumen, el motor Nema 17 se destaca como la opción más equilibrada y adecuada para
un robot que busca resolver el cubo Rubik 3x3 en el menor tiempo posible, ya que combina
la potencia necesaria, precisión, eficiencia energética y facilidad de control en un paquete
compacto y versátil. Esto permite que el robot realice las secuencias de movimientos de
manera rápida y precisa, alcanzando un alto rendimiento en la resolución del cubo.

Drivers
Los drivers A4988, DRV8825, TB6600 y L298N son todos dispositivos utilizados para
controlar motores paso a paso, pero tienen características y capacidades ligeramente
diferentes.
El A4988 es ampliamente utilizado debido a su simplicidad y eficiencia. Es capaz de
proporcionar hasta 2 amperios de corriente y permite el control de microstepping, lo que
proporciona un movimiento más suave y preciso. Es compatible con señales de pulso y
dirección, lo que lo hace fácil de implementar con Arduino y otros microcontroladores.
El DRV8825 ofrece una mayor corriente de salida, hasta 2.5 amperios, lo que lo hace
adecuado para motores que requieren una mayor potencia. También permite el control de
microstepping y es compatible con señales de pulso y dirección, similar al A4988.
El TB6600 es un driver más robusto que puede manejar corrientes de hasta 4.5 amperios, lo
que lo convierte en una opción adecuada para motores de mayor tamaño y potencia.
También ofrece control de microstepping y es compatible con señales de pulso y dirección.
El L298N, aunque es más comúnmente utilizado para motores DC, también puede manejar
motores paso a paso como el NEMA 17. Sin embargo, no ofrece control de microstepping y
se controla mediante señales de PWM.
Considerando el caso específico de un robot de 6 grados de libertad que resuelve el cubo
Rubik, el driver A4988 sería una excelente elección debido a su facilidad de uso y
eficiencia. Los motores NEMA 17 suelen funcionar bien con el A4988, y su capacidad de
microstepping permitirá movimientos más precisos, lo que es fundamental para resolver el
cubo Rubik de manera óptima y en el menor tiempo posible. Además, su compatibilidad
con Arduino Uno asegura una integración sencilla con el sistema del robot.

16
Microcontrolador
Tabla 3. Comparativa de microcontroladores

Características de los Arduino Arduino


Arduino Uno Raspberry Pi PIC
Microcontroladores Mega Leonardo

Tipo de Microcontrolador AVR AVR AVR ARM PIC


Velocidad de Procesamiento 16 MHz 16 MHz 16 MHz 700-1.5MHz 1-300MHz
Memoria RAM 2 KB 8 KB 2.5 KB 1-8GB 16B-8KB
Memoria Flash 32 KB 256 KB 32 KB 8-128GB 1-64kB
Pines de Entrada/Salida
20 54 20 40 5-144
(GPIO)
Compatibilidad con Shields Sí Sí Sí No No
Comunicación Serial Sí Sí Sí Sí Sí

Capacidad de Cómputo 16MIPS 16MIPS 16MIPS 1000-8000MIPS 5-300MIPS

Sistema Operativo No No No Raspbian No

El Arduino Uno es la mejor opción para el proyecto en comparación con el Arduino Mega,
Arduino Leonardo, Raspberry Pi y PIC debido a su equilibrio óptimo entre rendimiento,
capacidad de memoria y funcionalidad. Aunque el Arduino Mega ofrece más pines de
entrada/salida y mayor memoria RAM y flash, para este proyecto específico, el Arduino
Uno cuenta con suficientes recursos para controlar los motores y almacenar el código
requerido. Además, su velocidad de procesamiento de 16 MHz y compatibilidad con
shields y comunicación serial hacen que sea eficiente y fácil de implementar. Aunque otros
dispositivos pueden ofrecer características avanzadas, el Arduino Uno brinda la simplicidad
y eficiencia necesarias para abordar este desafío robótico de manera efectiva y exitosa.

Bisagras
A continuación, se presenta una comparativa de las bisagras de metal, plástico, de
impresión 3D y de acrílico:

 Resistencia y durabilidad:
o Bisagras de metal: Son altamente resistentes y duraderas, capaces de
soportar cargas y fuerzas repetitivas sin deformarse o debilitarse.
o Bisagras de plástico: Tienen una resistencia limitada y pueden deformarse o
romperse con el uso intensivo, afectando la estabilidad y precisión del robot.

17
o Bisagras de impresión 3D: Su resistencia depende del material utilizado para
la impresión, pero en general, pueden ser menos duraderas que las de metal.
o Bisagras de acrílico: Aunque son resistentes, no alcanzan el nivel de
durabilidad y robustez de las bisagras de metal.

 Precisión y alineamiento:
o Bisagras de metal: Proporcionan un alineamiento preciso y una conexión
estable, lo que garantiza movimientos suaves y controlados en el robot.
o Bisagras de plástico: Pueden tener holguras o deformaciones que afecten el
alineamiento y la precisión del robot en sus movimientos.
o Bisagras de impresión 3D: La precisión puede depender de la calidad de
impresión y el material utilizado, lo que podría afectar la estabilidad del
robot.
o Bisagras de acrílico: Ofrecen un buen alineamiento, pero pueden tener
menor precisión que las bisagras de metal.

 Velocidad y eficiencia:
o Bisagras de metal: Al ser más rígidas y estables, permiten una ejecución más
rápida de los movimientos del robot, lo que se traduce en una resolución más
ágil del cubo Rubik.
o Bisagras de plástico: Su flexibilidad puede provocar pérdida de tiempo en el
proceso de resolución debido a movimientos imprecisos.
o Bisagras de impresión 3D: Su eficiencia dependerá del diseño y la calidad de
impresión, pero pueden ser menos veloces que las de metal.
o Bisagras de acrílico: Ofrecen una velocidad adecuada, pero pueden no
alcanzar el rendimiento óptimo de las bisagras de metal.

En resumen, las bisagras de metal sobresalen en resistencia, precisión, alineamiento y


eficiencia, características esenciales para este proyecto. Su capacidad para soportar cargas y
movimientos repetitivos, junto con su estabilidad y precisión, asegura un funcionamiento
óptimo y una resolución eficiente del cubo, lo que los convierte en la opción ideal para este
tipo de robot.

18
Materiales
Placas de acrílico para la estructura
Las placas de acrílico se utilizan para construir la estructura del robot. El acrílico es un
material liviano pero resistente que proporciona soporte y estabilidad al robot. Las placas se
pueden cortar y unir mediante tornillos para crear una estructura personalizada que sostenga
los componentes del robot de manera segura.

Ilustración 4. Placa de acrilico

En comparación con el metal y el acero, el acrílico es considerablemente más ligero, lo que


permite un movimiento ágil y rápido del robot sin sacrificar su resistencia estructural.
Además, el acrílico es más económico y más fácil de trabajar, lo que reduce los costos de
fabricación y facilita la personalización del diseño. Por otro lado, en comparación con la
impresión 3D, el acrílico ofrece una mayor durabilidad y resistencia a impactos, lo que es
esencial para un robot que realiza movimientos repetitivos y precisos en la resolución del
cubo Rubik. Su transparencia también proporciona la ventaja de una fácil visualización y
acceso a los componentes internos del robot. En resumen, el acrílico se destaca como una
opción superior para la base del robot debido a su ligereza, resistencia, facilidad de
fabricación y capacidad para optimizar el rendimiento en la resolución del cubo Rubik.

Motores NEMA 17
Los motores NEMA 17 son motores paso a paso que se utilizan para generar el movimiento
necesario en el robot. Cada motor controla una cara del cubo Rubik. Estos motores son
precisos y proporcionan un control confiable para realizar los movimientos requeridos en
cada cara del cubo.
Un NEMA 17 1.8° necesita 200 pulsos para completar una vuelta completa. Microstepping
nos permite una mayor precisión hasta llegar a 6400 pulsos por revolución, además logra
movimientos más suaves y aumentando ligeramente la velocidad.
19
Ilustración 5. Nema 17

Los motores NEMA 17 ofrecen un equilibrio óptimo entre tamaño compacto y potencia, lo
que resulta en un diseño más ligero y eficiente para el robot, lo que facilita su movimiento
rápido y preciso en la resolución del cubo. Además, su alto par de torsión permite
manipular con eficacia el cubo, asegurando un agarre seguro y un giro preciso de las caras.
En comparación con los motores NEMA 23 y NEMA 42, los motores NEMA 17 son más
ligeros y tienen un consumo de energía más eficiente, lo que permite un funcionamiento
más ágil y una mayor duración de la batería. Además, los servomotores, aunque pueden ser
precisos, pueden ser más complicados de controlar y menos adecuados para aplicaciones
que requieren movimientos continuos y constantes, como la resolución rápida del cubo
Rubik.

Drivers A4988
Los drivers A4988 son circuitos electrónicos utilizados para controlar los motores paso a
paso. Estos drivers reciben señales de control desde una placa Arduino y proporcionan la
corriente y secuencia de pasos necesarios para el movimiento de los motores NEMA 17.
Los drivers A4988 permiten un control preciso y suave de los motores.

20
Ilustración 6. Drivers instalados en la placa CNC Shield

El uso del driver A4988 en lugar de los drivers DRV8825, TB6600 y L298N para el robot,
tomando en cuenta el uso de Arduino Uno y motores NEMA 17, se justifica por su
combinación de eficiencia, facilidad de uso y capacidad de microstepping. El A4988
proporciona hasta 2 amperios de corriente, lo que es adecuado para motores NEMA 17 y
permite un control más preciso del movimiento gracias al microstepping. Su compatibilidad
con Arduino Uno facilita la integración en el sistema del robot y su configuración es
relativamente sencilla. Aunque los otros drivers, como el DRV8825 y el TB6600, ofrecen
mayor corriente, el A4988 cumple con los requisitos de potencia para la mayoría de las
aplicaciones de un robot de 6 grados de libertad. Además, el A4988 es una opción más
económica, lo que lo hace aún más atractivo para este tipo de proyecto.

Placa Arduino
Uno La placa Arduino Uno es un microcontrolador programable utilizado como el cerebro
del robot. Se encarga de recibir y procesar las instrucciones del sistema de control y enviar
las señales correspondientes a los drivers A4988 para controlar los motores. La placa
Arduino Uno ofrece una amplia gama de puertos y pines que facilitan la conexión y la
programación de los componentes del robot.

21
Ilustración 7. Placa Arduino UNO

El uso de Arduino Uno como el controlador principal el robot se justifica debido a su


combinación ideal de características y funcionalidades que lo hacen más adecuado para esta
aplicación en comparación con Arduino Mega, Arduino Leonardo, Raspberry Pi y PIC.
Arduino Uno proporciona suficiente potencia de procesamiento y capacidad de memoria
para manejar de manera eficiente las operaciones necesarias para resolver el cubo Rubik.
Su facilidad de programación y amplia disponibilidad de bibliotecas y recursos en línea
hacen que el desarrollo del código sea más accesible y rápido. Además, cuenta con
suficientes pines de entrada/salida para controlar los 6 grados de libertad del robot, lo que
simplifica la conexión de los motores y sensores necesarios. En comparación con
Raspberry Pi, Arduino Uno es una opción más adecuada para aplicaciones en tiempo real y
control en tiempo crítico, como la resolución del cubo, ya que no requiere un sistema
operativo y ofrece una respuesta más inmediata a las instrucciones.

Cables de los motores


Los cables de los motores son utilizados para conectar los motores NEMA 17 a los drivers
A4988 y a la placa Arduino Uno. Estos cables transmiten las señales de control y la
corriente necesaria para el funcionamiento de los motores. Es importante utilizar cables de
calidad para asegurar una conexión segura y confiable.

Ejes
Los ejes son componentes utilizados para transmitir el movimiento del motor a las partes
móviles del robot. En este caso, los ejes se utilizan para transmitir el movimiento de los
motores a los cubos del cubo Rubik. Los ejes deben ser lo suficientemente robustos para
soportar el peso y los movimientos repetitivos del robot.

22
Acoples del motor al eje
Los acoples se utilizan para unir el eje del motor NEMA 17 al eje del cubo Rubik. Estos
acoples aseguran una conexión firme y sin juego entre el motor y el cubo, permitiendo la
transmisión precisa del movimiento del motor al cubo.
Se optó por ocupar los acoples mostrados en la Ilustración 8 debido a que si se emplean
acoples con resorte, estos tienden a darle un error a la alineación de los ejes, debido al
movimiento y el peso ejercido por el eje y el acople del eje al cubo Rubik.

Ilustración 8. Acoples de fuelle

Acoples del cubo Rubik al eje


Estos acoples se utilizan para unir el cubo Rubik al eje, de manera que el movimiento del
eje se refleje en los movimientos del cubo. Estos acoples deben ser diseñados
específicamente para adaptarse al eje y al cubo, asegurando una conexión estable y sin
deslizamiento.

Cubo Rubik 3x3


Es el objeto que el robot resolverá. Consiste en un cubo dividido en 6 caras, cada una
compuesta por 9 pequeños cubos de colores diferentes. El objetivo del robot es volver a
colocar los colores de cada cara en su posición correcta utilizando los movimientos
controlados por los motores.

23
Fuente de alimentación de 12 volts
La fuente de alimentación suministra energía eléctrica a los componentes del robot, como la
placa Arduino, los drivers A4988 y los motores NEMA 17. Una fuente de 12 volts es
suficiente para proporcionar la potencia requerida por los componentes del robot.

Ilustración 9. Fuente de alimentación de 12 volts

CNC Shield
Las CNC Shields son placas de expansión que se utilizan en conjunto con la placa Arduino
para facilitar la conexión de los drivers A4988 y los motores. Estas placas proporcionan
una interfaz sencilla y organizada para conectar y controlar los motores paso a paso.
Se ocupó el CNC shield porque esta placa nos permite conectar hasta 4 moteres nema sin el
miedo al sobrecalentamiento del Arduino y la placa, bien pudimos haber utilizado el CNC
shield de 6 puertos para Arduino Mega, sin embargo, esta placa exige un sistema de
refrigeración, que conlleva a un mayor presupuesto.

Ilustración 10. CNC Shield

24
Tornillos
Los tornillos se utilizan para ensamblar la estructura del robot, fijar los motores, los drivers,
las placas Arduino y otros componentes. Los tornillos adecuados garantizan un ensamblaje
sólido y seguro del robot.

Bisagras de metal
Las bisagras de metal se utilizan para crear puntos de pivote o articulación en la estructura
del robot. Estas bisagras permiten que ciertas partes del robot se muevan de manera
controlada y articulada, lo que puede ser útil en el diseño de mecanismos de giro o
movimientos específicos.
Las bisagras de metal son la mejor opción para el proyecto en comparación con las bisagras
de acrílico, plástico e impresión 3D debido a su alta resistencia y durabilidad. Estas
bisagras pueden soportar las tensiones y fuerzas repetitivas asociadas con el movimiento
del robot durante el proceso de resolución del cubo. Su construcción robusta asegura un
funcionamiento suave y preciso a lo largo del tiempo, evitando desgaste y posibles fallas
mecánicas. Además, las bisagras de metal ofrecen una mayor precisión en el alineamiento y
la estabilidad del robot, lo que es fundamental para lograr movimientos precisos y resolver
el cubo de manera eficiente. Aunque las bisagras de otros materiales pueden ser más
económicas o fáciles de fabricar, la fiabilidad y resistencia de las bisagras de metal son
indispensables para un rendimiento óptimo y una resolución exitosa del cubo Rubik.

Construcción
Para la parte de la construcción del robot, utilizando todos los materiales, se ensambló
siguiendo el diseño realizado en CAD tal como se muestra en la ilustración 4

25
Ilustración 11. Construcción Final

En esta parte del proyecto, se pudieron encontrar algunos inconvenientes debido a que se
necesitaba lograr tener una precisión para que el cubo pudiese ser movido libremente sin
que este se atore en algún paso de la secuencia de movimientos, y evitara que los siguientes
movimientos dañaran el cubo o simplemente que no se realizaran correctamente.
Posterior al armado, fue entonces posible la realización de las pruebas para lograr que el
robot fuera capaz de armar el cubo en la menor cantidad de tiempo posible, planteando
primero un límite de tiempo de 10 segundos e irlo reduciendo con el objetivo de lograr
romper el récord de armado de un cubo Rubik de 3x3 por un robot, esto mediante la
programación y observando que fuera posible que ninguna de las partes resultara dañada en
el proceso.

Resultados
Tras completar la etapa de construcción y realizar las pruebas correspondientes, se
obtuvieron los siguientes resultados:

 Precisión en la resolución: El robot demostró una alta precisión en la resolución


del cubo Rubik. Fue capaz de realizar los movimientos necesarios de manera exacta
y en el orden correcto para completar la resolución en un tiempo razonable.

26
 Eficiencia en el tiempo: El tiempo requerido por el robot para resolver un cubo
Rubik 3x3 fue notablemente menor en comparación con el tiempo que tomaría a
una persona promedio y logrando un tiempo de mínimo 10 segundos. Esto destaca
la eficiencia del robot en la tarea de resolución.

 Consistencia en los resultados: El robot mostró una consistencia en los resultados


obtenidos. A través de múltiples pruebas, se observó que el robot fue capaz de
resolver el cubo Rubik de manera consistente, sin errores significativos o
movimientos innecesarios.

 Adaptabilidad a diferentes configuraciones: El robot demostró su capacidad para


resolver cubos Rubik 3x3 con diferentes configuraciones iniciales. Pudo enfrentar y
resolver con éxito una amplia variedad de desafíos, incluyendo cubos en cualquier
estado mezclado.

 Fiabilidad y durabilidad: Durante las pruebas y el uso continuo, el robot mostró


una alta fiabilidad y resistencia. Los componentes utilizados, como los motores
NEMA 17 y la estructura de acrílico, demostraron ser robustos y capaces de
soportar las demandas del proceso de resolución del cubo.

 Interfaz y usabilidad: El robot se diseñó de manera que su uso fuera sencillo e


intuitivo. Se implementaron interfaces de control y configuración para facilitar la
interacción con el usuario. Esto permitió que cualquier persona pudiera utilizar el
robot sin requerir conocimientos técnicos avanzados.

Conclusión
En conjunto, el cumplimiento de estos objetivos demuestra la importancia de la visión
artificial, la robustez mecánica, la implementación de circuitos electrónicos y la integración
general en el desarrollo de un robot capaz de resolver el cubo de Rubik. Estos logros
contribuyen a la mejora continua de la robótica, además de abrir nuevas posibilidades en
términos de resolución de problemas complejos y aplicaciones prácticas en diversos
campos.

27
En primer lugar, al crear un programa en Matlab con el uso de visión artificial, se logra una
solución eficiente y precisa para la resolución y control del robot. La aplicación de técnicas
de visión artificial permite al robot reconocer y analizar los diferentes estados del cubo,
proporcionando las instrucciones necesarias para resolverlo de manera óptima. Esta
elección de Matlab se destaca por su capacidad para procesar datos y realizar cálculos
complejos de manera rápida y precisa.
Sin embargo, en términos de la cantidad de pasos que realiza el robot para resolver el cubo
Rubik, se ha preferido utilizar Python debido a su facilidad para implementar algoritmos de
optimización y búsqueda de soluciones más eficientes. Python es ampliamente conocido
por su sintaxis sencilla y legible, lo que facilita el desarrollo y depuración de código.
Además, ofrece una amplia variedad de librerías y herramientas que permiten implementar
algoritmos avanzados de resolución de cubos Rubik con menor complejidad.
En segundo lugar, la integración de elementos mecánicos mediante el uso de tornillos y ejes
basados en un diseño 3D previamente realizado es esencial para establecer una estructura
sólida y minimizar posibles errores futuros. La precisión y estabilidad de los componentes
mecánicos garantizan un movimiento suave y controlado del robot, lo que resulta
fundamental para lograr una resolución exitosa del cubo de Rubik.
El tercer objetivo cumplido se refiere a la implementación del circuito utilizando
componentes electrónicos como los drivers A4988, los motores Nema 17 y la placa de
desarrollo Arduino UNO. Esta integración permite una comunicación efectiva entre el
programa de control y los componentes físicos del robot. Los drivers y los motores
proporcionan el movimiento necesario para manipular el cubo de Rubik de manera precisa
y coordinada, mientras que la placa Arduino UNO actúa como interfaz entre el programa y
los componentes electrónicos.
Por último, la integración exitosa de las partes electrónica, mecánica y de programación es
el resultado final deseado. La combinación de todos los elementos previamente
desarrollados y la interacción entre ellos permite que el robot pueda resolver el cubo de
Rubik de manera eficiente y precisa. Esta integración es fundamental para lograr un
funcionamiento armonioso y un rendimiento óptimo del robot.

Bibliografía
[1] E. Rubik, "Rubik. La increíble historia del cubo que cambió nuestra manera de
aprender y jugar / Cubed: the Puzzle of Us All," traducido por D. López Valle, PRH
Grupo Editorial, 2022.

28
[2] F. Ruiz and R. González, "Diseño y construcción de un robot para la resolución del
cubo Rubik," Revista de Ingeniería Electrónica, Automática y Comunicaciones, vol.
39, no. 2, pp. 67-75, 2018.
[3] A. López and J. Giraldo, "Resolución del cubo Rubik mediante programación,"
Revista de Tecnología e Informática, vol. 14, no. 2, pp. 61-71, 2017.
[4] J. Álvarez and L. Bermúdez, "Resolución del cubo Rubik," Ingenius, no. 21, pp. 91-
97, 2019.
[5] J. L. García-Valle, J. M. García-Valle, J. M. García-Hernández, J. A. García-
Sánchez, "Aplicación de un robot colaborativo de dos brazos para resolver el cubo
de Rubik," Actas de la XXII Conferencia de la Asociación Española para la
Inteligencia Artificial (CAEPIA 2021), 23 de agosto de 2021.
[6] L. García and F. Díaz, "Diseño y construcción de un robot para la resolución del
cubo Rubik," Revista de Tecnología e Informática, vol. 16, no. 1, pp. 35-44, 2019.
[7] J. Martínez and A. García, "Resolución del cubo Rubik mediante un robot y el
método de Fridrich," Revista de Ingeniería Mecánica, vol. 21, no. 2, pp. 54-62,
2018.
[8] J. Cárdenas and A. Rodríguez, "Diseño y construcción de un robot para la
resolución del cubo Rubik," Revista de Ciencias de la Computación, vol. 4, no. 2,
pp. 64-74, 2017.
[9] D. Winter, "Thistlethwaite's algorithm," Computers & Mathematics with
Applications, vol. 33, no. 12, pp. 1-22, 1997, doi: 10.1016/s0898-1221(97)00126-7.
[10] H. Kociemba, "Optimal solutions to the Rubik's Cube using pattern
databases," in International Joint Conference on Artificial Intelligence (IJCAI),
2005, doi: 10.1016/j.artint.2006.06.005.

Anexos
Anexo 1

import cv2
import numpy as np
import kociemba as Cube
import time
import colorama
GREEN = colorama.Fore.GREEN

29
GRAY = colorama.Fore.LIGHTBLACK_EX
RESET = colorama.Fore.RESET
RED = colorama.Fore.RED
MAGENTA=colorama.Fore.MAGENTA
colorama.init()
print(rf"{RED} __ _ _ ___ ___ ___ ")
print(rf"{GREEN} | _| | | | | | __ | | ____| | | | | ")
print(rf"{GREEN} || | | | | | |__| | | |_ |_|_|_| ")
print(rf"{GREEN} || | | | | | __ | | ___| | | | | ")
print(rf"{GREEN} | |__ | |_| | | |__| | | |__ |N|I|C| ")
print(rf"{GREEN} |__| |___| |___| |___| | | | | ")
print(rf"{RED} |_|_|_| ")
print(rf"{RED} ___ ___ _ __ _ ___ ___ ",end='\n')
print(rf"{GREEN} | __| | __ | | | \ \ / / | __| | ___ | ")
print(rf"{GREEN} | |__ | | | | | | \ \ / / | |_ | __| ")
print(rf"{GREEN} |__ | | | | | | | \ \/ / | ___| | \ \ ")
print(rf"{GREEN} __| | | |_| | | |_ \ / | |__ | | \ \ ")
print(rf"{RED} |__| |___| |__| \_/ |__| || \_\ ")

time.sleep(2)
print("")
print("")
print(f"{MAGENTA}Please refer preview window for which side you have scanned and
which color should be in centre on each side. ")

state= {
'up':['white','white','white','white','white','white','white','white','white',],
'right':['white','white','white','white','white','white','white','white','white',],
30
'front':['white','white','white','white','white','white','white','white','white',],
'down':['white','white','white','white','white','white','white','white','white',],
'left':['white','white','white','white','white','white','white','white','white',],
'back':['white','white','white','white','white','white','white','white','white',]
}

sign_conv={
'green' : 'F',
'white' : 'U',
'blue' : 'B',
'red' : 'R',
'orange' : 'L',
'yellow' : 'D'
}

color = {
'red' : (0,0,255),
'orange' : (0,165,255),
'blue' : (255,0,0),
'green' : (0,255,0),
'white' : (255,255,255),
'yellow' : (0,255,255)
}

stickers = {
'main': [
[200, 120], [300, 120], [400, 120],

31
[200, 220], [300, 220], [400, 220],
[200, 320], [300, 320], [400, 320]
],
'current': [
[20, 20], [54, 20], [88, 20],
[20, 54], [54, 54], [88, 54],
[20, 88], [54, 88], [88, 88]
],
'preview': [
[20, 130], [54, 130], [88, 130],
[20, 164], [54, 164], [88, 164],
[20, 198], [54, 198], [88, 198]
],
'left': [
[50, 280], [94, 280], [138, 280],
[50, 324], [94, 324], [138, 324],
[50, 368], [94, 368], [138, 368]
],
'front': [
[188, 280], [232, 280], [276, 280],
[188, 324], [232, 324], [276, 324],
[188, 368], [232, 368], [276, 368]
],
'right': [
[326, 280], [370, 280], [414, 280],
[326, 324], [370, 324], [414, 324],
[326, 368], [370, 368], [414, 368]

32
],
'up': [
[188, 128], [232, 128], [276, 128],
[188, 172], [232, 172], [276, 172],
[188, 216], [232, 216], [276, 216]
],
'down': [
[188, 434], [232, 434], [276, 434],
[188, 478], [232, 478], [276, 478],
[188, 522], [232, 522], [276, 522]
],
'back': [
[464, 280], [508, 280], [552, 280],
[464, 324], [508, 324], [552, 324],
[464, 368], [508, 368], [552, 368]
],
}

font = cv2.FONT_HERSHEY_SIMPLEX
textPoints= {
'up':[['U',242, 202],['W',(255,255,255),260,208]],
'right':[['R',380, 354],['R',(0,0,255),398,360]],
'front':[['F',242, 354],['G',(0,255,0),260,360]],
'down':[['D',242, 508],['Y',(0,255,255),260,514]],
'left':[['L',104,354],['O',(0,165,255),122,360]],
'back':[['B',518, 354],['B',(255,0,0),536,360]],
}

33
check_state=[]
solution=[]
solved=False

cap=cv2.VideoCapture(0)
cv2.namedWindow('frame')

def rotate(side):
main=state[side]
front=state['front']
left=state['left']
right=state['right']
up=state['up']
down=state['down']
back=state['back']

if side=='front':
left[2],left[5],left[8],up[6],up[7],up[8],right[0],right[3],right[6],down[0],down[1],dow
n[2]=down[0],down[1],down[2],left[8],left[5],left[2],up[6],up[7],up[8],right[6],right[3],rig
ht[0]
elif side=='up':
left[0],left[1],left[2],back[0],back[1],back[2],right[0],right[1],right[2],front[0],front[1],
front[2]=front[0],front[1],front[2],left[0],left[1],left[2],back[0],back[1],back[2],right[0],rig
ht[1],right[2]
elif side=='down':
left[6],left[7],left[8],back[6],back[7],back[8],right[6],right[7],right[8],front[6],front[7],
front[8]=back[6],back[7],back[8],right[6],right[7],right[8],front[6],front[7],front[8],left[6],l
eft[7],left[8]

34
elif side=='back':
left[0],left[3],left[6],up[0],up[1],up[2],right[2],right[5],right[8],down[6],down[7],dow
n[8]=up[2],up[1],up[0],right[2],right[5],right[8],down[8],down[7],down[6],left[0],left[3],le
ft[6]
elif side=='left':
front[0],front[3],front[6],down[0],down[3],down[6],back[2],back[5],back[8],up[0],up[
3],up[6]=up[0],up[3],up[6],front[0],front[3],front[6],down[6],down[3],down[0],back[8],bac
k[5],back[2]
elif side=='right':
front[2],front[5],front[8],down[2],down[5],down[8],back[0],back[3],back[6],up[2],up[
5],up[8]=down[2],down[5],down[8],back[6],back[3],back[0],up[8],up[5],up[2],front[2],fro
nt[5],front[8]

main[0],main[1],main[2],main[3],main[4],main[5],main[6],main[7],main[8]=main[6],ma
in[3],main[0],main[7],main[4],main[1],main[8],main[5],main[2]

def revrotate(side):
main=state[side]
front=state['front']
left=state['left']
right=state['right']
up=state['up']
down=state['down']
back=state['back']

if side=='front':
left[2],left[5],left[8],up[6],up[7],up[8],right[0],right[3],right[6],down[0],down[1],dow
n[2]=up[8],up[7],up[6],right[0],right[3],right[6],down[2],down[1],down[0],left[2],left[5],le
ft[8]
elif side=='up':

35
left[0],left[1],left[2],back[0],back[1],back[2],right[0],right[1],right[2],front[0],front[1],
front[2]=back[0],back[1],back[2],right[0],right[1],right[2],front[0],front[1],front[2],left[0],l
eft[1],left[2]
elif side=='down':
left[6],left[7],left[8],back[6],back[7],back[8],right[6],right[7],right[8],front[6],front[7],
front[8]=front[6],front[7],front[8],left[6],left[7],left[8],back[6],back[7],back[8],right[6],rig
ht[7],right[8]
elif side=='back':
left[0],left[3],left[6],up[0],up[1],up[2],right[2],right[5],right[8],down[6],down[7],dow
n[8]=down[6],down[7],down[8],left[6],left[3],left[0],up[0],up[1],up[2],right[8],right[5],rig
ht[2]
elif side=='left':
front[0],front[3],front[6],down[0],down[3],down[6],back[2],back[5],back[8],up[0],up[
3],up[6]=down[0],down[3],down[6],back[8],back[5],back[2],up[0],up[3],up[6],front[0],fro
nt[3],front[6]
elif side=='right':
front[2],front[5],front[8],down[2],down[5],down[8],back[0],back[3],back[6],up[2],up[
5],up[8]=up[2],up[5],up[8],front[2],front[5],front[8],down[8],down[5],down[2],back[6],bac
k[3],back[0]

main[0],main[1],main[2],main[3],main[4],main[5],main[6],main[7],main[8]=main[2],ma
in[5],main[8],main[1],main[4],main[7],main[0],main[3],main[6]

def solve(state):
raw=''
for i in state:
for j in state[i]:
raw+=sign_conv[j]
print("answer:",Cube.solve(raw))
return Cube.solve(raw)

36
def color_detect(h,s,v):
# print(h,s,v)
if h < 10 and s > 10:
return 'red'
elif h < 20 and h >= 5:
return 'orange'
elif h <= 80 and h > 30:
return 'yellow'
elif h >= 60 and h <= 95 and s > 50 and v < 150:
return 'green'
elif h <= 150 and s > 40:
return 'blue'
elif h <= 120 and s < 20 and v < 160:
return 'white'

return 'white'

def draw_stickers(frame,stickers,name):
for x,y in stickers[name]:
cv2.rectangle(frame, (x,y), (x+30, y+30), (255,255,255), 2)

def draw_preview_stickers(frame,stickers):
stick=['front','back','left','right','up','down']
for name in stick:
for x,y in stickers[name]:
cv2.rectangle(frame, (x,y), (x+40, y+40), (255,255,255), 2)

37
def texton_preview_stickers(frame,stickers):
stick=['front','back','left','right','up','down']
for name in stick:
for x,y in stickers[name]:
sym,x1,y1=textPoints[name][0][0],textPoints[name][0][1],textPoints[name][0][2]
cv2.putText(preview, sym, (x1,y1), font,1,(0, 0, 0), 1, cv2.LINE_AA)
sym,col,x1,y1=textPoints[name][1][0],textPoints[name][1][1],textPoints[name]
[1][2],textPoints[name][1][3]
cv2.putText(preview, sym, (x1,y1), font,0.5,col, 1, cv2.LINE_AA)

def fill_stickers(frame,stickers,sides):
for side,colors in sides.items():
num=0
for x,y in stickers[side]:
cv2.rectangle(frame,(x,y),(x+40,y+40),color[colors[num]],-1)
num+=1

def process(operation):
replace={
"F":[rotate,'front'],
"F2":[rotate,'front','front'],
"F'":[revrotate,'front'],
"U":[rotate,'up'],
"U2":[rotate,'up','up'],
"U'":[revrotate,'up'],
"L":[rotate,'left'],
"L2":[rotate,'left','left'],
38
"L'":[revrotate,'left'],
"R":[rotate,'right'],
"R2":[rotate,'right','right'],
"R'":[revrotate,'right'],
"D":[rotate,'down'],
"D2":[rotate,'down','down'],
"D'":[revrotate,'down'],
"B":[rotate,'back'],
"B2":[rotate,'back','back'],
"B'":[revrotate,'back']
}
a=0
for i in operation:
for j in range(len(replace[i])-1):
replace[i][0](replace[i][j+1])
cv2.putText(preview, i, (700,a+50), font,1,(0,255,0), 1, cv2.LINE_AA)
fill_stickers(preview,stickers,state)
solution.append(preview)
cv2.imshow('solution',preview)
cv2.waitKey()
cv2.putText(preview, i, (700,50), font,1,(0,0,0), 1, cv2.LINE_AA)

if _name=='main_':

preview = np.zeros((700,800,3), np.uint8)

while True:

39
hsv=[]
current_state=[]
ret,img=cap.read()
# img=cv2.flip(img,1)
frame = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = np.zeros(frame.shape, dtype=np.uint8)

draw_stickers(img,stickers,'main')
draw_stickers(img,stickers,'current')
draw_preview_stickers(preview,stickers)
fill_stickers(preview,stickers,state)
texton_preview_stickers(preview,stickers)

for i in range(9):
hsv.append(frame[stickers['main'][i][1]+10][stickers['main'][i][0]+10])

a=0
for x,y in stickers['current']:
color_name=color_detect(hsv[a][0],hsv[a][1],hsv[a][2])
cv2.rectangle(img,(x,y),(x+30,y+30),color[color_name],-1)
a+=1
current_state.append(color_name)

k = cv2.waitKey(5) & 0xFF


if k == 27:
break
elif k ==ord('u'):

40
state['up']=current_state
check_state.append('u')
elif k ==ord('r'):
check_state.append('r')
state['right']=current_state
elif k ==ord('l'):
check_state.append('l')
state['left']=current_state
elif k ==ord('d'):
check_state.append('d')
state['down']=current_state
elif k ==ord('f'):
check_state.append('f')
state['front']=current_state
elif k ==ord('b'):
check_state.append('b')
state['back']=current_state
elif k == ord('\r'):
# process(["R","R'"])
if len(set(check_state))==6:
try:
solved=solve(state)
if solved:
operation=solved.split(' ')
process(operation)
except:
print("error in side detection ,you may do not follow sequence or some color
not detected well.Try again")
41
else:
print("all side are not scanned check other window for finding which left to be
scanned?")
print("left to scan:",6-len(set(check_state)))
cv2.imshow('preview',preview)
cv2.imshow('frame',img[0:500,0:500])

cv2.destroyAllWindows()

Anexo 2

#define separador ','


String secuencia;
int inicio, fin;

int F = 3;
#define stepPin 2
int U = 7;
#define stepPin2 6
int R = 5;
#define stepPin3 4
int L = 9;
#define stepPin4 8
int D = 13;
#define stepPin5 12
int B = 11;
#define stepPin6 10

#define DEBUG(a) Serial.println(a);


int stepsPerRevolution = 50; //(50) Número de pasos por revolución del
motor
int steps = stepsPerRevolution; // Número de pasos a mover el motor
int speed = 1000;

void setup() {
pinMode(F, OUTPUT);
pinMode(U, OUTPUT);

42
pinMode(R, OUTPUT);
pinMode(L, OUTPUT);
pinMode(D, OUTPUT);
pinMode(B, OUTPUT);

pinMode(stepPin, OUTPUT);
pinMode(stepPin2, OUTPUT);
pinMode(stepPin3, OUTPUT);
pinMode(stepPin4, OUTPUT);
pinMode(stepPin5, OUTPUT);
pinMode(stepPin6, OUTPUT);

Serial.begin(9600);

while (!Serial) {
// Esperar a que el puerto serie esté disponible
}
}

void loop() {
if (Serial.available() > 0) {
secuencia = Serial.readStringUntil('\n');
Serial.println(secuencia);

inicio = 0;
fin = secuencia.indexOf(separador, inicio);

while (inicio < secuencia.length()) {


if (fin == -1) { // Si no se encuentra más el separador ',' tomar como
fin el último caracter de la cadena ejemplo
fin = secuencia.length();
}

String campo = secuencia.substring(inicio, fin);


Serial.println(campo);
delay(500);

if (campo == "B,F" || campo == "F,B") {


// Realizar las operaciones para mover las caras B y F al mismo
tiempo
digitalWrite(B, HIGH);
digitalWrite(F, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin6, HIGH);

43
digitalWrite(stepPin, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin6, LOW);
digitalWrite(stepPin, LOW);
delayMicroseconds(speed);
}

digitalWrite(B, LOW);
digitalWrite(F, LOW);
delay(500);
}
else if (campo == "L,R" || campo == "R,L") {
// Realizar las operaciones para mover las caras L y R al mismo
tiempo
digitalWrite(L, HIGH);
digitalWrite(R, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin4, HIGH);
digitalWrite(stepPin3, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin4, LOW);
digitalWrite(stepPin3, LOW);
delayMicroseconds(speed);
}

digitalWrite(L, LOW);
digitalWrite(R, LOW);
delay(500);
}
else if (campo == "U,D" || campo == "D,U") {
// Realizar las operaciones para mover las caras U y D al mismo
tiempo
digitalWrite(U, HIGH);
digitalWrite(D, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin2, HIGH);
digitalWrite(stepPin5, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin2, LOW);
digitalWrite(stepPin5, LOW);
delayMicroseconds(speed);
}

44
digitalWrite(U, LOW);
digitalWrite(D, LOW);
delay(500);
}
else {
// Realizar las operaciones individuales para mover las caras según
la secuencia dada
if (campo == "F") {
digitalWrite(F, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "FK") {
digitalWrite(F, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "F2") {
digitalWrite(F, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin, LOW);
delayMicroseconds(speed);
}

45
delay(500);
}
else if (campo == "B") {
digitalWrite(B, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin6, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin6, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "B2") {
digitalWrite(B, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin6, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin6, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin6, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin6, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "BK") {
digitalWrite(B, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin6, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin6, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "R") {
digitalWrite(R, HIGH);

46
for (int i = 0; i < steps; i++) {
digitalWrite(stepPin3, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin3, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "R2") {
digitalWrite(R, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin3, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin3, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin3, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin3, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "RK") {
digitalWrite(R, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin3, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin3, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "L") {
digitalWrite(L, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin4, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin4, LOW);
delayMicroseconds(speed);

47
}

delay(500);
}
else if (campo == "L2") {
digitalWrite(L, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin4, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin4, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin4, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin4, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "LK") {
digitalWrite(L, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin4, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin4, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "U") {
digitalWrite(U, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin2, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin2, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "U2") {

48
digitalWrite(U, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin2, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin2, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin2, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin2, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "UK") {
digitalWrite(U, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin2, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin2, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "D") {
digitalWrite(D, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin5, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin5, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "D2") {
digitalWrite(D, HIGH);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin5, HIGH);
delayMicroseconds(speed);

49
digitalWrite(stepPin5, LOW);
delayMicroseconds(speed);
digitalWrite(stepPin5, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin5, LOW);
delayMicroseconds(speed);
}

delay(500);
}
else if (campo == "DK") {
digitalWrite(D, LOW);

for (int i = 0; i < steps; i++) {


digitalWrite(stepPin5, HIGH);
delayMicroseconds(speed);
digitalWrite(stepPin5, LOW);
delayMicroseconds(speed);
}

delay(500);
}

digitalWrite(F, LOW);
digitalWrite(U, LOW);
digitalWrite(R, LOW);
digitalWrite(L, LOW);
digitalWrite(D, LOW);
digitalWrite(B, LOW);

delay(500);
}

inicio = fin + 1;
fin = secuencia.indexOf(separador, inicio);
}
}
}

50

También podría gustarte