Electrónica y Programación en Personal
«Si no se soluciona con un script en Python entonces no es viable»

por Yeison Cardona el 30 de noviembre de 2011 a las 21:16 UTC
Reciclando una vieja impresora le he podido extraer unos motores paso a paso, lo primero que pensé fué: cómo lo conecto con Pinguino?, así que reseñaré esta práctica con un motor de esta naturaleza y Pinguino, posteriormente una interfaz con la computadora para manipularlo desde la linea de comandos de Python.

El motor paso a paso es un dispositivo electromecánico que convierte una serie de impulsos eléctricos en desplazamientos angulares discretos, lo que significa es que es capaz de avanzar una serie de grados (paso) dependiendo de sus entradas de control. El motor paso a paso se comporta de la misma manera que un conversión digital-analógica y puede ser gobernado por impulsos procedentes de sistemas lógicos.

Este motor presenta las ventajas de tener alta precisión y repetibilidad en cuanto al posicionamiento.


Tipo de motor
Ya se ha dicho que es un motor paso a paso, pero existen dos tipos: bipolares y unipolares en esta ocasión hablaremos de los unipolares ya que son los mas simples de controlar.



Controlador
El controlador es el mediador, es la interfaz entre la parte lógica (pinguino) y el motor, en el caso de un motor bipolar el controlador no sería más que un puente H, en el caso de un motor unipolar el controlador ideal es un ULN2003A , el cual es una array de 8 transistores tipo Darlington capaces de manejar cargas de hasta 500mA.



Pasos
En el caso de los motores paso a paso unipolares podemos usar tres secuencias diferentes:

Secuencia Normal: Esta es la secuencia más usada y la que generalmente recomienda el fabricante. Con esta secuencia el motor avanza un paso por vez y debido a que siempre hay al menos dos bobinas activadas, se obtiene un alto torque de paso y de retención.

Paso
Bobina A
Bobina B
Bobina D
Bobina D

1
HIGH
HIGHLOWLOW
2
LOWHIGHHIGHLOW
3
LOW
LOWHIGHHIGH
4
HIGHLOWLOWHIGH




Secuencia del tipo wave drive: En esta secuencia se activa solo una bobina a la vez. En algunos motores esto brinda un funcionamiento mas suave. La contrapartida es que al estar solo una bobina activada, el torque de paso y retención es menor.

Paso
Bobina A
Bobina B
Bobina D
Bobina D

1
HIGH
LOWLOWLOW
2
LOWHIGHLOWLOW
3
LOW
LOWHIGHLOW
4
LOWLOWLOWHIGH




Secuencia del tipo medio paso: En esta secuencia se activan las bobinas de tal forma de brindar un movimiento igual a la mitad del paso real. Para ello se activan primero 2 bobinas y luego solo 1 y así sucesivamente. Como vemos en la tabla la secuencia completa consta de 8 movimientos en lugar de 4.

Paso
Bobina A
Bobina B
Bobina D
Bobina D

1
HIGH
LOWLOWLOW
2
HIGHHIGHLOWLOW
3
LOW
HIGHLOWLOW
4
LOWHIGHHIGHLOW
5
LOWLOWHIGHLOW
6
LOWLOWHIGHHIGH
7
LOWLOWLOWHIGH
8
HIGHLOWLOWHIGH





Conexión con Pinguino
El uso del ULN2003 nos facilita enormemente el trabajo, ya que no necesitaremos de nada más aparte de una fuente, en nuestro caso 12v.




Código en Pinguino

En este ejemplo el motor simplemente girará en un solo sentido durante la ejecución del código.
//Movimiento constante en un motor paso a paso unipolar.
//Código probado en un motor de 200 pasos y polarizado a con +12v.

//Función para ejecutar un paso, y fijar la pausa 
void paso(int bA, int bB, int bC, int bD, int pause){
 digitalWrite(7,bA);
 digitalWrite(6,bB);
 digitalWrite(5,bC); 
 digitalWrite(4,bD);
 delay(pause);
 }

void setup(){
 //Los pines que controlaran las bobinas
 pinMode(7,OUTPUT);
 pinMode(6,OUTPUT);
 pinMode(5,OUTPUT);
 pinMode(4,OUTPUT);
 }

void loop(){
 //Iniciamos secuencia de medio paso (8 pasos)
 //El valor 15 indica la pausa que hará en cada paso
 paso(1,0,0,0,15);
 paso(1,1,0,0,15);
 paso(0,1,0,0,15);
 paso(0,1,1,0,15);
 paso(0,0,1,0,15);
 paso(0,0,1,1,15);
 paso(0,0,0,1,15);
 paso(1,0,0,1,15);
 //Termina la secuencia
 }
Si quisiéramos invertir el sentido de giro, habría que invertir también el orden de los pasos:
void loop(){
 paso(1,0,0,1,15);
 paso(0,0,0,1,15);
 paso(0,0,1,1,15);
 paso(0,0,1,0,15);
 paso(0,1,1,0,15);
 paso(0,1,0,0,15);
 paso(1,1,0,0,15);
 paso(1,0,0,0,15);
 }
