저번에 "한 번에 2개 이상의 스테핑 모터를 제어하기"를 했었는데.......

'Stepper'라이브러리가 업데이트 많이 됐군요. ㅎㅎㅎ

 

버전에 맞춰 업데이트해보았습니다.

 

 

[Arduino] 'Stepper.h'는 두개의 모터를 제어할 수 없다.

[Arduino] 한번에 2개이상의 스테핑 모터를 제어하기

[Arduino] 한 번에 2개 이상의 스테핑 모터를 제어하기 - StepperMulti5

 

 

이전 글에서 'Stepper.h'는 '.step()'이 동작하는 동안 다른 동작을 할 수 없다고 이야기했습니다.

(참고 : [Arduino] 'Stepper.h'는 두개의 모터를 제어할 수 없다. )

그래서 'Stepper.h'를 수정한 라이브러를 작성하고 사용하는 방법에 대한 포스팅입니다.

 

 

 

기존 'Stepper'를 수정하는 방법은 이전 글에서 다뤘으므로 이 포스팅은 수정된 코드만 나열합니다.

 

 

1. Stepper.h -> StepperMulti5.h

헤더는 거의 그대로입니다.

 

참고 : github - StepperMulti5.h

/*
  StepperMulti5.h
  ( http://blog.danggun.net/2092 )
  이 라이브러리는 아두이노의 'Stepper.h'를 개조한 라이브러리입니다.
  (Stepper.h : http://arduino.cc/en/reference/stepper )
  모든 내용은 'Stepper.h'와 거의 동일합니다.
  (1.1.0버전 기준)
*/
 
/*
 * Stepper.h - Stepper library for Wiring/Arduino - Version 1.1.0
 *
 * Original library        (0.1)   by Tom Igoe.
 * Two-wire modifications  (0.2)   by Sebastian Gassner
 * Combination version     (0.3)   by Tom Igoe and David Mellis
 * Bug fix for four-wire   (0.4)   by Tom Igoe, bug fix from Noah Shibley
 * High-speed stepping mod         by Eugene Kozlenko
 * Timer rollover fix              by Eugene Kozlenko
 * Five phase five wire    (1.1.0) by Ryan Orendorff
 *
 *
 * http://www.arduino.cc/en/Tutorial/Stepper
 */
 
// ensure this library description is only included once
#ifndef StepperMulti5_h
#define StepperMulti5_h
 
// library interface description
class StepperMulti5 {
  public:
    // constructors:
    StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2);
    StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                        int motor_pin_3, int motor_pin_4);
    StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                        int motor_pin_3, int motor_pin_4,
                                        int motor_pin_5);
 
    // speed setter method:
    void setSpeed(long whatSpeed);
 
    // mover method:
    void setStep(int number_of_steps);
    //'loop()'안에서 이 메소드를 호출해야 한다.
    void moveStep();
 
    int version(void);
 
  private:
    void stepMotor(int this_step);
 
    int direction;            // Direction of rotation
    unsigned long step_delay; // delay between steps, in ms, based on speed
    int number_of_steps;      // total number of steps this motor can take
    int pin_count;            // how many pins are in use.
    int step_number;          // which step the motor is on
 
    // motor pin numbers:
    int motor_pin_1;
    int motor_pin_2;
    int motor_pin_3;
    int motor_pin_4;
    int motor_pin_5;          // Only 5 phase motor
 
    unsigned long last_step_time; // time stamp in us of when the last step was taken
 
    //스템 저장
    int steps_left;
};
 
#endif

 

 

2. Stepper.cpp -> StepperMulti5.cpp

약간 바뀐 것이 있는데.....크진 않습니다.

 

step_number

this->step_number

로 바꿔줍니다.

 

참고 : github - StepperMulti5.cpp

/*
  StepperMulti5.h
  ( http://blog.danggun.net/2092 )
  이 라이브러리는 아두이노의 'Stepper.h'를 개조한 라이브러리입니다.
  (Stepper.h : http://arduino.cc/en/reference/stepper )
  모든 내용은 'Stepper.h'와 거의 동일합니다.
  (1.1.0버전 기준)
*/
 
/*
 * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.0
 *
 * Original library        (0.1)   by Tom Igoe.
 * Two-wire modifications  (0.2)   by Sebastian Gassner
 * Combination version     (0.3)   by Tom Igoe and David Mellis
 * Bug fix for four-wire   (0.4)   by Tom Igoe, bug fix from Noah Shibley
 * High-speed stepping mod         by Eugene Kozlenko
 * Timer rollover fix              by Eugene Kozlenko
 * Five phase five wire    (1.1.0) by Ryan Orendorff
 *
 * http://www.arduino.cc/en/Tutorial/Stepper
 */
 
#include "Arduino.h"
//헤더 연결 변경
#include "StepperMulti5.h"
 
/*
 * two-wire constructor.
 * Sets which wires should control the motor.
 */
