Mover dos motores a la vez TB6560 con relaciones diferentes

Buenas tardes, estoy intentando hacer una bobinadora y se me plantea un problema a la hora de los moviemientos de los motores, la programacion no es mi fuerte, pero con el tiempo le ire agarrando mas el truco a esto.
Tengo dos driver TB6560 y dos motores, uno va directo al carrete a bobinar, y el otro es la guia de avance que va con varilla de M5 con avance de 0,8mm por vuelta.
El motor del carrete esta configurado para 200 pasos por vuelta, y el motor de la guia a 500 por milimetro (400 por vuelta)
Mi codigo a la hora de mover los motores es un simple for, ej.

void bobinar(long pasoscar)
{
for (long i=pasoscar; i != 0; i--)
{

digitalWrite(3, HIGH);
delayMicroseconds(pulsewidth);
digitalWrite(3, LOW);
delayMicroseconds(49*pulsewidth);
}
}

El problema me viene a la hora de intercalar los moviemientos, ya que las relaciones de moviemiento para una resolucion de 0,1mm por vuelta en la guia me da una relacion de 50 paasos de la guia por cada 200 del carrete.
No me hago a la idea de como poder mezclar estos moviemientos, ya que a 0,3mm por vuelta son 150 pasos por cada 200 (una relacion de 0,75), lo mismo me viene a la hora de cambiar de direccion para cada capa, pero con que me echen un cable en lo de los pasos para mi ya es una avance.
Cuando termine posteare fotos.
Muchas gracias(y)
 
¿Que tipo de motor son?
Si no son paso a paso no sabes que es lo que están haciendo, bueno en realidad en los PaP tampoco lo sabes, solo lo supones.
 
Pues ahora que pienso, supongo que el avance de la varilla tendrá relación con el diámetro del hilo con el que estés bobinando.
Supongo que el avance es igual al diámetro del hilo en una vuelta, que eso corresponde a X revoluciones del motor, y eso lo repartes a lo largo del giro del otro motor.
 
Hola, tu descripción del mecanismo me recuerda al funcionamiento del antiguo cassette. En donde la cinta se desplazaba accionado por un rodillo, mientras dicha cinta era recogida por un carrete accionado por un embrague, el cual mantenía siempre tensa a la misma.
Deberías subir el esquema mecánico de tu proyecto, para apreciar lo que requieres.
 
Hola buen día para tu propósito debes complementarla, con pantalla digital y sensores, de lo contrario no sabras ni cuantas vueltas da, ni la relación de este mismo, ni mucho menos poder controlar el giro, eso depende mucho de la longitud del carrete y calibre del alambre.

Mira por aquí para que tengas una idea, busca toda la información que puedas hacerca de bobinadoras controladas con Stepper Motor, si quieres precisión debes montarle una varilla roscada trapezoidal.

http://geekchickens.blogspot.com.co/2014/04/aplicacion-de-las-interrupciones.html?m=1

Maki.
 
Última edición:
Aqui esta la foto, es un sistema sencillo pero funcional, como dijo scooter, mantienen la misma relacion durante todo el bobinado, esta fabricado con un NEMA 17 y un NEMA 26 (creo q asi era) de fuerza va muy bien ya que tengo que bobinar hilo de 1,5mm2 de silicona.
Mañana mirare mejor el enlace que me han puesto pero lo veo complicado para lo que yo quiero. pongo el cogido completo aqui.

Código:
int pasosxmilimetro = 500, pasosxvuelta = 200, pulsewidth = 50;
long vueltas, ancho, diametro, valor, mover, pasoscarrete, pasosguia, pasoscapa, velocidadcarrete = 2500, velocidadguia = 64000;
char funcion;
char cadena[5];

void setup()
{  
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    Serial.begin(115200);
}

