micropython-control-motores-dc-l298n-tb6612

Control de motores DC con MicroPython: L298N y TB6612

  • 6 min

Un motor DC es un actuador que gira al aplicarle corriente continua.

Los servomotores están genial para mover un brazo o girar una cámara, pero si queremos crear un vehículo con ruedas, un ventilador o una cinta transportadora, necesitamos motores de corriente continua.

El problema de los motores DC es que son “tontos” y “hambrientos”.

  1. Tontos: Si les das energía, giran. Si les quitas energía, paran (por inercia). No saben en qué posición están.
  2. Hambrientos: Consumen mucha más corriente de la que un pin de un microcontrolador puede dar.

Nunca conectes un motor directamente al GPIO Un pin de ESP32 o Pico entrega como máximo 20mA-40mA. Un motor de juguete pequeño consume 200mA en vacío y puede llegar a 1A bloqueado. Si los conectas directo, quemarás el pin o el procesador instantáneamente.

Para solucionar esto, necesitamos un intermediario: el Driver de Motor.

El concepto de puente H

Para controlar un motor necesitamos dos cosas:

  1. Velocidad: Que controlaremos mediante PWM (encendiendo y apagando rápido la energía).
  2. Dirección: Para invertir el giro, necesitamos invertir la polaridad de los cables.

Como no podemos cambiar los cables físicamente mientras el robot anda, usamos un circuito de transistores llamado Puente H.

Imagina cuatro interruptores. Dependiendo de cuáles cerremos, la corriente fluye de izquierda a derecha (giro horario) o de derecha a izquierda (giro antihorario).

Los drivers más comunes

En el mundo maker existen dos reyes indiscutibles, y ambos se manejan de forma muy similar desde el código.

L298N: El clásico veterano

Es ese módulo rojo grande con un disipador de aluminio.

  • Pros: Barato, robusto, aguanta voltajes altos (hasta 35V).
  • Contras: Tecnología antigua (BJT). Es muy ineficiente. Se “come” unos 2V de la batería solo para funcionar y se calienta mucho.

TB6612FNG / DRV8833: La opción moderna

Son módulos pequeñitos.

  • Pros: Tecnología MOSFET. Muy eficientes, apenas se calientan y aprovechan mejor la batería.
  • Contras: Son más delicados con los voltajes máximos (generalmente hasta 10V-12V).

Si estás alimentando tu robot con pilas o baterías pequeñas (LiPo 1S o 2S), usa siempre un TB6612 o DRV8833. El L298N desperdicia demasiada energía.

Conexión eléctrica

Vamos a suponer una configuración estándar que funciona para ambos drivers. Necesitamos 3 pines del microcontrolador por cada motor (aunque luego veremos cómo optimizarlo a 2).

  • IN1: Controla un lado del puente.
  • IN2: Controla el otro lado.
  • ENA (Enable): Activa o desactiva el motor (a veces se usa para el PWM).

El esquema de cableado IMPRESCINDIBLE:

  1. GND del Driver unido al GND del Microcontrolador. (Sin esto, no funcionará).
  2. Alimentación del motor (VM) a las baterías externas.
  3. Alimentación lógica (VCC) a los 3.3V o 5V de la placa.

Control básico en MicroPython

La lógica para mover el motor es la siguiente tabla de verdad:

IN1IN2Resultado
LowLowParado (Inercia)
HighLowGiro Sentido A
LowHighGiro Sentido B
HighHighFreno (Cortocircuito)

Vamos a implementarlo controlando la velocidad mediante PWM en los pines IN1 e IN2 directamente, lo cual nos permite ahorrar el pin ENA (que podemos conectar físicamente a 5V/3.3V para que esté siempre activo).

Clase MotorDC

Como siempre, en luisllamas.es nos gusta el código limpio y reutilizable. Vamos a crear una clase para gobernar nuestros motores.

from machine import Pin, PWM

