stepper: two (synchronous) steppers

The mount will need two stepper motors and I want them to both move at the same time – I don’t want to ‘move all the azimuth steps’ and then ‘move all the altitude steps’. And they also need to accelerate / decelerate as in the last post.

So, again, a bit of amendment was necessary to the arduino stepper library.

An example sketch

The end result looks like this:

/*
 * Two synchronous stepper motors  
 * uses the Stepper_Aclr8_2 library
 *
 * created by Ben @ cape ealing
 * 25 May 2008
 *
 */

// include the library
#include 

// initialise the class
Steppers_Aclr8_2 MyTwoSteppers = Steppers_Aclr8_2();

void setup()
{
  // define each stepper motor
  // (no of steps per rev, pin1, pin2, pin3, pin4)
  MyTwoSteppers.stepper1(200, 4, 6, 5, 7);
  MyTwoSteppers.stepper2(200, 8, 10, 9, 11);

  // define the rates of each motor
  // (min speed, max speed, steps take to accelerate)
  MyTwoSteppers.stepper1speeds(5, 30, 200);
  MyTwoSteppers.stepper2speeds(10, 40, 100);
}

void loop()
{
// First motor: 600 steps forward
// Second motor: 300 steps back
MyTwoSteppers.step(600, -300);
delay(2000);

// First motor: 300 steps backward
// Second motor: 600 steps forward
MyTwoSteppers.step(-300, 600);
delay(2000);
}

The main class

The heart of the library is below:

/*
  Steppers_Aclr8_2.cpp 
  A library for two (synchronous stepper motors 
  with acceleration and deceleration 
  for Wiring/Arduino 
  - Version 1.0
 */

#include "WProgram.h"
#include "Steppers_Aclr8_2.h"


/*
 *   Initialise the class
 */
Steppers_Aclr8_2::Steppers_Aclr8_2()
{
}

/*	 First motor
 *   Constructor for four-pin stepper motor
 *   Sets which wires should control the motor and
 *   primary variables used by motor.
 */
void Steppers_Aclr8_2::stepper1(int number_of_steps1, \
						   int motor1_pin_1, int motor1_pin_2, \
						   int motor1_pin_3, int motor1_pin_4)
{
  // which step the motor is on
  this->step_number1 = 0;
  // the motor speed1, in revolutions per minute
  this->speed1 = 0;
  // motor direction1
  this->direction1 = 0;
  // time stamp in ms of the last step taken
  this->last_step_time1 = 0;
  // total number of steps for this motor
  this->number_of_steps1 = number_of_steps1;
  // find the delay nec at 1 rev per min
  this->delay_1revpermin1 = 60L * 1000L  / number_of_steps1;

  // Arduino pins for the motor control connection
  this->motor1_pin_1 = motor1_pin_1;
  this->motor1_pin_2 = motor1_pin_2;
  this->motor1_pin_3 = motor1_pin_3;
  this->motor1_pin_4 = motor1_pin_4;

  // setup the pins on the microcontroller
  pinMode(this->motor1_pin_1, OUTPUT);
  pinMode(this->motor1_pin_2, OUTPUT);
  pinMode(this->motor1_pin_3, OUTPUT);
  pinMode(this->motor1_pin_4, OUTPUT);
}

/*	 Second motor
 *   Constructor for four-pin stepper motor
 *   Sets which wires should control the motor and
 *   primary variables used by motor.
 */
void Steppers_Aclr8_2::stepper2(int number_of_steps2, \
						   int motor2_pin_1, int motor2_pin_2, \
						   int motor2_pin_3, int motor2_pin_4)
{
  // which step the motor is on
  this->step_number2 = 0;
  // the motor speed, in revolutions per minute
  this->speed2 = 0;
  // motor direction
  this->direction2 = 0;
  // time stamp in ms of the last step taken
  this->last_step_time2 = 0;
  // total number of steps for this motor
  this->number_of_steps2 = number_of_steps2;
  // find the delay nec at 1 rev per min
  this->delay_1revpermin2 = 60L * 1000L  / number_of_steps2;

  // Arduino pins for the motor control connection
  this->motor2_pin_1 = motor2_pin_1;
  this->motor2_pin_2 = motor2_pin_2;
  this->motor2_pin_3 = motor2_pin_3;
  this->motor2_pin_4 = motor2_pin_4;

  // setup the pins on the microcontroller
  pinMode(this->motor2_pin_1, OUTPUT);
  pinMode(this->motor2_pin_2, OUTPUT);
  pinMode(this->motor2_pin_3, OUTPUT);
  pinMode(this->motor2_pin_4, OUTPUT);
}