void loop()
{
  if(Serial.available()) //Nos dice si hay datos dentro del buffer
  {
    memset(cadena, 0,sizeof(cadena));//memset borra el contenido del array  "cadena" desde la posición 0 hasta el final sizeof
    
    if(Serial.available()>0) //Mientras haya datos en el buffer ejecuta la función
    {
      funcion=Serial.read();
      delay(5); //Poner un pequeño delay para mejorar la recepción de datos
      cadena[0]=Serial.read();//Lee un carácter del string "cadena" de la "posicion", luego lee el siguiente carácter con "posicion++"
      delay(5);
      cadena[1]=Serial.read();
      delay(5);
      cadena[2]=Serial.read();
      delay(5);
      cadena[3]=Serial.read();
      delay(5);
      cadena[4]=Serial.read();
    }
 
    valor = atoi(cadena);

  }
  switch(funcion)
  {
  case 'V':
  vueltas = valor;
  funcion=0;
  break;
  case 'A':
  diametro = valor;
  diametro = diametro/10;
  funcion=0;
  break;
  case 'T':
  ancho = valor;
  funcion=0;
  break;
  case 'H':

  funcion=0;
  break;
  case 'C':

  funcion=0;
  break;
  case 'G':

  funcion=0;
  break;
  case 'F':

  funcion=0;
  break;
  case 'S':
  velocidadguia = ((velocidadcarrete/pasosxvuelta)*(diametro*pasosxmilimetro))/100;

  pasoscarrete = pasosxvuelta*vueltas;
  pasosguia = vueltas*pasosxmilimetro;
  pasoscapa = (ancho/diametro)*pasosxmilimetro;
  bobinar2(pasosguia);
  funcion=0;
  break;
  }
   // Change direction at the limits
    Serial.print("VUELTAS: ");
    Serial.print(vueltas);
    Serial.print(" ");
    Serial.print("DIAMETRO: ");
    Serial.print(diametro);
    Serial.print(" ");
    Serial.print("ANCHO CARRETE: ");
    Serial.print(ancho);
    Serial.print(" ");
    Serial.print("PASOS CARRETES: ");
    Serial.print(pasoscarrete);
    Serial.print(" ");
    Serial.print("PASOS GUIA: ");
    Serial.print(pasosguia);
    Serial.print(" ");
    Serial.print("PASOS CAPA: ");
    Serial.println(pasoscapa);

  //carrete.run();
}
void bobinar(long pasoscar)
{
  for (long i=pasoscar; i != 0; i--)
  { 
    
    digitalWrite(3, HIGH);
    delayMicroseconds(pulsewidth);
    digitalWrite(3, LOW);
    delayMicroseconds(49*pulsewidth);
  }
}
void bobinar2(long pasoscar)
{
  for (float i=pasoscar; i != 0; i-0.75)
  {
    digitalWrite(2, HIGH);
    delayMicroseconds(2*pulsewidth);
    digitalWrite(2, LOW);
    delayMicroseconds(28*pulsewidth);
  }
}

Gracias(y)



Makitronica, seteo lo parametros via serial y luego lo pongo a correr, no hace falta sensores ya que seteo el cero antes de empezar.
Lo unico q no logro es dar con la manera de mantener la relacion de cada 10 pasos de motor el otro de 6, algo asi.
Gracias
 

Adjuntos

  • image1 (005).jpg
    image1 (005).jpg
    99.4 KB · Visitas: 29
Última edición por un moderador:
Bueno Mikaelectronic he leido el link que me haz pasado, y realmente es menos que lo que tengo ahora, yo ahora puero controlar las vueltas del carrete y de la guia ,bien, pero por separado, cada uno con su "for", lo que quiero es poder meter a los dos en un mismo "for" o algo asi, pero que cada x pasos de uno haga un paso del otro e inversa, por que segun el diametro del cable a veces hacen falta mas pasos de la guia que del carrete (ej. hilo de 2mm) necesito 1000 pasos por cada 200 del carrete, pero cuando es de 0,1mm necesito 50 pasos por cada 200 del carrete, una opcion es hacerlo por separado, vuelta y luego avanzar pero me sentiria tonto por no poder hacerlo ambos a la vez, he probado con la libreria accelsteeper y la verdad q las aceleraciones van mal con el TB6560 (por que se acorta el ancho del pulso a menos del minimo) y pierdo pasos, por eso la mejor opcion es hacerlo asi basico.
Si alguien echa un cable seria de agradecer.
Saludos(y)
 
