Acelerando un motor paso a paso sin hacer ruido [cerrado]

0

Tengo algunos problemas para mover mis motores paso a paso sin que haga ruido.

Leí en algún lugar que la aceleración de la frecuencia de la señal modulada por impulsos ayudaría, pero parece tener los mismos problemas también. ¿Es la "aceleración" empinada ...?

El motor paso a paso que estoy usando es un PK244-01A , y está conectado a una placa de controladores, que requiere la habilitación, dirección y paso de la señal de entrada = > que es el que estoy ramping Driverboard

HEre es el código:

    void setup()
    {
      Serial.begin(9600);
      pinMode(9, OUTPUT); //Step
      pinMode(12,OUTPUT); //en
      pinMode(13,OUTPUT); //dir
      TCCR1A = _BV(COM1A1) | _BV(COM1B1) ; // phase and frequency correct mode. NON-inverted mode
      TCCR1B = _BV(WGM13) | _BV(CS11);     // Select mode 8
                                           // Prescaled by 8 on main clock.
    }


    float count = 1000; //

    void loop() {
      // put your main code here, to run repeatedly:
      //output_freq = CPU_clk/(2*8*ICR1_value)
      //ICR1 = CPU_clk/2*8*output_freq
      digitalWrite(12,HIGH);

      delay(1);

      digitalWrite(13,HIGH);

      delay(1);
      ICR1 = count;
      OCR1A = int(count/2);

      while(1)
      {
         if(count != 20)
         {
           count -= 10;
         }
      }
    }


The ICR1 value is computes using this formula $$ICR1 = \frac{(cpu_{freq})}{(2*prescaler*desired_{freq}))}$$

Se actualizó el código con las respuestas de @jms:

void setup()
    {
      Serial.begin(230400);
      pinMode(9, OUTPUT); //Step
      pinMode(12,OUTPUT); //en
      pinMode(13,OUTPUT); //dir
      TCCR1A = _BV(COM1A1) | _BV(COM1B1) ; // phase and frequency correct mode. NON-inverted mode
      TCCR1B = _BV(WGM13) | _BV(CS11);     // Select mode 8
                                           // Prescaled by 8 on main clock.
    }


    int count = 200000;

    void loop() {
      // put your main code here, to run repeatedly:
      //output_freq = CPU_clk/(2*8*ICR1_value)
      //ICR1 = CPU_clk/2*8*output_freq
      digitalWrite(12,HIGH);

      delay(1);

      digitalWrite(13,HIGH);

      delay(1);


      while(1)
      {


        int freq = (16000000)/(2*8*ICR1);

        ICR1 = count;
        OCR1A = int(count/2);

        Serial.print("freq: ");
        Serial.println(freq);
        Serial.print('\n');
        Serial.print("count: ");
        Serial.println(count);
        Serial.print('\n');
      }
    
pregunta Johnny_boi

1 respuesta

2
  • Tu código actual no hace ninguna rampa en absoluto. Después de configurar el temporizador 1 para generar una onda cuadrada en la salida del "paso", su código simplemente ingresa en un bucle infinito sin condición de salida ( while(1){... ).

    void loop() {
        ...
        ICR1 = count;
        OCR1A = int(count/2);
    
        while(1)
        {
            if(count != 20)
            {
                count -= 10;
            }
        }
    }  
    

    Sí, la variable count se decrementa en 10 cada vez que el ciclo while ejecuta una iteración, pero los registros del temporizador que controlan la forma de onda no se actualizan . ICR1 y OCR1A no son punteros a datos para leer, si eso es lo que pensaba.

  • No tiene ningún retraso en el ciclo de disminución del período de pasos, por lo que no obtendría una rampa de velocidad controlada incluso si actualizase los registros del temporizador en dicho ciclo.

  • Realmente desea evitar el uso de la aritmética de punto flotante en un microcontrolador de 8 bits (que carece de una unidad de punto flotante). No solo muchas operaciones de punto flotante pueden tardar milisegundos en calcularse, sino que su compilador debe incluir importantes funciones de biblioteca de punto flotante que aumentan drásticamente el tamaño de su código. En este caso, los flotadores ni siquiera tienen ninguna ventaja, ya que solo estás calculando con enteros.

  • Probar flotadores (como en if(count != 20)... ) para la igualdad (o desigualdad) es generalmente una mala idea en cualquier plataforma. Los números de punto flotante no son números reales perfectos, y sufren por ej. Errores limitados de precisión y redondeo. Podría pensar que 10.000002 y 10.000000 son iguales, pero su computadora no estará de acuerdo.

    float a = 0.0, b = 10.0;
    for(int n = 100; n > 0; --n)
        a = a + 0.1;
    
    if(a != b)
        printf("a and b are not equal!\n");
    printf("a: %f, b: %f", a, b);  
    
    //prints out:  
    //a and b are not equal!
    //a: 10.000002, b: 10.000000
    
respondido por el jms

Lea otras preguntas en las etiquetas