class MotorDC:
    def __init__(self, pin_in1, pin_in2, freq=1000):
        """
        :param pin_in1: Pin GPIO conectado a IN1 del driver
        :param pin_in2: Pin GPIO conectado a IN2 del driver
        :param freq: Frecuencia del PWM (1kHz suele ir bien para evitar zumbidos)
        """
        self.pwm1 = PWM(Pin(pin_in1))
        self.pwm2 = PWM(Pin(pin_in2))
        
        self.pwm1.freq(freq)
        self.pwm2.freq(freq)
        
        # Inicializamos parados
        self.stop()

    def forward(self, speed):
        """
        Mueve el motor hacia adelante.
        :param speed: Velocidad en porcentaje (0 a 100)
        """
        duty = self._percentage_to_duty(speed)
        self.pwm1.duty_u16(duty)
        self.pwm2.duty_u16(0)

    def backward(self, speed):
        """
        Mueve el motor hacia atrás.
        :param speed: Velocidad en porcentaje (0 a 100)
        """
        duty = self._percentage_to_duty(speed)
        self.pwm1.duty_u16(0)
        self.pwm2.duty_u16(duty)

    def stop(self):
        """Detiene el motor por inercia (Coast)."""
        self.pwm1.duty_u16(0)
        self.pwm2.duty_u16(0)

    def brake(self):
        """Frena el motor en seco (Short brake)."""
        self.pwm1.duty_u16(65535)
        self.pwm2.duty_u16(65535)
        
    def _percentage_to_duty(self, percentage):
        """Convierte 0-100 a 0-65535"""
        # Limitamos entre 0 y 100
        percentage = max(0, min(percentage, 100))
        return int((percentage / 100) * 65535)
Copied!

Ejemplo de uso

Ahora vamos a poner a prueba nuestro driver haciendo que el motor acelere suavemente, frene y retroceda.

import time
# from motor_dc import MotorDC  <-- Si guardaste la clase en otro archivo

# Pines ejemplo para ESP32: IN1=GPIO26, IN2=GPIO27
motor_izquierdo = MotorDC(26, 27)

print("Acelerando hacia adelante...")
for vel in range(0, 101, 5): # De 0 a 100% en pasos de 5
    motor_izquierdo.forward(vel)
    time.sleep(0.1)

print("Frenando...")
motor_izquierdo.brake()
time.sleep(1)

print("Marcha atrás a media potencia...")
motor_izquierdo.backward(50)
time.sleep(2)

print("Parada libre...")
motor_izquierdo.stop()
Copied!

Problemas comunes y soluciones

Cuando trabajamos con motores, la física nos juega malas pasadas que no ocurren al encender un simple LED.

El microcontrolador se reinicia por brownout

Al arrancar, los motores piden mucha corriente de golpe. Esto puede provocar una caída de tensión momentánea que reinicia tu ESP32 o Pico.

  • Solución: Usa fuentes de alimentación separadas (una para motores, otra para el micro) compartiendo GND.
  • Solución: Pon condensadores electrolíticos grandes (ej. 470uF) en la entrada de alimentación del driver.

El motor hace un ruido agudo y no gira

Si envías una velocidad muy baja (ej. 10%), es posible que la energía no sea suficiente para vencer la fricción inicial, pero la frecuencia del PWM hace vibrar las bobinas.

  • Solución: Aumenta la velocidad mínima de arranque (zona muerta). Rara vez un motor DC barato arranca bien por debajo del 30% de PWM.

Ruido eléctrico

Los motores son generadores de chispas y ruido electromagnético que puede volver loca a tu electrónica.

  • Solución: Suelda condensadores cerámicos pequeños (100nF) entre los terminales del motor y su carcasa.

Dominar los motores DC es el primer paso para construir tu propio rover. Ahora que tenemos movimiento y dirección, lo siguiente será aprender a usar sensores para que nuestro robot no se choque contra las paredes.