Go Down

Topic: Controlar vueltas de motor cabestrante (Read 2493 times) previous topic - next topic

surbyte

Primero felicitarte por la flexibilidad que demuestras tanto técnicamente como con la programación. Aunque sea un copy & paste, hay muchas habilidades incluídas en lo realizado y te aseguro que no es para minimizar.

Lo segundo es que no se por qué el código pone esto

Code: [Select]
motorGo(0, CW, 1023);

En un timer de 8 bits 1023 no tiene nada que hacer, puesto que lo máximo será 255.
De todos modos no afecta tu funcionamiento pero esta de mas.
Será en otro arduino?

Bueno aprovechando el uso del driver, ahora deberíamos poder aproximarnos con mas lentitud o sea cambiar la velocidad en el arranque y la aproximación.
Una Rampa sería apropiado, algo que vaya de 0 a MAX y de MAX a 0.

ya sabes que ese número PWM controla la velocidad.
Asi que para hacer esto deberíamos considerar por ejemplo que si arranca va de 0 a MAX PWM en media vuelta o 1 vuelta y lo mismo para desacelerar.

Qué opinas?

tauro0221

Hi,

Adjunto para tu informacion acerca de max temperatura del chp VNH2SP30-E. Esto te ayudara a determinar si necesitas heatsink o no.

MCasellas

Buenos días a todos,
os respondo por orden.

#45
@surbyte

Gracias por los halagos, me sonrojaste. Solo intento aprender de lo que estoy(estamos) haciendo aunque al ser un campo de conocimiento tan lejano al mío, no te voy a negar que más de una vez me siento frustrado e inútil! Jajajaja... Pero ahí voy, poco a poco.

Sobre lo que me indicabas del valor 1023 que figura en esa línea del código, llevas razón, ya me percaté de ello y en algún videotutorial ya vi que el máximo sería 255. De hecho, hoy trataré de hacer las pruebas para ver qué valor mínimo logra hacer funcionar el motor, aunque he probado con 100 y la velocidad (aunque sin carga) ya me va gustando. Pero bueno, tengo curiosidad sobre la velocidad mínima a la que se puede controlar con el driver, el cual, me tiene maravillado (gracias por la recomendación).

Sobre el uso de una Rampa, supongo que si que eso es lo que ganábamos con el driver y es lo más oportuno y elegante. Un incremento al inicio y una desaceleración al final. Sé que ambos serán muy sutiles porque tampoco que es que este motor trabaje a una velocidad muy alta de revoluciones, pero me encanta que la velocidad no sea constante.

Ahora tengo dos cuestiones, ¿cómo programar esa rampa? (cosa que a partir de ahora buscaré info) y ¿vamos a seguir usando el sensor electromagnético para contar las vueltas? Esto lo pregunto porque tal y como he soldado los pines al driver, estos encajan perfectamente sobre el arduino uno y no he tenido en cuenta preguntaros antes de coger el estaño si debía dejar algún pin libre para el sensor. (Error mío por la ansiedad!)

#46
@tauro0221

Gracias por el documento que has posteado. No sé si lo he entendido muy bien, supongo que puede trabajar entre los -40º y los 150º (ºC). Deduzco que en un principio no lo necesito, ¿estoy en lo correcto? Pero en cualquier caso, ayer pensé que más adelante pordría usar el driver para controlar otros motores con otras temperaturas y será mejor ponerle los disipadores/heatsink. Así que me he decidido a comprarlos, y en este caso, ¿cuáles me recomiendas? (El tamaño del chip VNH2SP30-E, en la placa es de 15x17mm)


Gracias a todos una vez más!

tauro0221

Hi,
 
Mi consejo es que cuando este completamente en operacion mida la temperatura para que estes seguro de que esta entre los limites de -40 to 150 C que recomienda el fabricante. Felicitaciones  por el excelente  trabajo que has hecho con las limitaciones de conocimientos que tenias al empezar el projecto y que haz podido seguir los consejos hechos por los mimbros de este forum. Buen trabajo.

surbyte

Prueba esta versión con rampa

Code: [Select]

#define STEP_RAMPA   10UL  // 10 mseg UL es unsigned long
#define BRAKEVCC 0
#define CW    1
#define CCW  2
#define BRAKEGND 3
#define CS_THRESHOLD 100


/*  VNH2SP30 pin definitions
 xxx[0] controls '1' outputs
 xxx[1] controls '2' outputs */
const byte inApin[2] = {7, 4};  // INA: Clockwise input
const byte inBpin[2] = {8, 9}; // INB: Counter-clockwise input
const byte pwmpin[2] = {5, 6}; // PWM input
const byte cspin[2]  = {2, 3}; // CS: Current sense ANALOG input
byte  enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)

