I am using an ESP32 with MicroPython to control a motor driver. I have created a class for the motor that allows me to set the motor's power using a setPower method. However, I have encountered an issue where the GPIO pin used to control the motor only activates (sets to "high") if I call setPower(1) inside a while loop. If I try to activate the motor before the loop, the pin does not remain active.
I even added timeouts hoping it was just a boot issue, but that didn't work.
from lib.Driver import *
from time import sleep_ms as delay
delay(3000) # Wait 3 seconds to let the ESP32 boot
p = Motor(PORT_1A) # Create Motor instances
p2 = Motor(PORT_2A)
driver = TB6612FNG(p, p2, STBY_A)
print("Pin activated")
driver.motorB.setPower(1) # Attempt to set power to 1 before the loop
while True:
delay(1000) # Wait 1 second
print("Running...")
Observed Behavior:
- The motor does not activate when driver.motorB.setPower(1) is called outside the while loop.
- If I move driver.motorB.setPower(1) inside the while loop, the motor activates and runs as expected.
- If I remove the while loop completely, the motor activates as well. Here is the version that works correctly:
I thought it was perhaps a problem caused because the Esp32 did not maintain the high state of the pin, but even when I put a 10 second sleep in the loop, the pin does not return to a low state.
This is the code that "works":
from lib.Driver import *
from time import sleep_ms as delay
p = Motor(PORT_1A)
p2 = Motor(PORT_2A)
driver = TB6612FNG(p, p2, STBY_A);
while True:
driver.motorB.setPower(1)
I also thought it was because of my esp's firmware, but I tried with the last two versions: v1.24.1 (2024-11-29) .bin / [.app-bin] / [.elf] / [.map] / [Release notes] (latest) v1.24.0 (2024-10-25) .bin / [.app-bin] / [.elf] / [.map] / [Release notes]
and the same thing happens with both.
This is the code I use to control the TB6612FNG H-bridge:
from machine import Pin, PWM
import time
PORT_1A = [26,25,27]
PORT_2A = [32,4,0]
STBY_A = 33
PORT_1B = [15,16,2]
PORT_2B = [18,19,23]
STBY_B = 17
class Motor:
def __init__(self, *args):
if len(args)==1 and isinstance(args[0], list):
p = args[0]
in1 = p[0]
in2 = p[1]
pwm_pin = p[2]
elif len(args)==3:
in1 = args[0]
in2 = args[1]
pwm_pin = args[2]
else:
raise ValueError("se requieren 3 argumentos o una lista")
"""
Clase para controlar un motor individual.
:param in1: Pin para la dirección IN1.
:param in2: Pin para la dirección IN2.
:param pwm_pin: Pin PWM para la velocidad.
"""
self.in1 = Pin(in1, Pin.OUT)
self.in2 = Pin(in2, Pin.OUT)
self.pwm = PWM(Pin(pwm_pin), freq=1000) # PWM a 1 kHz
self.direction = 1 # Dirección predeterminada
self.stop() # Por seguridad, inicializa el motor detenido
def set_direction(self, direction):
"""
Configura la dirección del motor.
:param direction: 'forward' para dirección normal o 'reverse' para invertir el giro.
"""
if direction in ['forward', 'reverse']:
self.direction = 1 if direction == "forward" else -1
else:
raise ValueError("La dirección debe ser 'forward' o 'reverse'.")
def setPower(self, power):
"""Controla la velocidad y dirección del motor.
Parámetro power: -1 (máxima velocidad atrás) a 1 (máxima velocidad adelante).
"""
power = max(min(1, power), -1)
self.duty_cycle = abs(int(power * 1023)) # Convierte el valor en 0-1023 (PWM)
if power == 0:
# Detener el motor
self.in1.value(0)
self.in2.value(0)
self.pwm.duty(0)
elif power * self.direction > 0:
# Adelante
self.in1.value(1)
self.in2.value(0)
self.pwm.duty(self.duty_cycle)
else:
# Atrás
self.in1.value(0)
self.in2.value(1)
self.pwm.duty(self.duty_cycle)
def stop(self):
"""
Detiene el motor.
"""
self.in1.off()
self.in2.off()
self.pwm.duty(0)
class TB6612FNG:
# def __init__(self, ain1, ain2, pwma, bin1, bin2, pwmb, stby):
# """
# Clase para controlar el controlador TB6612FNG con dos motores.
# :param ain1, ain2, pwma: Pines del Motor A.
# :param bin1, bin2, pwmb: Pines del Motor B.
# :param stby: Pin de Standby (habilitación).
# """
# self.stby = Pin(stby, Pin.OUT)
# self.stby.on() # Activa el controlador (quita Standby)
#
# # Inicialización de los dos motores usando la clase Motor
# self.motorA = Motor(ain1, ain2, pwma)
# self.motorB = Motor(bin1, bin2, pwmb)
def __init__(self, *args):
if len(args)==1 and isinstance(args[0], list):
p = args[0]
if len(args[0])==7:
ain1 = p[0]
ain2 = p[1]
pwma = p[2]
bin1 = p[3]
bin2 = p[4]
pwmb = p[5]
stby = p[6]
else:
raise ValueError("se requieren 7 argumentos correspondientes a los 7 pines")
elif len(args)==7:
ain1 = args[0]
ain2 = args[1]
pwma = args[2]
bin1 = args[3]
bin2 = args[4]
pwmb = args[5]
stby = args[6]
elif len(args)==3:
self.motorA = args[0]
self.motorB = args[1]
self.stby = Pin(args[2], Pin.OUT)
self.stby.on()
else:
raise ValueError("se requieren los 7 pines del driver o 1 lista que los contenga a todos")
"""
Clase para controlar el controlador TB6612FNG con dos motores.
:param ain1, ain2, pwma: Pines del Motor A.
:param bin1, bin2, pwmb: Pines del Motor B.
:param stby: Pin de Standby (habilitación).
"""
if(self.motorA is None):
self.stby = Pin(stby, Pin.OUT)
self.stby.on() # Activa el controlador (quita Standby)
# Inicialización de los dos motores usando la clase Motor
self.motorA = Motor(ain1, ain2, pwma)
self.motorB = Motor(bin1, bin2, pwmb)
def standby_on(self):
"""Activa el modo Standby."""
self.stby.off()
def standby_off(self):
"""Desactiva el modo Standby."""
self.stby.on()