0
\$\begingroup\$

I am currently working with interfacing a stepper motor (4-pin bipolar), and providing it the propper input signal, such that it accelelrate and decellerate correctly. In recently also across an application note by atmel (link), which adresses this issue, and also provides the code for programming a timer to do so which is available on github (github).. (Perfect) Since i already have the driver, i don't need to provide it a 4 pin signal (A+,A-,B-,B+) but only a pulse modulated signal, with a increasing and decreasing the frequency for a given amount of steps.

I changed the ISR routine, as it seemed to be where the step signal seemed to be generated, and changed it to toggle the state of the step_pin everytime an interrupt occured, thus recreating a PWM signal. Problem is though that signal doesn't resemble that, and if i remove the Serial.print() become the signal a sawtooth shaped signal.

enter image description here 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;
}

The ISR routine is here..

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); 
}

The rest if the code is the same as before, and available on github.

I know i am doing something wrong here? but how do i create the desired signal?

here is the schematic of the setup:

Setup

Edit - Setup output_pins() I use the function setup_output_pins() To setup the output pins, i did though read somewhere that wasn't a good idea as the arduino need some time to settle or something?

\$\endgroup\$

closed as unclear what you're asking by brhans, Daniel Grillo, Voltage Spike, pjc50, dim Oct 20 '16 at 12:47

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ ... and your schematic is where? \$\endgroup\$ – brhans Oct 5 '16 at 17:00
  • \$\begingroup\$ A schmatic of how things are connected has been added.. I pretty sure the error is in the code, and not in the setup.. \$\endgroup\$ – Sorrow Oct 5 '16 at 17:10
  • \$\begingroup\$ well... At the moment i just testing it, So the arduino uno and the motor driver board ST330 aren't connected. I am currently scoping the output of the arduino \$\endgroup\$ – Sorrow Oct 5 '16 at 17:24
  • 1
    \$\begingroup\$ You have to load the GPIO, leaving the GPIO floating makes sense such output transition. \$\endgroup\$ – Marko Buršič Oct 5 '16 at 17:26
  • 4
    \$\begingroup\$ @Sorrow When you'll finish, you can answer your own question, with new scope image. Maybe you will help someone with similar problem. \$\endgroup\$ – Marko Buršič Oct 5 '16 at 17:46
1
\$\begingroup\$

Since this question was regarding why i am getting a sawtooth signal rather than a square signal, will this answer "close" this question.

@Marko Buršič mentioned that the issue might have been that the Pins were floating, seemed to have been the case. initiliazing them in the setup routine fixed the issue I had and provided me with the desired square shaped signal.

Blurred image of the wanted signal

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.