const byte statpin = 13;
byte estado = 0, estadoAnt = 10;
int sentido = CW, sentidoAnt = 0;
int rampa = 0, rampaAnt = -1;

unsigned long start, start_step;

void setup()
{
  Serial.begin(9600);
  delay(3000);
  Serial.println("Comanzando a mover el cabrestante.");
 
  pinMode(statpin, OUTPUT);

  // Initialize digital pins as outputs
  for (int i=0; i<2; i++)
  {
    pinMode(inApin[i], OUTPUT);
    pinMode(inBpin[i], OUTPUT);
    pinMode(pwmpin[i], OUTPUT);
  }
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  // motorGo(0, CW, 1023);
  // motorGo(1, CCW, 1023);
}

void loop() {

   
  if (millis() - start_step > STEP_RAMPA) {
  if (rampa != rampaAnt || estado != estadoAnt || sentido != sentidoAnt) {
      print_status();
}
rampaAnt = rampa;
estadoAnt = estado;
sentidoAnt = sentido;
  if (sentido == CW) {
       rampa++;
       if (rampa > 255)
           rampa = 255;
  }
  else {
  rampa--;
       if (rampa < 0)
           rampa = 0;
  }
  start_step = millis();
  }
 
  switch (estado) {
  case 0: motorGo(0, CW,  255);
  motorGo(1, CCW, rampa);
  if (rampa == 255) {// termino el estado
      start = millis();
      estado = 1;
  }
  break;
  case 1: if (millis() - start > 10000UL) {
  Serial.println("Superamos 10 seg");
      estado = 2;
      sentido = CCW;
      print_status();
      start = millis();
  }
  break;
  case 2: motorGo(0, CCW,  255);
  motorGo(1, CW, rampa);
  if (rampa == 0) {// termino el estado
      estado = 3;
      start = millis();
  }
  break;
  case 3: if (millis() - start > 6000UL) {
  Serial.println("Superamos 6 seg");
  print_status();
    estado = 4;
    start = millis();
  }
  break;
  case 4: Serial.println("Motor parado");
  motorGo(0, CCW,  0); // motor parado.
  motorGo(1, CW,   0);
  estado = 5;
  break;
  case 5: break;
  }

  if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD))
     digitalWrite(statpin, HIGH);
}

void motorOff(int motor)
{
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  analogWrite(pwmpin[motor], 0);
}

/* motorGo() will set a motor going in a specific direction
 the motor will continue going in that direction, at that speed
 until told to do otherwise.
 
 motor: this should be either 0 or 1, will selet which of the two
 motors to be controlled
 
 direct: Should be between 0 and 3, with the following result
 0: Brake to VCC
 1: Clockwise
 2: CounterClockwise
 3: Brake to GND
 
 pwm: should be a value between ? and 1023, higher the number, the faster
 it'll go
 */
void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
  if (motor <= 1)  {
    if (direct <=4) {
      // Set inA[motor]
      if (direct <=1)
        digitalWrite(inApin[motor], HIGH);
      else
        digitalWrite(inApin[motor], LOW);

      // Set inB[motor]
      if ((direct==0)||(direct==2))
        digitalWrite(inBpin[motor], HIGH);
      else
        digitalWrite(inBpin[motor], LOW);

      analogWrite(pwmpin[motor], pwm);
    }
  }
}


void print_status() {
char buffer[30];

sprintf(buffer, "%03d Sentido = %3s  Estado = %d", rampa, (2-sentido)?"CW":"CCW", estado);
  Serial.println(buffer);
}



En el monitor serie veras el avance del código.

El paso es de 10 msegu para poder llegar a 2550 mseg cuando casi complete una vuelt.
Lo mismo la desaceleracion.

MCasellas

Saludos de nuevo,
en primer lugar gracias por vuestro apoyo, indicaciones y felicitaciones aunque esto último no creo que sea para tanto porque creo que voy dando palos de ciego a pesar de ir aprehendiendo tantas pequeñas cosas con la programación (que sigue siendo mi archienemigo).

Dicho esto os cuento.

Ayer estuve trabajando con un código básico para comprender a controlar los motores con el driver.
Code: [Select]
void setup() {
  for(int j=4;j<=9;j++){ //declarar Pines del 4 al 9
  pinMode(j,OUTPUT);    // declarar pines anteriores como SALIDA
}
 // Los pines 4,7,8, y 9 empienzan en LOW //RECUERDA LOW = 0, HIGH = 1
  digitalWrite(4,0);
  digitalWrite(7,0);
  digitalWrite(8,0);
  digitalWrite(9,0);

  Serial.begin(9600);

}