bueno he conseguido algo metiendo dentro del for de las vueltas del carrete las vueltas de la guia pero eso me limita a que no puede haber mas pasos de guia que de vueltas con lo que me limita a un paso maximo de 0,8mm (400 pasos), podria subir la resolucion del carrete hasta 1600 pasos pero pierdo velocidad y torque del motor (segun he leido) podria susar otro driver que me da hasta 6400 pasos pero me daria pena gastarlo en esto, la otro posibilidad seria hacer el for por el doble de pasos y solo haciendo funcionar el carrete en los pares, con eso tengo el doble, podria usar 4 veces mas pero tendria que ser variable ya que seria malo que para 0,1 de diametro avanzaria en los primero 50 pasos de los pasos del carreteX4...
Alguna idea?
Gracias
 
Bueno, con un resultado aceptable he logrado que funcionara.
He hecho que seleccione una relación según el diámetro del cable "1" para cables hasta 1,6mm que da con la relación 1 a 1 y la dos que alcanza como máximo 3,2 mm. en una relación de 2 a 1.

Dejo el código por si le sirve a alguien.
Los pines están en los comentarios y los comandos seriales abajo.
Si alguien le hace cambios que puedan mejorarlo, sería genial que me los pasaran.
Gracias.

PHP:
int pasosxmilimetro = 250, pasosxvuelta = 400, pulsewidth = 40,vueltasxcapa, capasenteras, vueltassueltas, capas, relacion1;
long vueltas, ancho, valor, mover, pasoscarrete, pasosguia, pasoscapa, velocidadcarrete = 2500, velocidadguia = 64000, vueltascap;
char funcion;
char cadena[5];
float diametro;

void setup()
{  
    pinMode(2, OUTPUT); //paso de guia
    pinMode(3, OUTPUT); //paso de carrete
    pinMode(5, OUTPUT); //direccion guia
    pinMode(6, OUTPUT); //direccion carrete
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    Serial.begin(115200);
}

