¿Por qué la señal tiene forma de diente de sierra? [cerrado]

0

Actualmente estoy trabajando con la interfaz de un motor paso a paso (bipolar de 4 pines) y proporcionándole la señal de entrada adecuada, de manera que acelere y decelere correctamente. Recientemente también a través de una nota de aplicación por atmel (enlace), que aborda este problema y también proporciona el código para programando un temporizador para hacerlo, que está disponible en github (github) .. (Perfecto) Como ya tengo el controlador, no necesito darle una señal de 4 pines (A +, A-, B-, B +) sino solo una señal modulada por impulsos, con un aumento y una disminución de la frecuencia para una cantidad determinada de pasos .

Cambié la rutina ISR, ya que parecía ser donde parecía que se generaba la señal de paso, y la cambié para cambiar el estado de step_pin cada vez que ocurría una interrupción, recreando así una señal PWM. El problema es que la señal no se parece a eso, y si elimino Serial.print() , la señal se convierte en una señal con forma de diente de sierra.

ISR(TIMER1_COMPA_vect)    {      //Mantieneelsiguienteperiododedemora.      unsignedintnew_step_delay;

//Rememberthelaststepdelayusedwhenaccelrating.staticintlast_accel_delay;//Countingstepswhenmoving.staticunsignedintstep_count=0;//Keeptrackofremainderfromnew_step-delaycalculationtoincraseaccurancystaticunsignedintrest=0;OCR1A=profile.step_delay;Serial.print('\n');Serial.print("step_delay: ");
  Serial.println(profile.step_delay);
  Serial.print('\n');

  switch (profile.run_state)
  {

    case STOP:
      step_count = 0;
      rest = 0;
      TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
      break;

    case ACCEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      profile.accel_count++;
      new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest) / (4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.step_delay) + rest) % (4 * profile.accel_count + 1);

      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_val;
        profile.run_state = DECEL;
      }

      // Chech if we hitted max speed.
      else if (new_step_delay <= profile.min_time_delay)
      {
        last_accel_delay = new_step_delay;
        new_step_delay = profile.min_time_delay;
        rest = 0;
        profile.run_state = RUN;
      }
      break;
    case RUN:
       digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      new_step_delay = profile.min_time_delay;
      // Chech if we should start decelration.
      if (step_count >= profile.decel_start) 
      {
        profile.accel_count = profile.decel_val;
        // Start decelration with same delay as accel ended with.
        new_step_delay = last_accel_delay;
        profile.run_state = DECEL;
      }
      break;
    case DECEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      step_count++;
      profile.accel_count++;
      new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest)/(4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.step_delay)+rest)%(4 * profile.accel_count + 1);
      // Check if we at last step
      if(profile.accel_count >= 0)
      {
        profile.run_state = STOP;
      }
      break;

  }
    profile.step_delay = new_step_delay;
}

La rutina ISR está aquí ..

ISR(TIMER1_COMPA_vect)
{
  // Holds next delay period.
  unsigned int new_step_delay;

  // Remember the last step delay used when accelrating.
  static int last_accel_delay;

  // Counting steps when moving.
  static unsigned int step_count = 0;

  // Keep track of remainder from new_step-delay calculation to incrase accurancy
  static unsigned int rest = 0;

  OCR1A = profile.step_delay;
  Serial.print('\n');
  Serial.print("step_delay: ");
  Serial.println(profile.step_delay);
  Serial.print('\n');

  switch (profile.run_state)
  {

    case STOP:
      step_count = 0;
      rest = 0;
      TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
      break;

    case ACCEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      profile.accel_count++;
      new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest) / (4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.step_delay) + rest) % (4 * profile.accel_count + 1);

      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_val;
        profile.run_state = DECEL;
      }

      // Chech if we hitted max speed.
      else if (new_step_delay <= profile.min_time_delay)
      {
        last_accel_delay = new_step_delay;
        new_step_delay = profile.min_time_delay;
        rest = 0;
        profile.run_state = RUN;
      }
      break;
    case RUN:
       digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      new_step_delay = profile.min_time_delay;
      // Chech if we should start decelration.
      if (step_count >= profile.decel_start) 
      {
        profile.accel_count = profile.decel_val;
        // Start decelration with same delay as accel ended with.
        new_step_delay = last_accel_delay;
        profile.run_state = DECEL;
      }
      break;
    case DECEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      step_count++;
      profile.accel_count++;
      new_step_delay = profile.step_delay - (((2 * (long)profile.step_delay) + rest)/(4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.step_delay)+rest)%(4 * profile.accel_count + 1);
      // Check if we at last step
      if(profile.accel_count >= 0)
      {
        profile.run_state = STOP;
      }
      break;

  }
    profile.step_delay = new_step_delay;
}

main

#include "speed_profile.h"

void setup() {
  // put your setup code here, to run once:
  cli();
  Serial.begin(230400);
  output_pin_setup();
  timer1_setup();
  sei();
}

void loop() 
{
  // put your main code here, to run repeatedly:
  Serial.print("start");
  Serial.print('\n');

  int motor_steps = 10000;
  // Accelration to use.
  int motor_acceleration = 10;
  // Deceleration to use.
  int motor_deceleration = 10;
  // Speed to use.
  int motor_speed = 500;
  compute_speed_profile(motor_steps, motor_acceleration, motor_deceleration, motor_speed);
  Serial.print("NewRound");
  Serial.print('\n');

}

output_pin_setup ();

void output_pin_setup()
{
  pinMode(en_pin,OUTPUT);
  pinMode(dir_pin,OUTPUT);
  pinMode(step_pin,OUTPUT); 
}

El resto si el código es el mismo que antes, y está disponible en github.

Sé que estoy haciendo algo mal aquí? pero ¿cómo creo la señal deseada?

Aquí está el esquema de la configuración:

Editar - Configurar output_pins () Yo uso la función setup_output_pins () Para configurar los pines de salida, he leído en algún lugar que no era una buena idea, ya que el arduino necesita algo de tiempo para establecerse o algo así.

    
pregunta Sorrow

1 respuesta

1

Dado que esta pregunta fue sobre por qué recibo una señal de diente de sierra en lugar de una señal cuadrada, ¿esta respuesta "cerrará" esta pregunta?

@Marko Buršič mencionó que el problema podría haber sido que los Pins flotaban, parecía haber sido el caso. Iniciándolos en la rutina de instalación solucioné el problema que tenía y me proporcionó la señal cuadrada deseada.

    
respondido por el Sorrow

Lea otras preguntas en las etiquetas