Introducción
En este proyecto, unimos el mundo del software de alto nivel (Python) con el hardware (Arduino) para crear un bot que juega físcamente por nosotros al famoso juego del dinosaurio de Chrome.
Usaremos Python para «ver» la pantalla, analizar cuándo se acerca un obstáculo y tomar la decisión de saltar. Luego, enviará una señal por el puerto serie a un Arduino, que moverá un servomotor (nuestro «dedo» robótico) para presionar la barra espaciadora. Es la introducción perfecta a la visión por computadora y la automatización física.
Materiales Necesarios
- Placa Arduino (Uno, Nano, o similar)
Un Servomotor (un SG90 es perfecto)
Cables Jumper (macho-macho)
Un PC con Python y el IDE de Arduino
Cable USB para el Arduino
(Opcional) Cinta adhesiva de doble cara para fijar el servo.
Esquema de Montaje
El hardware es la parte más sencilla de este proyecto. Solo necesitamos conectar el servo al Arduino.
Montaje Físico: El verdadero reto es mecánico. Debes posicionar el servomotor de forma que su brazo (la hélice de plástico) quede justo encima de la barra espaciadora de tu teclado. La cinta de doble cara puede ser tu mejor aliada para fijarlo temporalmente a la mesa
Conexiones:
Servo Pin Naranja/Amarillo (Señal): ➡️ Pin digital ~9 del Arduino (un pin PWM).
Servo Pin Rojo (VCC): ➡️ Pin 5V del Arduino.
Servo Pin Marrón/Negro (GND): ➡️ Pin GND del Arduino.
Código de arduino
/* * PROYECTO: Bot Dinosaurio (El Dedo) * AUTOR: electronicaparatodos * * CONTROL: Espera un comando ('1') por el puerto serie * para mover un servo y presionar la barra espaciadora. */ #include <Servo.h> Servo miServo; // Crea un objeto servo // --- AJUSTA ESTOS ÁNGULOS --- // Tendrás que calibrar esto según tu montaje int posReposo = 90; // Ángulo cuando no presiona la tecla int posPresion = 60; // Ángulo para presionar la barra espaciadora // ---------------------------- int pinServo = 9; // Pin donde conectaste el servo void setup() { miServo.attach(pinServo); // Conecta el servo al pin 9 miServo.write(posReposo); // Lo pone en posición inicial Serial.begin(9600); // Inicia comunicación serie } void loop() { // Revisa si hay datos llegando desde Python if (Serial.available() > 0) { char comando = Serial.read(); // Lee el comando // Si Python envía '1', saltamos if (comando == '1') { miServo.write(posPresion); // Mueve el servo para presionar delay(150); // Mantiene presionado 150ms miServo.write(posReposo); // Vuelve a la posición de reposo } } }
Código Python
Este script se ejecuta en tu PC. Necesitarás instalar algunas librerías si no las tienes: pip install pyserial mss numpy
Guarda este código en un archivo (ej. dino_bot.py):
import time import serial import mss import numpy as np # --- 1. CONFIGURACIÓN DE COMUNICACIÓN --- # ¡Asegúrate de poner tu puerto COM correcto! try: arduino = serial.Serial('COM5', 9600, timeout=1) print("Conexión con Arduino en COM5 establecida.") time.sleep(2) except serial.SerialException: print("Error: No se pudo conectar al Arduino.") print("Verifica el puerto COM y que no esté en uso.") exit() # --- 2. CONFIGURACIÓN DE CAPTURA (LA PARTE CLAVE) --- # ¡DEBES CALIBRAR ESTO! # Coordenadas de la caja que "vigilará" delante del dino mon = {'top': 379, 'left': 680, 'width': 81, 'height': 52} # --- 3. CONFIGURACIÓN DE DETECCIÓN (LA OTRA CLAVE) --- # ¡DEBES CALIBRAR ESTO! # Valor de píxel medio que separa el "fondo" del "obstáculo" UMBRAL_OBSTACULO = 55 print("Bot iniciado. Abre 'chrome://dino' y haz clic en el juego.") print("Presiona CTRL+C en esta terminal para parar.") def saltar(): """Envía el comando '1' al Arduino para que mueva el servo.""" print("¡Obstáculo detectado! Saltando...") arduino.write(b'1') # --- 4. BUCLE PRINCIPAL --- try: with mss.mss() as sct: while True: # Captura la pantalla en la región definida img = sct.grab(mon) # Convierte la imagen a un array de numpy img_np = np.array(img) # Calcula el color medio de la caja valor_medio = np.mean(img_np[:, :, 0]) # Línea para calibrar (¡muy útil!) print(f"Valor medio detectado: {valor_medio}") # Decisión de saltar (¡LÓGICA CALIBRADA!) # Fondo ~36, Cactus ~78. Saltamos si es MAYOR que 55 if valor_medio > UMBRAL_OBSTACULO: saltar() time.sleep(0.3) # Pausa para no saltar dos veces except KeyboardInterrupt: print("\nBot detenido por el usuario.") finally: arduino.close() print("Conexión con Arduino cerrada.")
Explicación del Código
Sketch de Arduino
#include <Servo.h>: Importa la librería para controlar servos fácilmente.posReposoyposPresion: Estas son las variables clave de calibración mecánica.posReposoes dónde espera el servo,posPresiones el ángulo que presiona la tecla. ¡Tendrás que ajustarlas!Serial.begin(9600): Inicia la comunicación serie, esperando datos de Python.if (Serial.available() > 0): Es la línea más importante. Revisa constantemente si Python ha enviado algo.if (comando == '1'): Si lo que ha enviado es el carácter ‘1’, ejecuta la secuencia de salto.
Script de Python
serial.Serial('COM5', 9600): La línea que conecta Python con Arduino. ¡TuCOMpuede ser diferente!mssynumpy:msses una librería de captura de pantalla increíblemente rápida.numpynos permite hacer cálculos matemáticos (como la media) sobre los píxeles de esa captura de forma muy eficiente.mon = {'top': ...}: Esta es la Región de Interés (ROI). Define el rectángulo exacto de la pantalla que el script vigilará. ¡Esta es la primera gran calibración que debes hacer!UMBRAL_OBSTACULO = 55: Esta es la segunda gran calibración. Es el número «mágico» que le dice al bot qué es «fondo» y qué es «obstáculo».if valor_medio > UMBRAL_OBSTACULO:: Esta es la lógica de decisión. Compara el valor medio de los píxeles en la caja con nuestro umbral. Dependiendo de si el juego está en modo día (fondo blanco) o modo noche (fondo negro), puede que necesites cambiar>por<.
Cómo Calibrar tu Bot
Calibrar la Posición del Servo (Arduino):
Sube el código de Arduino.
Ajusta los valores
posReposoyposPresionen el código de Arduino y vuelve a subirlo.Repite hasta que el servo presione la barra espaciadora perfectamente y regrese sin tocarla.
Calibrar la Región de Interés (ROI) (Python):
Necesitas encontrar las coordenadas
(top, left, width, height)de la caja delante del dinosaurio.Puedes usar un script auxiliar de Python (con
pyautogui.position()) o incluso MS Paint para tomar capturas de pantalla y ver las coordenadas de los píxeles.Actualiza la variable
monen el script de Python.
Calibrar el Umbral de Detección (Python):
Con tu ROI ya configurado, ejecuta el script
dino_bot.py.Abre el juego
chrome://dinoy no juegues.Mira la terminal. Verás una lluvia de números. Anota el valor del FONDO (ej.
36.5).Ahora juega manualmente. Cuando un CACTUS pase por la caja, anota el nuevo número (ej.
78.2).¡Ya tienes tus valores! Tu
UMBRAL_OBSTACULOdebe ser un número justo en medio de esos dos (ej.55).Ajusta la lógica (
<o>) según si el número del cactus es mayor o menor que el del fondo.
Conclusiones y siguientes pasos
¡Y ahí lo tienes! Un bot que interactúa con el mundo real para ganar en un juego virtual. Este proyecto es una base excelente para ideas más complejas.
Para llevarlo al siguiente nivel:
Detección Automática Día/Noche: El script actual fallará si el juego cambia de modo (fondo blanco a negro). ¿Podrías añadir una lógica que primero compruebe el color de fondo y luego ajuste el umbral y la lógica (
<o>) automáticamente?Detección de Pájaros: El bot actual solo salta. No se agacha. ¿Podrías definir una segunda «caja» (ROI) más alta para detectar los pájaros y modificar el servo para que presione la tecla «flecha abajo»?
Material
Aquí os dejamos los materiales que nosotros compramos cuando empezamos. Si quieres darnos una pequeña ayuda puedes comprar desde este link. Gracias por leernos!
- Placa arduino: https://amzn.to/43LM4k4
- Protoboard: https://amzn.to/3LZaZdM
- Cables: https://amzn.to/3K5N3ox
- Servomotores: https://amzn.to/4p4ZuAe
- Pack de lo necesario para empezar: https://amzn.to/3MmuDAs