void loop() {
 

  digitalWrite(7,0); 
  digitalWrite(4,0);
  digitalWrite(8,0);
  digitalWrite(9,1);
 
  analogWrite(5, 100);  //motor 1 // Manejarme entre valores del 50 al 255
  analogWrite(6, 80);  //motor 2 // Manejarme entre valores del 50 al 255
}


No logré hacerlo funcionar porque creo que el driver que usé estaba mal, tras la frustración, menos mal que hoy se me ocurrió usar el otro driver (ya que compré dos) y este ya me ha funcionado.

Ahora puedo enumerar las cosas que voy teniendo claras:

1- Ya entiendo qué pines se asocian a cada motor y cómo elegir dirección de giro y velocidad.

2- He testado los valores mínimos de los pines pwm para controlar la velocidad y en mi caso, no creo que funcione con valores menores a 50 (de 255) ya que con valores inferiores a 50 el motor a veces ni se mueve.

3- He detectado que a valores bajos de pwm, el chip se calienta demasiado e incluso se ha parado el funcionamiento por la temperatura alcanzada. Por lo tanto, @tauro0221, le pondremos los disipadores en cuanto me lleguen.

Ahora, respondo a @surbyte sobre el código para probar la Rampa que me has pasado en el post anterior (#49). No saco mucho en claro al intentar entender el código, es casi como si estuviese leyendo chino, pero seguiré descifrándolo. Entiendo que maneja dos motores y como en mi caso tengo uno solo, ando cambiándolo de las salidas del driver para hacerme una idea de la relación entre programación y movimiento del motor. (Intentaré conseguir otro motor para verlo de forma más inmediata)

Si lo conecto como motor2 (ver video adjunto), tiene una aceleración muy elegante (permitirme este adjetivo). Prueba Rampa @surbyte Aunque la parada podría ser igual de "pausada" como el inicio porque aparentemente frena de forma más "brusca".

Como motor1, no adjunto video, pero es un movimiento más constante.

También hay algo que no sé bien porqué sucede, si os fijáis al final del video que he adjuntado antes, cuando el motor se detiene al final, uno de los leds se queda "medio encendido" y no sé a qué se debe. Quizás no sea influyente, pero desde mi desconocimiento, creo que no debería de ser así. ¿Debo preocuparme?

Bueno, pues voy a seguir intentando comprender el código. (Por cierto, una ultima consulta, a pesar de usar el driver seguiré necesitando contar las vueltas del motor ¿no?)

Un saludo a todos, muchas gracias y disculparme si esto se está extendiendo tanto.

tauro0221

Hi,
El problema es que cuando el motor esta parado y lo vaz a arrancar tienes que por lo menos aplicarle el max de los pwm que serian un valor de 255. Esto lo haces por unos segundos al principio y despues lo bajas. Vaz a tener que hacer algunas pruebas con diferents valores de pwm para ver como el motor te trabaja. Posiblemaente vaz tener que  olvidarte de usar el pwm y enegizar el driver directamentecon con un  pin o usar el pwm con un valor de 255 y enviar pulso para mover el motor. Otra cosa es que cuando enegizas un motor en estado de reposo la corriente iniciar va hacer como tres veces la corriente normal.

surbyte

Bueno me he dado cuenta de algunos errores asi que volveré al código a corregirlos.
Respecto de motor1 y motor2 también veo ahi un error en mi código.

En breve postearé la modificación.

MCasellas

Hola de nuevo,

Respondiendo los post anteriores:

#51
@tauro0221, no sé si te he entendido bien, pero te cuento. He estado haciendo las pruebas que me recomiendas, de hecho ya las hice antes de tu post para ver con qué valor mínimo de pwm funcionaba el motor y como te digo no entiendo bien lo que me explicas porque el motor inicia con valores de 30 (pwm), aunque le noto más "estabilidad" con un valor mínimo de 50 (pwm), sin necesidad de arrancarlo con 255 (pwm). Es más, en el sketch de prueba que pasó @surbyte en el post #49 y que se puede ver en el video que colgué en el post #50, el motor arranca suavemente y va incrementando su velocidad, a mi entender (que es poco), de forma perfecta. Por eso digo que no sé si te entendí bien del todo, pero aún así muchísimas gracias por tu anotación.

#52
@surbyte, @tauro021, @PeterKantTropus... No sé cómo agradeceros esto!!! GRACIAS

surbyte

Basicamente el error esta en que la rampa de arranque estuvo bien pero no la de apagado y luego creo que no lo hace mas... requiere leve ajuste.

tauro0221

Hi,
Creo que si entendistes lo que decia pues a mi me paso lo mismo controlando un fan para un horno. Al principio no se movia. Hice unas pruebas para ver cuando empezaba a caminar y use ese valor  simpre que encendia el abanico.Una vez que arrancaba no tenia problemas manteniedo la velocidad. Una de las ventajas de usar el pwm es que el corre en el background. Una vez que inicia el comando el va a mantener ese comando hasta que no lo refresque con un cambio nuevo.

MCasellas

Hola a todos!

#54, exacto @surbyte, no hace ninguna rampa en el apagado. Si en el inicio de marcha, pero no en el frenado. Sobre lo que te comenté de que con el motor1 no hacía la aceleración progresiva, ya he visto a que se debía a que no estaba aplicada la rampa en el pin pwm. (Una pavada como decís por allá!)

El resto del código, llevo 3 días tratando de descifrarlo, pero hay demasiadas órdenes nuevas para mi.

Y aún mantengo mi duda, ¿seguiremos necesitando contar las vueltas con un sensor no?

#55, gracias @tauro0221 por tu aclaración, parece que si, que lo entendí. :)

Saludos a todos!

surbyte

Quote
Y aún mantengo mi duda, ¿seguiremos necesitando contar las vueltas con un sensor no?
Las vueltas del motor deben contarse para asegurar una distancia de desplazamiento.
Ya que el proceso de subida y bajada tienen diferente velocidad si no cuentas las vueltas no sabes donde esta tu carga desplazada.

Para explicarte el código necesito saber porque usas Motor1 y Motor2, se supone que tienes un solo motor no es así?

Otra cosa es que estos comandos

 direct: Should be between 0 and 3, with the following result
 0: Brake to VCC
 1: Clockwise
 2: CounterClockwise
 3: Brake to GND

aseguran el funcionamiento del motor pero tienes 0 o 3 para frenarlo sea contra VCC o contra GND.
Estas usando 0 o sea que le aplicas VCC. Verifica si eso no calienta el motor como has dicho o si el calentamiento ocurre por arrancar en 0.
De todos modos luego te explicaré pero pasamos de 0 a 50 que es donde dices empieza a moverse en 500 mseg y no creo que eso genere calentamiento del motor.

Si puedo cambiar la rampa para que vaya desde 45 y no desde 0 a 255.

MCasellas

#58
May 28, 2018, 10:44 am Last Edit: May 28, 2018, 12:37 pm by MCasellas
Hola @surbyte,

eso me temía, que con solo con el driver no podría contar las vueltas. Aunque se me ha pasado por la cabeza usar el valor pwm para equiparar las velocidades en cada sentido de giro, pero pienso que eso sería una solución muy mala.

Llevas razón, en un principio quiero controlar un solo motor. Estoy usando dos, porque en los sketch que he encontrado, como en el que me pasaste en el post #49, siempre se usan dos motores. Por eso que haya mencionado lo de motor1 y motor2. Así que si, podríamos limitarnos a un solo motor, de hecho, ayer logré ignorar el uso de un segundo motor en el código que me pasaste.

También, probando sin saber muy bien qué tocaba del código, he podido cambiar que la rampa comience a contar desde 50 y sobre el calentamiento, debo decirte que por ahora no nos debemos preocupar porque desde que el código trabaja con un solo motor y he reducido el tiempo que está activo el motor, el driver no se calienta mucho. (Aún así, voy a ponerles los disipadores de aluminio y probablemente un ventilador que venía en el lote al comprar los heatsink)

Os dejo el código con las modificaciones que le he hecho para anular el uso de uno de los motores y que la rampa comience desde 50 (pwm).

Code: [Select]

#define STEP_RAMPA   10UL  // 10 mseg UL es unsigned long
#define BRAKEVCC     0
#define CW        1
#define CCW       2
#define BRAKEGND    3
#define CS_THRESHOLD  100


/*  VNH2SP30 pin definitions
 xxx[0] controls '1' outputs
 xxx[1] controls '2' outputs */
const byte inApin[2] = {7, 4};  // INA: Clockwise input
const byte inBpin[2] = {8, 9}; // INB: Counter-clockwise input
const byte pwmpin[2] = {5, 6}; // PWM input
const byte cspin[2]  = {2, 3}; // CS: Current sense ANALOG input
byte  enpin[2]     = {0, 1}; // EN: Status of switches output (Analog pin)

const byte statpin = 13;
byte estado = 0, estadoAnt = 10;
int sentido = CW, sentidoAnt = 0;
int rampa = 50, rampaAnt = -1;     // Creo que aquí puedo establecer desde qué valor comienza la rampa, en mi caso rampa = 50

unsigned long start, start_step;

void setup()
{
  Serial.begin(9600);
  delay(3000);
  Serial.println("Comanzando a mover el cabrestante.");
  
  pinMode(statpin, OUTPUT);

  // Initialize digital pins as outputs
  for (int i=0; i<2; i++)
  {
    pinMode(inApin[i], OUTPUT);
    pinMode(inBpin[i], OUTPUT);
    pinMode(pwmpin[i], OUTPUT);
  }
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  // motorGo(0, CW, 1023);
  // motorGo(1, CCW, 1023);
}

void loop() {

  
  if (millis() - start_step > STEP_RAMPA) {
     if (rampa != rampaAnt || estado != estadoAnt || sentido != sentidoAnt) {
        print_status();
   }
   rampaAnt = rampa;
   estadoAnt = estado;
   sentidoAnt = sentido;
     if (sentido == CW) {
         rampa++;
         if (rampa > 255)
             rampa = 255;
     }
     else {
       rampa--;
         if (rampa < 0)
             rampa = 0;
     }
     start_step = millis();
  }
  
  switch (estado) {
    case 0: motorGo(0, CCW,  rampa);     // . Valores entre paréntesis (Primero elige motor, segundo elige sentido, tercero velocidad)
        //motorGo(1, CCW , rampa);  //Desactivado para probar con un solo motor
        if (rampa == 255) {// termino el estado
            start = millis();
            estado = 1;
        }
        break;
    case 1: if (millis() - start > 3000UL) {
          Serial.println("Superamos 3 seg");
            estado = 2;
            sentido = CCW;
            print_status();
            start = millis();
        }
        break;
    case 2: motorGo(0, CCW,  255);
        //motorGo(1, CW, rampa);  //Desactivado para probar con un solo motor
        if (rampa == 0) {// termino el estado      
            estado = 3;
            start = millis();
        }
        break;
    case 3: if (millis() - start > 2000UL) {
          Serial.println("Superamos 2 seg");
          print_status();
          estado = 4;
          start = millis();
        }
        break;
    case 4: Serial.println("Motor parado");
        motorGo(0, CCW,  0); // motor parado.
        //motorGo(1, CW,   0);  //Desactivado para probar con un solo motor
        estado = 5;
        break;
    case 5: break;
  }

  if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD))
     digitalWrite(statpin, HIGH);
}