/*	First motor
	Set the min speed, max speed, and steps taken to accelerate
*/
void Steppers_Aclr8_2::stepper1speeds(long minSpeed1, long maxSpeed1, double Accel1)
{
	this->motorMinSpeed1 = minSpeed1;
	this->motorMaxSpeed1 = maxSpeed1;
	// Number of steps to accelerate over
	this->motorAccSteps1 = Accel1;
	// Change in speed1 needed per step
	this->motorAccelVal1 = (this->motorMaxSpeed1 -this->motorMinSpeed1) / (Accel1-1);
}

/*	Second motor
	Set the min speed, max speed, and steps taken to accelerate
*/
void Steppers_Aclr8_2::stepper2speeds(long minSpeed2, long maxSpeed2, double Accel2)
{
	this->motorMinSpeed2 = minSpeed2;
	this->motorMaxSpeed2 = maxSpeed2;
	// Number of steps to accelerate over
	this->motorAccSteps2 = Accel2;
	// Change in speed1 needed per step
	this->motorAccelVal2 = (this->motorMaxSpeed2 -this->motorMinSpeed2) / (Accel2-1);
}

/*	
	Step method for both motors
*/
void Steppers_Aclr8_2::step(int steps_to_move1, int steps_to_move2)
{
  // steps taken
  int steps_no1= 1;
  int steps_no2= 1;

  // Steps for each motor to complete, and the total
  // how many steps to take for the motor
  int steps_left1 = abs(steps_to_move1);
  int steps_left2 = abs(steps_to_move2);
  int total_steps_left = steps_left1 + steps_left2;

  // determine direction1 based on whether steps_to_mode is + or -:
  if (steps_to_move1 > 0) {this->direction1 = 1;}
  else
  {this->direction1 = 0;}
  if (steps_to_move2 > 0) {this->direction2 = 1;}
  else
  {this->direction2 = 0;}

  // reset the motor speed
  this->speed1 = this->motorMinSpeed1;
  this->speed2 = this->motorMinSpeed2;

  // this is the loop for both motor
  while(total_steps_left > 0) {

	//First motor
	//If the motor steps not completed it's steps then
    if (steps_left1 > 0) {

	  //1.a. if in the first third of total steps AND
	  if ((steps_left1 > abs(steps_to_move1/3)) && \
		  (steps_left1 > (abs(steps_to_move1/3)*2))) {
			  // 1.b if not yet at max speed1
			  if (this->speed1 < this->motorMaxSpeed1){
				  // get the new speed1
				  this->speed1 = ((steps_no1 -1) * this->motorAccelVal1) + this->motorMinSpeed1; 
				  // get the new delay
				  step_delay1 = (this->delay_1revpermin1 / this->speed1); 
              } // i.b.  end if: not yet max speed1
	  } //1.a. end if: first third of total steps
			  
	  //2. if in middle third of steps do nothing

	  //3.a. if in the last third of total steps AND
	  if (steps_left1 <= (abs(steps_to_move1)/3)) {
		  //3.b. if within deceleration zone
		  if (steps_left1 <= this->motorAccSteps1) {
			  // get the new speed1
			  this->speed1 = ((steps_left1-1) * this->motorAccelVal1) + this->motorMinSpeed1; 
			  // get the new delay
			  step_delay1 = (this->delay_1revpermin1 / this->speed1); 
		} //end if: within deceleration zone
	  } //3.a. end if: last third of total steps

      // move only if the appropriate delay has passed:
      if (millis() - this->last_step_time1 >= this->step_delay1) {
        // get the timeStamp of when you stepped:
        this->last_step_time1 = millis();
          // increment or decrement the step number,
          // depending on direction1:
          if (this->direction1 == 1) {
            this->step_number1++;
            if (this->step_number1 == this->number_of_steps1) {
            this->step_number1 = 0;
            }
          }
          else
		  {
            if (this->step_number1 == 0) {
            this->step_number1 = this->number_of_steps1;
            }
          this->step_number1--;
          }
      // in/decrement the steps left:
      steps_no1++;
      steps_left1--;
	  total_steps_left--;
      
	  // step the motor to step number 0, 1, 2, or 3:
      stepMotor1(this->step_number1 % 4);
      }
    } //End: if (steps_left1 > 0)

	//Second motor  
	//If the motor steps not completed it's steps then
    if (steps_left2 > 0) {

	  //1.a. if in the first third of total steps AND
	  if ((steps_left2 > abs(steps_to_move2/3)) && \
		  (steps_left2 > (abs(steps_to_move2/3)*2))) {
			  // 1.b if not yet at max speed1
			  if (this->speed2 < this->motorMaxSpeed2){
				  // get the new speed1
				  this->speed2 = ((steps_no2 -1) * this->motorAccelVal2) + this->motorMinSpeed2; 
				  // get the new delay
				  step_delay2 = (this->delay_1revpermin2 / this->speed2); 
              } // i.b.  end if: not yet max speed1
	  } //1.a. end if: first third of total steps
			  
	  //2. if in middle third of steps do nothing

	  //3.a. if in the last third of total steps AND
	  if (steps_left2 <= (abs(steps_to_move2)/3)) {
		  //3.b. if within deceleration zone
		  if (steps_left2 <= this->motorAccSteps2) {
			  // get the new speed1
			  this->speed2 = ((steps_left2-1) * this->motorAccelVal2) + this->motorMinSpeed2; 
			  // get the new delay
			  step_delay2 = (this->delay_1revpermin2 / this->speed2); 
		} //end if: within deceleration zone
	  } //3.a. end if: last third of total steps

      // move only if the appropriate delay has passed:
      if (millis() - this->last_step_time2 >= this->step_delay2) {
        // get the timeStamp of when you stepped:
        this->last_step_time2 = millis();
          // increment or decrement the step number,
          // depending on direction1:
          if (this->direction2 == 1) {
            this->step_number2++;
            if (this->step_number2 == this->number_of_steps2) {
            this->step_number2 = 0;
            }
          }
          else
		  {
            if (this->step_number2 == 0) {
            this->step_number2 = this->number_of_steps2;
            }
          this->step_number2--;
          }
      // in/decrement the steps left:
      steps_no2++;
      steps_left2--;
	  total_steps_left--;
      
	  // step the motor to step number 0, 1, 2, or 3:
      stepMotor2(this->step_number2 % 4);
      }
    } //End: if (steps_left1 > 0)

  } //End: WHILE statement
} //End: void step()