void loop()
{
  if(Serial.available()) //Nos dice si hay datos dentro del buffer
  {
    memset(cadena, 0,sizeof(cadena));//memset borra el contenido del array  "cadena" desde la posición 0 hasta el final sizeof
    
    if(Serial.available()>0) //Mientras haya datos en el buffer ejecuta la función
    {
      funcion=Serial.read();
      delay(5); //Poner un pequeño delay para mejorar la recepción de datos
      cadena[0]=Serial.read();//Lee un carácter del string "cadena" de la "posicion", luego lee el siguiente carácter con "posicion++"
      delay(5);
      cadena[1]=Serial.read();
      delay(5);
      cadena[2]=Serial.read();
      delay(5);
      cadena[3]=Serial.read();
      delay(5);
      cadena[4]=Serial.read();
    }
 
    valor = atoi(cadena);

  }
  switch(funcion)
  {
  case 'V':
  vueltas = valor;
  funcion=0;
  break;
  case 'D':
  diametro = valor;
  diametro = diametro/10;
  funcion=0;
  break;
  case 'A':
  ancho = valor;
  funcion=0;
  break;
  case 'H':
  moverguia(valor, LOW);
  funcion=0;
  break;
  case 'C':
  moverguia(valor, HIGH);
  funcion=0;
  break;
  case 'R':
  relacion1 = valor;
  funcion=0;
  break;
  case 'F':
  
  funcion=0;
  break;
  case 'S':
  bobinar(vueltassueltas, diametro, HIGH, HIGH, relacion1);
  funcion=0;
  break;
  }
    if (diametro > 1.60)
    {
      relacion1 = 2;
    }else{
      relacion1 = 1;
    }
    vueltasxcapa = ancho/diametro;
    capas = vueltas/vueltasxcapa;
    vueltassueltas = vueltas-(vueltasxcapa*capas);
    if (vueltas < vueltasxcapa)
    {
      vueltascap = 0;
    }else{
      vueltascap = vueltasxcapa;
    }
    Serial.print("VUELTAS: ");
    Serial.print(vueltas);
    Serial.print(" ");
    Serial.print("DIAMETRO: ");
    Serial.print(diametro);
    Serial.print(" ");
    Serial.print("ANCHO CARRETE: ");
    Serial.print(ancho);
    Serial.print(" ");
    Serial.print("VUELTA POR CAPA: ");
    Serial.print(vueltascap);
    Serial.print(" ");
    Serial.print("CAPAS ENTERAS: ");
    Serial.print(capas);
    Serial.print(" ");
    Serial.print("VUELTAS SUELTAS: ");
    Serial.print(vueltassueltas);
    Serial.print(" ");
    Serial.print("RELACION: ");
    Serial.println(relacion1);
}
void moverguia(long milimetros, bool direccion)
{
  digitalWrite(5, direccion);
  for (long i=milimetros; i != 0; i--)
    {
      for (long h=pasosxmilimetro; h != 0; h--)
      { 
      digitalWrite(2, HIGH);
      delayMicroseconds(pulsewidth);
      digitalWrite(2, LOW);
      delayMicroseconds(25*pulsewidth);
      }
    }
}
void bobinar(long vueltassueltas, float avance, bool dirguia, bool dircarrete, int relacion)
{
  int estado = 1;
  digitalWrite(5, dirguia);
  digitalWrite(6, dircarrete);
  for (long f=capas; f != 0; f--)
  {
    for (long i=vueltasxcapa; i != 0; i--)
    {
      for (long h=pasosxvuelta*relacion; h != 0; h--)
      { 
        switch(relacion)
        {
          case 1:
          if (h<=avance*pasosxmilimetro) digitalWrite(2, HIGH);
          digitalWrite(3, HIGH);
          delayMicroseconds(pulsewidth);
          digitalWrite(3, LOW);
          digitalWrite(2, LOW);
          delayMicroseconds(24*(pulsewidth));
          break;

          case 2:
          if (h<=avance*pasosxmilimetro) digitalWrite(2, HIGH);
          if (estado == 2)
          {
          digitalWrite(3, HIGH);
          delayMicroseconds(pulsewidth);
          digitalWrite(3, LOW);
          digitalWrite(2, LOW);
          delayMicroseconds(24*(pulsewidth/relacion));
          estado = 1;
          }else{
          delayMicroseconds(pulsewidth);
          digitalWrite(2, LOW);
          delayMicroseconds(25*(pulsewidth));
          estado++;
          }
          break;
        }
      }
    }
    if (dirguia == HIGH)                        //CAMBIO DE SENTIDO
    {
      dirguia=LOW;
      digitalWrite(5, dirguia);
    }else{
       dirguia=HIGH;
       digitalWrite(5, dirguia);                ////////////////////
    }
  }
  estado = 1;
  for (long i=vueltassueltas; i != 0; i--)       //VUELTAS SUELTAS
    {
      for (long h=pasosxvuelta*relacion; h != 0; h--)
      { 
        switch(relacion)
        {
          case 1:                                                           /// SI LA RELACION ES 1 ES AVANCE ES 1 A 1
          if (h<=avance*pasosxmilimetro) digitalWrite(2, HIGH);
          digitalWrite(3, HIGH);
          delayMicroseconds(pulsewidth);
          digitalWrite(3, LOW);
          digitalWrite(2, LOW);
          delayMicroseconds(24*(pulsewidth));
          break;

          case 2:                                                         /// SI LA RELACION ES 1 ES AVANCE ES 2 DE GUIA A 1 DE CARRETE
          if (h<=avance*pasosxmilimetro) digitalWrite(2, HIGH);
          if (estado == 2)
          {
          digitalWrite(3, HIGH);
          delayMicroseconds(pulsewidth);
          digitalWrite(3, LOW);
          digitalWrite(2, LOW);
          delayMicroseconds(24*(pulsewidth/relacion));
          estado = 1;
          }else{
          delayMicroseconds(pulsewidth);
          digitalWrite(2, LOW);
          delayMicroseconds(25*(pulsewidth));
          estado++;
          }
          break;
        }
      }
    }
}
Comandos:
'V' Vueltas de carrete (valor máximo 32,767)
'A' Ancho carrete útil (valor en mm, valor máximo 32,767)
'D' Diámetro del cable (valor en décimas de mm, 10 = 1mm. valor máximo 3,2mm)
'H' Mueve guia milímetros a home (valor máximo 32,767)
'C' Mueve guia milímetros hacia fuera (valor máximo 32,767)
'S' Comienza a bobinar

