Dinosaurio con python y servo

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.

  • posReposo y posPresion: Estas son las variables clave de calibración mecánica. posReposo es dónde espera el servo, posPresion es 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. ¡Tu COM puede ser diferente!

  • mss y numpy: mss es una librería de captura de pantalla increíblemente rápida. numpy nos 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 posReposo y posPresion en 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 mon en 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://dino y 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_OBSTACULO debe 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!