/* First motor
 * Moves the motor forward or backwards
 */
void Steppers_Aclr8_2::stepMotor1(int thisStep1)
{
    switch (thisStep1) {
      case 0:    // 1010
      digitalWrite(motor1_pin_1, HIGH);
      digitalWrite(motor1_pin_2, LOW);
      digitalWrite(motor1_pin_3, HIGH);
      digitalWrite(motor1_pin_4, LOW);
      break;
      case 1:    // 0110
      digitalWrite(motor1_pin_1, LOW);
      digitalWrite(motor1_pin_2, HIGH);
      digitalWrite(motor1_pin_3, HIGH);
      digitalWrite(motor1_pin_4, LOW);
      break;
      case 2:    //0101
      digitalWrite(motor1_pin_1, LOW);
      digitalWrite(motor1_pin_2, HIGH);
      digitalWrite(motor1_pin_3, LOW);
      digitalWrite(motor1_pin_4, HIGH);
      break;
      case 3:    //1001
      digitalWrite(motor1_pin_1, HIGH);
      digitalWrite(motor1_pin_2, LOW);
      digitalWrite(motor1_pin_3, LOW);
      digitalWrite(motor1_pin_4, HIGH);
      break;
    }
}


/* Second motor
 * Moves the motor forward or backwards
 */
void Steppers_Aclr8_2::stepMotor2(int thisStep2)
{
    switch (thisStep2) {
      case 0:    // 1010
      digitalWrite(motor2_pin_1, HIGH);
      digitalWrite(motor2_pin_2, LOW);
      digitalWrite(motor2_pin_3, HIGH);
      digitalWrite(motor2_pin_4, LOW);
      break;
      case 1:    // 0110
      digitalWrite(motor2_pin_1, LOW);
      digitalWrite(motor2_pin_2, HIGH);
      digitalWrite(motor2_pin_3, HIGH);
      digitalWrite(motor2_pin_4, LOW);
      break;
      case 2:    //0101
      digitalWrite(motor2_pin_1, LOW);
      digitalWrite(motor2_pin_2, HIGH);
      digitalWrite(motor2_pin_3, LOW);
      digitalWrite(motor2_pin_4, HIGH);
      break;
      case 3:    //1001
      digitalWrite(motor2_pin_1, HIGH);
      digitalWrite(motor2_pin_2, LOW);
      digitalWrite(motor2_pin_3, LOW);
      digitalWrite(motor2_pin_4, HIGH);
      break;
    }
}

/*
  version() returns the version of the library:
*/
int Steppers_Aclr8_2::version(void)
{
  return 1;
}

The full library can be downloaded here.
Ben

post a comment...

you must be logged in to post a comment.