Ejemplo: (configurar 32767 vueltas) V32767
Ejemplo: (configurar 67 vueltas) V67
 
Última edición por un moderador:
Buenas tardes, estoy trabajando en la programacion de un Robot SCARA de 3 grados de libertad en donde estoy utilizando drivers TB6550 para mover los motores a pasos. El problema comenzo cuando surgio la necesidad de mover ambos motores para que se dirigieran a una posicion, es decir, necesito que los motores comienzen y terminen al mismo tiempo, teniendo cada motor un angulo diferente para dirigirse al punto que deseo, ya que necesito hacer una trayectoria. Estoy programando en lenguaje c en MPLAB con el microcontrolador 18F4550. Hasta ahora solo se como calcular los grados que debe moverse cada motor, pero no puedo hacerlos mover al mismo tiempo con un solo for.

Muchas gracias!! ...
 
Última edición:
Tenes que interpolar es decir que para que realice una trayectoria lineal el motor de menor distancia debera tardar lo mismo que el de mayor distancia
interpolacion_lineal.gif


Es lo que se utiliza en control númerico
 
Última edición:
Buenas tardes, estoy trabajando en la programacion de un Robot SCARA de 3 grados de libertad en donde estoy utilizando drivers TB6550 para mover los motores. El problema comenzo cuando surgio la necesidad de mover ambos motores para que se dirigieran a una posicion, es decir, necesito que los motores comienzen y terminen al mismo tiempo, teniendo cada motor un angulo diferente para dirigirse al punto que deseo, ya que necesito hacer una trayectoria. Estoy programando en lenguaje c en MPLAB con el microcontrolador 18F4550. Hasta ahora solo se como calcular los grados que debe moverse cada motor, pero no puedo hacerlos mover al mismo tiempo con un solo for.

Muchas gracias!! ...

A eso se le llama la cinemática del robot, dependiendo de su geometría tiene una relación con la posición de los motores u otra para llegar a un punto, además suelen tener la posición "codo arriba" y codo abajo" para cada punto.
Normalemente se trabaja con matrices te trasformación porque es mas sencillo.

Además la cinematica directa es bastante simple/tonta, la cinemática inversa tiene su miga.

La directa es conocer la posición de la pinza conociendo los ángulos, la inversa es lo contrario; conocer los ángulos necesarios para llegar a cierto punto.

Busca un libro de robótica, no es sencillo, ni "evidente" pero tu duda es bastante común....


Y después de eso que es lo fácil, llega lo divertido que es la dinámica del brazo; habrá que par precisa cada articulación para que en la pinza levante X peso. Es par depende de la posición, la carga, las recducciones y el peso del brazo en si.
 
Creo que me entendiste mal, amigo. Con lo que tengo problema es con la programación.
Hacer que los dos motores a pasos se muevan al mismo tiempo y terminen al mismo tiempo.

Yo ya calculé la cinemática directa e inversa.
Ya sé cómo sacar los ángulos que deben moverse, pero repito, lo que busco es hacer mover ambos motores al mismo tiempo, después de decirles cuantos ángulos deben moverse y que estos terminen de moverse al mismo tiempo.