StepperMulti5::StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2)
{
  //스탭초기화
  this->steps_left = 0;
 
  this->step_number = 0;    // which step the motor is on
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
 
  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
 
  // When there are only 2 pins, set the others to 0:
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;
  this->motor_pin_5 = 0;
 
  // pin_count is used by the stepMotor() method:
  this->pin_count = 2;
}
 
 
/*
 *   constructor for four-pin version
 *   Sets which wires should control the motor.
 */
StepperMulti5::StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4)
{
  //스탭초기화
  this->steps_left = 0;
 
  this->step_number = 0;    // which step the motor is on
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;
 
  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);
 
  // When there are 4 pins, set the others to 0:
  this->motor_pin_5 = 0;
 
  // pin_count is used by the stepMotor() method:
  this->pin_count = 4;
}
 
/*
 *   constructor for five phase motor with five wires
 *   Sets which wires should control the motor.
 */
StepperMulti5::StepperMulti5(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4,
                                      int motor_pin_5)
{
 
  //스탭초기화
  this->steps_left = 0;
 
  this->step_number = 0;    // which step the motor is on
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;
  this->motor_pin_5 = motor_pin_5;
 
  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);
  pinMode(this->motor_pin_5, OUTPUT);
 
  // pin_count is used by the stepMotor() method:
  this->pin_count = 5;
}
 
/*
 * Sets the speed in revs per minute
 */
void StepperMulti5::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed;
}
 
/*
 * Moves the motor steps_to_move steps.  If the number is negative,
 * the motor moves in the reverse direction.
 */
void StepperMulti5::setStep(int steps_to_move)
{
  //전역 번수에 스탭을 저장한다.
  this->steps_left = abs(steps_to_move);  // how many steps to take
 
  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) { this->direction = 1; }
  if (steps_to_move < 0) { this->direction = 0; }
 
 
  //스탭을 진행 한다.
  moveStep();
}
 
/*
 * loop안에서 호출하여 스탭모터의 동작을 제어한다.
*/
void StepperMulti5::moveStep()
{
    // decrement the number of steps, moving one step each time:
    // while -> if
    // 'while'의 역할을 'loop'가 대신 해주기 때문에 여기서는 'while'가 필요없다.
    //while (steps_left > 0)
    if(this->steps_left > 0)
    {
        unsigned long now = micros();
        // move only if the appropriate delay has passed:
        if (now - this->last_step_time >= this->step_delay)
        {
            // get the timeStamp of when you stepped:
            this->last_step_time = now;
            // increment or decrement the step number,
            // depending on direction:
            if (this->direction == 1)
            {
                this->step_number++;
                if (this->step_number == this->number_of_steps) {
                    this->step_number = 0;
                }
            }
            else
            {
                if (this->step_number == 0) {
                    this->step_number = this->number_of_steps;
                }
                this->step_number--;
            }
            
            //스탭 남은 개수를 전역변수에 저장한다.
            this->steps_left--;// decrement the steps left:
            // step the motor to step number 0, 1, ..., {3 or 10}
            if (this->pin_count == 5)
                stepMotor(this->step_number % 10);
            else
                stepMotor(this->step_number % 4);
        }
    }
}
 
 
/*
 * Moves the motor forward or backwards.
 */
void StepperMulti5::stepMotor(int thisStep)
{
  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0:  // 01
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 1:  // 11
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 2:  // 10
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
      break;
      case 3:  // 00
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:  // 1010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 1:  // 0110
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 2:  //0101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:  //1001
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }
 
  if (this->pin_count == 5) {
    switch (thisStep) {
      case 0:  // 01101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 1:  // 01001
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 2:  // 01011
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 3:  // 01010
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 4:  // 11010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 5:  // 10010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 6:  // 10110
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 7:  // 10100
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 8:  // 10101
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 9:  // 00101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
    }
  }
}
 
/*
  version() returns the version of the library:
*/
int StepperMulti5::version(void)
{
  return 5;
}

 

 

3. 테스트

이제 테스트 코드를 만들어 봅시다.

 

참고 : github - StepperMulti5_Examples.ino

 

#include <StepperMulti5.h>
 
StepperMulti5 stepper(200, 12, 11, 10, 9);
StepperMulti5 stepper2(200, 7, 6, 5, 4);
 
void setup() 
{
  Serial.begin(9600);
  stepper.setSpeed(30);
  stepper2.setSpeed(60);
}
 
void loop() 
{
  if (Serial.available())
  {
    int steps = Serial.parseInt();
 
    if(steps != 0)
    {
      stepper.setStep(steps);
      stepper2.setStep(steps);
      //stepper.setStep(200);
      //stepper2.setStep(200);
  
      Serial.print("steps : ");
      Serial.println(steps); 
    }
    
  }
  
  stepper.moveStep();
  stepper2.moveStep();
 
}

 

이제 테스트를 해봅시다.

 

 

 

마무리

완성된 샘플 : Github - Arduino_StepperMulti/StepperMulti5/

라이브러리 다운로드 :  

StepperMulti5.zip
다운로드

 

이제는 라이브러리에 출력 버전이 있네요.

출력 버전에 맞춰 이름을 바꿀 예정입니다.

핫 포스팅