Control desde Consola Python Como de costumbre siempre dedico un poco de código para interfazar pinguino con Python, como siempre, usaré el módulo PinguinoProcessing que se encuentra en el paquete pynguino.
El archivo pynguino.pde se encuentra disponible en: http://yeisoneng.googlecode.com/svn/trunk/pynguino/archivos_pde/pynguino.pde Al usar un motor paso a paso unipolar de 100 pasos se tienen unas grandes ventajas, una de ellas (la principal) es que tenemos una precisión de 3.6° en cada paso, haciendo uso de un poco de algoritmos podríamos saber incluso en que posición se encuentra en cualquier momento.
#! /usr/bin/python
#-*- coding: utf-8 -*-

from pynguino import PinguinoProcessing
from time import sleep as delay

########################################################################
class StepperMotor():
    #----------------------------------------------------------------------
    def __init__(self):
        self.pinguino=PinguinoProcessing()
        self.pinguino.RecursiveConect()
        self.conectar()
        self.currentStep=(1,0,0,0)
        self.globalPos=0
        self.pausa=0.05
        self.steps=((1,0,0,0),
                    (1,1,0,0),
                    (0,1,0,0),
                    (0,1,1,0),
                    (0,0,1,0),
                    (0,0,1,1),
                    (0,0,0,1),
                    (1,0,0,1))
        
    #----------------------------------------------------------------------
    #Establecemos la comunicación con Pinguino
    def conectar(self):
        if self.pinguino.RecursiveConect():
            self.pinguino.pinMode(7,"output")
            self.pinguino.pinMode(6,"output")
            self.pinguino.pinMode(5,"output")
            self.pinguino.pinMode(4,"output")
            return
        else: self.conectar()
        
    #----------------------------------------------------------------------
    #Ejecutamos un paso en sentido horario y actualizamos la posición del motor
    def paso(self):
        try:pos=self.steps[self.steps.index(self.currentStep)+1]
        except:pos=self.steps[0]
        
        self.pinguino.digitalWrite(7,pos[0])
        self.pinguino.digitalWrite(6,pos[1])
        self.pinguino.digitalWrite(5,pos[2])
        self.pinguino.digitalWrite(4,pos[3])
        
        self.currentStep=pos
        self.globalPos+=1
        if self.globalPos==200: self.globalPos=0
        delay(self.pausa)
        
    #----------------------------------------------------------------------
    #Ejecutamos un paso en sentido anti-horario y actualizamos la posición del motor
    def rPaso(self):
        try:pos=self.steps[self.steps.index(self.currentStep)-1]
        except:pos=self.steps[3]
        
        self.pinguino.digitalWrite(7,pos[0])
        self.pinguino.digitalWrite(6,pos[1])
        self.pinguino.digitalWrite(5,pos[2])
        self.pinguino.digitalWrite(4,pos[3])
        
        self.currentStep=pos
        self.globalPos-=1
        if self.globalPos==-1: self.globalPos=200
        delay(self.pausa)
        
    #----------------------------------------------------------------------
    #Se desplaza hasta la posición indicada en sentido horario
    def goTo(self,pos):
        while self.globalPos!=pos: self.paso()
         
    #----------------------------------------------------------------------
    #Se desplaza hasta la posición indicada en sentido anti-horario
    def rGoTo(self,pos):
        while self.globalPos!=pos: self.rPaso()
        
    #----------------------------------------------------------------------
    #Se mueve según el parámetro ese número de pasos en sentido horario
    def stepper(self,steps):
        for x in range(steps): self.paso()
        
    #----------------------------------------------------------------------
    #Se mueve según el parámetro ese número de pasos en sentido anti-horario
    def rStepper(self,steps):
        for x in range(steps): self.rPaso()
        
Ahora para ejecutar desde un terminal debemos guardar el archivo, por ejemplo unipolar_stepper.py y abrir una terminal en el lugar en donde se tenga el archivo
yeison@YeisonEng:~/Escritorio$ python
Python 2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from unipolar_stepper import StepperMotor
>>> motor=StepperMotor()
>>> motor.stepper(99)
>>> motor.rStepper(99)
>>> motor.pause=0.02
>>> motor.stepper(99)
>>> motor.rStepper(99)
>>> motor.pause=0.005
>>> motor.goTo(50)
>>> motor.rGoTo(0)
>>> motor.goTo(25)
>>> motor.globalPos
25
>>> motor.rGoTo(0)
>>> motor.goTo(99)
>>> motor.globalPos
99
>>> motor.stepper(45)
>>> motor.globalPos
44
>>> 


Fuente: http://www.todorobot.com.ar/informacion/tutorial%20stepper/stepper-tutorial.htm

También podría interesarte:

Comentarios:
Anonymous dijo:
19 de febrero de 2012 20:31
Muy buen proyecto Yeison, voy a tratar de armarlo, ya descargue e instalé el software necesario, todo anda ok!!! ahora me falta el hardware para probar......tambien armé alguna interfaz en QtDesigner......tu blog me fue muy útil...Gracias.

Saludos Andrés...desde argentina.

Ubuntu Linux 10.04 Lucid.
Responder a Anonymous
Anonymous dijo:
13 de junio de 2012 12:59
Hola Yeison:

Ya armé este proyecto con pinguino+python con motores paso a paso, utilice un ULN2803 para poder manejar dos motores.

Una observación sobre el tutorial:
La tabla de verdad para la secuencia wave drive está equivocada en el paso 4.

Debiera ser así:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Saludos. Andrés de Argentina
Responder a Anonymous
Añadir un nuevo comentario:
Si desean una respuesta para su comentario sólo deben agregarme en G+ y hacer una mención a Yeison Cardona, así les podré responder lo antes posible.