Este es mi código hasta ahora.
PHP:
/*CONFIGURACION PIC*/
#include "18f4550.h"
#include "math.h"
#use delay(clock=48000000)
#build(reset=0x02000,interrupt=0x02008)
#org 0x0000,0x1FFF {}
#define LCD_ENABLE_PIN PIN_B5 // Definición del RB5 para el E del LCD
#define LCD_RW_PIN PIN_B6 // Definición del RB6 para el R/W del LCD
#define LCD_RS_PIN PIN_B7 // Definición del RB7 para el RS del LCD
#define LCD_DATA4 PIN_D4 // Definición del RD4 para el DB4 del LCD
#define LCD_DATA5 PIN_D5 // Definición del RD5 para el DB5 del LCD
#define LCD_DATA6 PIN_D6 // Definición del RD6 para el DB6 del LCD
#define LCD_DATA7 PIN_D7 // Definición del RD7 para el DB7 del LCD
#include <lcd.c> // Se incluye al proyecto la librería lcd.c
#define CLK PIN_E0
#define CW PIN_E1
#define CLK2 PIN_E2
#define CW2 PIN_E3
/* Programa principal*/

void main() {


float x, y;
float L1, L2, Betha;
float R, ro, x1, y1;
float theta1, theta2, theta11, theta22, a, b;
float Pulsos1, PulsosReales1, Pulsos2, PulsosReales2;
long NumPulso;

lcd_init(); // Inicializo la lcd.

L1 = 17.3;
L2 = 19.3;

x = 15;
y = 10;


Betha = atan(y/x);

R = sqrt((x*x)+(y*y));

ro = acos(((L1*L1) + (R*R) - (L2*L2)) / (2*L1*R));



theta11 = (Betha + ro);
theta1 = (180*theta11)/3.141592654;      

x1 = (R*cos(theta11));
y1 = (R*sin(theta11));

a = (x - x1);
b = (y - y1);

theta22 = atan(b/a);
theta2 = (180*theta22)/3.141592654;

/////////////////////THETA1 Y THETA2//////////////////////
Pulsos1 = theta1/0.1125;
PulsosReales1 = 2*Pulsos1*3.0901;

Pulsos2 = theta2/0.1125;
PulsosReales2 = 2*Pulsos2*3.0901;

lcd_gotoxy(2,1); // Posicionamos el cursor en la posición (2,1).
printf(lcd_putc, "\f theta1 = %f",theta1);

lcd_gotoxy(2,2); // Posicionamos el cursor en la posición (2,2).
printf(lcd_putc, "\n theta2 = %f",theta2);


if(theta1>theta2){



}


for (NumPulso=1;NumPulso<PulsosReales1;NumPulso++){

output_drive(CW); // Se configura el pin del CW como salida.
output_low(CW); // Se manda a apagar el CW.

output_toggle(CLK);
delay_ms(10); // Retardo de 10ms.

}

for (NumPulso=1;NumPulso<PulsosReales2;NumPulso++){

output_drive(CW2); // Se configura el pin del CW como salida.
output_low(CW2); // Se manda a apagar el CW.

output_toggle(CLK2);
delay_ms(10); // Retardo de 10ms.

}

 
}
Solo es para calcular los grados que debe moverse cada motor después de asignarle un punto al que debe moverse.
 
Última edición por un moderador:
Hola no la tengo muy clara pero una idea que se me ocurre es hacer los calculos en base al tiempo, por ejemplo si un motor tiene que dar 300 pasos en 300 segundos y el otro 400 en 300 segundos uno avanzaria cada 1 segundo y el otro cada 750ms.
 
Lo que tu estas pidiendo se llama interpolación, no quiera inventar lo que ya esta inventado, biker te lo esta diciendo, eso que esta expresado en tiempo es interpolación, si no logras entender eso es imposible que logres hacer el programa correspondiente
Vamos de nuevo
Croquis1_7.jpg
 
Última edición:
Atrás
Arriba