Go Down

Topic: Controlando varios motores de contínua (Read 3883 times) previous topic - next topic

quique

He estado haciendo varias pruebas para controlar la velocidad de varios motores de contínua por anchura de pulso mientras se leen las entradas y no he podido encontrar nada mejor que este código. Supongo que para una aplicación "fina", la lógica de control PWM se debería hacer por hardware. También más adelante quizá haya instrucciones específicas para hacer esto en directamente porque he visto que el Atmega8 tiene unos registros especialmente dedicados a este fin.
Mientras tanto y si no quereis complicaros demasiado la vida podeis probar este código. Si consigo que alguien me preste una grabadora de video también subo una peli. No es que esté muy satisfecho con la precisión del asunto pero según qué aplicaciones puede ser admisible. Tampoco sé si hay alguna manera más "elegante" de conseguir el mismo resultado, si es así me llevo un tironcillo de orejas  :-[ por liar al personal.
Code: [Select]

/* Driving two DC motors
 * -----------------------
 *
 *  Custom timer originally intended to DC motor
 *  control purposes and made from two nested loops:
 *   - "scan cycle" is the main loop
 *   - "control cycle" is the internal loop
 *  Timing id adjusted by changing number of iterations en each loop
 *  and the internal delay of each control cycle iteration (tic). If scan
 *  cycle code takes significative time to jam current control cycle, this
 *  delay could be easily reduced or bypassed.
 *
 */

  int ledPin0 = 13;                // LED connected to digital pin 13
  int motorPin1 = 9;              // Motor 1 connected to digital pin 9
  int motorPin2 = 8;               // Motor 1 connected to digital pin 8
  
  int potPin1   = 5;               // Potentiometer1 connected to analog pin 5 ( 5 is 1 in some boards)
  int potPin2   = 4;               // Potentiometer1 connected to analog pin 5 ( 4 is 2 in some boards)
    
// Timing Setup

  int scanCycle = 10;              // Number of control cycles in a scan cycle  
  int controlCycle = 200;         // Control cycle iterations
  int tic = 6;                    // Control cycle iteration aditional delay in microseconds

  int currentSCycle = 0;           // Current scan cycle iteration
  int currentCCycle = 0;           // Current control cycle iteration
  boolean scanEnable = true;       // Allows read analog & digital inputs

// End timing setup
  
  int counter = 0;                 // Scan cycle counter used to change led status
  int motor1_PW;                   // motor 1 Pulse Width
  int motor2_PW;                   // motor 2 Pulse Width
  
/*
* Switch the boolean value assigned to any variable
*/
boolean boolSwitch (boolean *target)
{
  if ( *target ) {*target = false;}  else { *target = true; }
  return *target;
}

void setup()
{
  pinMode (ledPin0, OUTPUT);      // sets the digital pin as output
  pinMode (motorPin1, OUTPUT);    // sets the digital pin as output
  pinMode (motorPin2, OUTPUT);    // sets the digital pin as output
}

void loop()
{
// Scan cycle
 
  if (scanEnable)
  {
    //
    // Scan cycle logic here
    //
    motor1_PW = analogRead (potPin1)/5; // Pot 1 read scale change
    motor2_PW = analogRead (potPin2)/5; // Pot 1 read scale change

    // Swith led in pin 13 each 10 scan cycles. We can assume that while
    // Led is on (or off), porgram has taken 10 scan cycles. So, if we adjust  
    // blink time to 1 sec, we are able to scanning inputs each 100 msec.
    if (counter++ >= 10)
      {
        digitalWrite (ledPin0, boolSwitch (ledPin0)); // Led blink each 10 scan cycles i.e. if
                                                      // led is on 1 second, we are scaning knobs each
                                                      // 100 miliseconds
        counter =0;
      }
   }

// Control cycle  
  for (currentCCycle = 0; currentCCycle < controlCycle; currentCCycle ++)
  {
    delayMicroseconds (tic);
    //
    // Control cycle logic here
    //
    if ( motor1_PW > currentCCycle )
    {
      digitalWrite ( motorPin1, LOW);
    }
    else
    {
      digitalWrite ( motorPin1, HIGH);
    }
    
    if ( motor2_PW > currentCCycle )
    {
      digitalWrite ( motorPin2, LOW);
    }
    else
    {
      digitalWrite ( motorPin2, HIGH);
    }

  }

// Detect completed scan cycle  
  if ( currentSCycle ++ > scanCycle)
  {
     scanEnable = true; // Allow readings of external inputs
     currentSCycle = 0; // Reset scan cycle counter
  }
  else
  {
    scanEnable = false; //
  }
}




angela

Hola.

Tengo un pequeño motor de continua que mueve todo el engranaje de un juguete, y que lleva a su vez asociado un encoder óptico, de forma que se puede conocer su posición por el número de pulsos que genera dicho encoder.


Así que necesito controlar su velocidad de una manera muy precisa...o similar al funcionamiento original, de forma que pueda también llegar a controlar los movimientos del juguete.

Para ello estoy utilizando un driver (L293D) y la velocidad la estoy regulando, introduciéndole una señal PWM (obtenida del pin de salida de Arduino y con la función "analogWrite") a la patilla "ENABLE" del driver.

Según tengo entendido, con Arduino sólo podemos obtener una señal PWM de frecuencia y PW (ancho de pulso) constante y dónde en ella sólo podemos variar el Voltage de salida entre un rango de 0-255 (0 es voltios y 255 es 5 voltios) ¿Esto es así?.

Con ello consigo un cambio de velocidad pero no la que requiere el juguete, así que he probado con tu código, y aunque consigo mover el motor a diferentes velocidades, en ninguno de los casos, con la suficiente potencia (o necesaria frecuencia), para mover todo el engranaje.

Entonces, necesitaría saber o la cuestión es:

-¿Cómo puedo obtener o hacer el cálculo de Frecuencia, Periodo, PW (ancho de pulso), "Vaverage" (tasa de voltage de salida) o factor "Duty Cycle" (% tiempo que el pulso está activo en un ciclo), etc.? Es decir, de los parámetros que definen la señal PWM.  

Intuyo que consiste en jugar con los parámetros:

int controlCycle = 200; // Control cycle iterations
int tic = 6; // Control cycle iteration aditional delay in microseconds

Pero no estoy consiguiendo ningún resultado   ???

quique

Hola Angela
La verdad es que cuando hice el programa mi idea no era la de controlar de una forma "precisa" la velocidad  de los motores sino la de poder hacelo simultáneamente  mientras que leía la entrada de dos potenciómetros.  Si ves alguno de los programas de ejemplo verás que después de leer una entrada analógica se suele dejar un intervalo de unos 100 ms llamando a la instrucción
delay (100);
Ocurre que si haces esto mientras que estás modulando un tren de pulsos que mandas a un motor provocas que el motor quede "congelado" durante una décima de segundo. Por eso pensé en dos bucles anidados: uno de 'control' que va gestionando el tren de pulsos que manda a cada motor y otro de 'scan' que va en una escala de tiempo mucho mayor y que lee las entradas analógicas cada vez que la variable scanEnable toma un valor alto. Es decir cuando se han ejecutado
scanCycle * controlCycle
iteraciones. Tic es un delay adicional en microsegundos que se ejecuta en cada iteración del cico de control. Como verás la escala de tiempo usada entonces es totalmente arbitraria, se trata de jugar un poco con los parámetros según cada aplicación.
Si controlCycle es un loop que se ejecuta 200 veces las variables motor1_PW y motor2_PW indican cuantas de esas veces el pulso que controla cada motor está alto. En este caso es la lectura de cada potenciómetro un poco acondicionada
Code: [Select]
motor1_PW = analogRead (potPin1)/5; // Pot 1 read scale change

Concluyendo (después del rollete este): con el programilla este no vas a obtener un timing preciso, no está pensado para eso sino para poder controlar varios motores sin que se te paren o se te aceleren mientras que puedes hacer lecturas analógicas u otras cosas que requieran observar un tiempo de retardo como podría ser comunicación serie y no meter ningún hardware adicional.

La salida PWM no la he llegado a usar nunca y no sé como se hace ???. Quizá si necesitase PWM "de libro", yo que soy un poco burro, usaría algún esquema para PWM basado en el temporizador 555 y le enchufaría a una de las salidas analógicas pero esto es algo que tampoco he probado nunca.



  

Go Up