Motor DC y puente en H

Vamos a explicar como funciona un motor de corriente continua (CC) o DC (Direct Current), como funciona un motor paso a paso, (o Stepper Motor), y como usar un motor DC con un puente en H.
Motor DC o CC:
Es una máquina que convierte energía eléctrica en mecánica, provocando un movimiento rotatorio, gracias a la acción de un campo magnético.
Generalmente tiene devanados que se mueven en un campo magnético que fluctua de norte a sur, varias veces por revolución. Cuando por los cables del devanado circula corriente eléctrica se desarrolla una fuerza siguiendo la ecuación de Lorentz. Esta fuerza es proporcional a la corriente y al campo magnético.
Las ventajas de este tipo de motores son:
- Son más silenciosos
- Operación libre de vibraciones
- Buena eficiencia
- Muy fáciles de controlar: Aceleran si la tensión aumenta, y se vuelven más lentos si la tensión se reduce.
Motor paso a paso o Stepper Motor:
Son motores que convierten impulsos eléctricos en desplazamientos angulares discretos, es decir, giran una cantidad de grados (pasos) dependiendo de sus entradas de control.
Sus ventajas principales son:
- Precisión
- Repetitividad en cuanto al posicionamiento
Al igual que los motores DC, los paso a paso están formados por 2 partes:
El estator , que como su nombre indica, es la parte que se queda estática y donde están las bobinas. y es la parte que no se mueve (, de ahí el nombre de estator). La diferencia con el de corriente continua, es que en el caso de los paso a paso, el estator tiene unas muescas que van a quedar imantadas cuando circule la corriente por las bobinas.
La parte que gira se llama rotor, y está formado por unos imanes que se alternan entre norte/sur.
La idea fundamental es que cuando se imantan las bobinas, los imanes son atraídos por las muescas, y el motor queda firme en su posición.
Un ejemplo muy claro para este tipo de motores, son las impresoras 3D.
Ejemplo de uso motores DC:
En nuestro caso, hemos decidido utilizar 2 motores DC para mover un robot. Hemos querido usar motores corriente continua porque nos permiten avanzar más rápido, y no requerimos de tanta precisión en la posición.
Sin embargo, en el circuito que vamos a preparar para usarlos, no disponemos de tensiones negativas, por lo que sólo podriamos hacer girar los motores en un sentido, y por tanto sólo podriamos avanzar el robot en una dirección. Para solventar esto vamos a usar un puente en H. El nombre proviene de la típica representación gráfica del circuito.
Un puente H se construye con 4 interruptores (mecánicos o mediante transistores).Cuando S1 y S4 están cerrados, se aplica una tensión positiva en el motor, haciéndolo girar en un sentido.
Mientras que si los que están cerrados son S2 y S3, la corriente circulará en sentido contrario, de tal manera que el giro del motor será en sentido opuesto al de la figura anterior.
En esta entrada vamos a utilizar el puente en H njm2670d2, puesto que nos permite controlar desde el mismo encapsulado 2 motores DC simultaneamente.
Tiene el siguiente esquema:
El programa en Python para utilizar ambos motores, y el puente en H puede quedar del siguiente modo:
# -*- coding: utf-8 -*-
#################################################
# #
# Motors control module #
# Authors: Ismael Tobar and Raquel Muñoz #
# #
#################################################
#----Libraries
import sys
import RPi.GPIO as GPIO
import threading
from time import sleep
MAX_DUTY = 100
MIN_DUTY = 30 #It's 30 because with a lower voltage the motors don't move
POWER_VOLTAGE = 0.7 #constant to convert percentage (or pwm duty) to voltage
FREQ = 50
#Motor pins
INA1 = 20
INA2 = 21
INB1 = 12
INB2 = 16
EN_A = 9
EN_B = 10
#pwm signals of each input of the motors
pwm_ina1 = 0
pwm_ina2 = 0
pwm_inb1 = 0
pwm_inb2 = 0
motors_not_used = True
initial = 0
#status variables
DISCONNECTED = 0
CONNECTED_OK = 1
CONNECTED_ERROR = 2
status = DISCONNECTED
def setup():
global initial
global status
try:
GPIO.setmode(GPIO.BCM)
GPIO.setup(INA1, GPIO.OUT)
GPIO.setup(INA2, GPIO.OUT)
GPIO.setup(INB1, GPIO.OUT)
GPIO.setup(INB2, GPIO.OUT)
GPIO.setup(EN_A, GPIO.OUT)
GPIO.setup(EN_B, GPIO.OUT)
if initial == 0:
print("Motors: Setup")
initial = 1
status = CONNECTED_OK
except Exception as e:
print("Motors: Error in setup.")
status = CONNECTED_ERROR
#Forward Instruction
def fd(power):
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
global status
try:
d = powerToDuty(power)
if MIN_DUTY <= d <= MAX_DUTY:
setup()
GPIO.output(EN_A, True)
GPIO.output(EN_B, True)
pwm_ina2 = GPIO.PWM(INA2, FREQ)
pwm_inb1 = GPIO.PWM(INB1, FREQ)
pwm_ina1 = GPIO.PWM(INA1, FREQ)
pwm_inb2 = GPIO.PWM(INB2, FREQ)
pwm_ina2.start(d)
pwm_inb1.start(d)
pwm_ina1.start(0)
pwm_inb2.start(0)
except Exception as e:
clean()
print("Motors: Error fordward thread")
status = CONNECTED_ERROR
#Backward Instruction
def bd(power):
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
global status
try:
d = powerToDuty(power)
print(power)
if MIN_DUTY <= d <= MAX_DUTY:
setup()
GPIO.output(EN_A, True)
GPIO.output(EN_B, True)
pwm_ina1=GPIO.PWM(INA1, FREQ)
pwm_inb2=GPIO.PWM(INB2, FREQ)
pwm_ina2 = GPIO.PWM(INA2, FREQ)
pwm_inb1 = GPIO.PWM(INB1, FREQ)
pwm_ina1.start(d)
pwm_inb2.start(d)
pwm_ina2.start(0)
pwm_inb1.start(0)
except Exception as e:
clean()
print("Motors: Error backward thread")
status = CONNECTED_ERROR
#Turn left Instruction
def lt(power):
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
global status
try:
d = powerToDuty(power)
if MIN_DUTY <= d <= MAX_DUTY:
setup()
GPIO.output(EN_A, True)
GPIO.output(EN_B, True)
pwm_ina2=GPIO.PWM(INA2, FREQ)
pwm_inb2=GPIO.PWM(INB2, FREQ)
pwm_ina1=GPIO.PWM(INA1, FREQ)
pwm_inb1=GPIO.PWM(INB1, FREQ)
pwm_ina2.start(d)
pwm_inb2.start(d)
pwm_ina1.start(0)
pwm_inb1.start(0)
except Exception as e:
clean()
print("Motors: Error left thread")
status = CONNECTED_ERROR
#Turn right Instruction
def rt(power):
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
global status
try:
d = powerToDuty(power)
if MIN_DUTY <= d <= MAX_DUTY:
setup()
GPIO.output(EN_A, True)
GPIO.output(EN_B, True)
pwm_ina1 =GPIO.PWM(INA1, FREQ)
pwm_inb1=GPIO.PWM(INB1, FREQ)
pwm_ina2=GPIO.PWM(INA2, FREQ)
pwm_inb2=GPIO.PWM(INB2, FREQ)
pwm_ina1.start(d)
pwm_inb1.start(d)
pwm_ina2.start(0)
pwm_inb2.start(0)
except Exception as e:
clean()
print("Motors: Error right thread")
status = CONNECTED_ERROR
#It cleans the GPIO of the enines and stops the pwm signals
def clean_and_ENA_setup():
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
pwm_ina1.stop()
pwm_ina2.stop()
pwm_inb1.stop()
pwm_inb2.stop()
GPIO.setup(EN_A, GPIO.OUT)
GPIO.setup(EN_B, GPIO.OUT)
GPIO.output(EN_A, False)
GPIO.output(EN_B, False)
GPIO.cleanup(EN_A)
GPIO.cleanup(EN_B)
GPIO.cleanup(INA1)
GPIO.cleanup(INA2)
GPIO.cleanup(INB1)
GPIO.cleanup(INB2)
#It only stops the pwm signals
def clean():
global pwm_ina1
global pwm_ina2
global pwm_inb1
global pwm_inb2
global motors_not_used
motors_not_used = False
pwm_ina1.stop()
pwm_ina2.stop()
pwm_inb1.stop()
pwm_inb2.stop()
GPIO.output(EN_A, False)
GPIO.output(EN_B, False)
def turn_left_90():
tim = 0.0
left(52)
while (tim < 2):
sleep(0.1)
tim += 0.1
stop()
def turn_right_90():
right(52)
tim = 0.0
while (tim < 2):
sleep(0.1)
tim += 0.1
stop()
#convert power indicated to pwm duty of the signal
def powerToDuty(p):
if 0 <= p <= 100:
return (p*POWER_VOLTAGE + MIN_DUTY)
def rt_90():
global status
try:
h = threading.Thread(target=turn_right_90)
h.start()
except Exception as e:
clean_and_ENA_setup()
print("Motors: Error starting turn_right_90 thread")
status = CONNECTED_ERROR
def lt_90():
global status
try:
h = threading.Thread(target=turn_left_90)
h.start()
except Exception as e:
clean_and_ENA_setup()
print("Motors: Error starting turn_left_90 thread")
status = CONNECTED_ERROR
def forward(power):
global status
try:
h = threading.Thread(target=bd, args=(power, ))
h.start()
print("Motors: forward", power)
except Exception as e:
clean_and_ENA_setup()
print("Motors: Error starting backward thread")
status = CONNECTED_ERROR
def backward(power):
global status
try:
h = threading.Thread(target=fd, args=(power, ))
h.start()
print("Motors: backward", power)
except Exception as e:
print("Motors: Error starting forward thread")
status = CONNECTED_ERROR
def left(power):
global status
try:
h = threading.Thread(target=lt, args=(power, ))
h.start()
print("Motors: left", power)
except Exception as e:
print("Motors: Error starting left thread")
status = CONNECTED_ERROR
def right(power):
global status
try:
h = threading.Thread(target=rt, args=(power, ))
h.start()
print("Motors: fright", power)
except Exception as e:
print("Motors: Error starting right thread")
status = CONNECTED_ERROR
def stop():
clean_and_ENA_setup()
print("Motors: stop")
if __name__ == "__main__":
terminate = False #finish the while()
# if run directly we'll just create an instance of the class and output
option = 6
while terminate == False:
sleep(0.1)
option = input('Enter: 1 -> Forward; 2 -> Backward; 3 -> Right; 4 -> Left; 5 -> Stop (0 to exit) : ')
if option == 0:
clean_and_ENA_setup()
terminate = True
elif (1 <= option <= 4):
power = input('Enter power (1 to 100) : ') #the power is asked
if option == 1:
forward(power)
elif option == 2:
backward(power)
elif option == 3:
right(power)
else:
left(power)
elif option == 5:
stop()
GPIO.cleanup()
print('Motors: Exit motors')
Si te ha interesado esta entrada, puedes ver nuestro vehículo robotizado que hemos desarrollado utilizando estos motores.