void motorOff(int motor)
{
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  analogWrite(pwmpin[motor], 0);
}

/* motorGo() will set a motor going in a specific direction
 the motor will continue going in that direction, at that speed
 until told to do otherwise.
 
 motor: this should be either 0 or 1, will selet which of the two
 motors to be controlled
 
 direct: Should be between 0 and 3, with the following result
 0: Brake to VCC
 1: Clockwise
 2: CounterClockwise
 3: Brake to GND
 
 pwm: should be a value between ? and 1023, higher the number, the faster
 it'll go
 */
void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
  if (motor <= 1)  {
    if (direct <=4) {
      // Set inA[motor]
      if (direct <=1)
        digitalWrite(inApin[motor], HIGH);
      else
        digitalWrite(inApin[motor], LOW);

      // Set inB[motor]
      if ((direct==0)||(direct==2))
        digitalWrite(inBpin[motor], HIGH);
      else
        digitalWrite(inBpin[motor], LOW);

      analogWrite(pwmpin[motor], pwm);
    }
  }
}


void print_status() {
  char buffer[30];

  sprintf(buffer, "%03d Sentido = %3s  Estado = %d", rampa, (2-sentido)?"CW":"CCW", estado);
    Serial.println(buffer);
}


Como siempre, muchísimas gracias. Me está costando demasiado esfuerzo entender algunas cosas, mis más sinceras disculpas. Me siento muy lastrado por mi desconocimiento en la materia y creo que lograr lo que pretendo va a quedar lejos de mi alcance hasta el punto que estoy apunto de tirar la toalla!! Espero que solo sea un mal día!

Saludos a todos!!

surbyte

Estuve pensando que al terminar la secuencia el sistema normalmente queda en la posición RECOGER pero apenas pasado. Es decir, recupera la cuerda y cuando lee la última vuelta detiene el motor.
Eso significa que se pasa unos grados la posición del iman.

La pregunta es que con facilidad podemos poner la cuerda en la posición inicial moviendola apenas hasta que atraviese el sensor estableciendo dicha posicion como la inicial y desde ahi contar 3 vueltas.

Estoy hablando de un movimiento pequeño.

Go Up