이전 글에서 'Stepper.h'는 '.step()'이 동작하는 동안 다른 동작을 할 수 없다는 것을 이야기하였습니다.
(참고 : [Arduino] 'Stepper.h'는 두개의 모터를 제어할 수 없다.)
그래서 'Stepper.h'를 약간 개조하여 한번에 여러 개의 동작(스탭모터라던가 led같은 것들)을 할 수 있도록 수정하겠습니다.
[Arduino] 'Stepper.h'는 두개의 모터를 제어할 수 없다.
* Stepper library for Wiring/Arduino - Version 0.4 기준 입니다. *
* 2019-11-27 기준 최신버전은 5버전입니다 ->
StepperMulti5
*
참고 : [Arduino] 한 번에 2개 이상의 스테핑 모터를 제어하기 - StepperMulti5
저번 글에서도 잠깐 이야기했습니다만 기존 라이브러리의 문제는 'while()'문이 끝나야 '.step()'가 끝난다는 것입니다.
그러니 기존 '.step()'에서 'while()'문 안의 내용을 따로 메소드로 빼서 호출해야 합니다.
이제 기존에 있는 라이브러리의 코드를 그대로 복사하여 이름을 'StepperMulti'로 바꿔 준다음 내용을 수정합니다.
(1) '.step()'의 역할이 좀 달라졌으므로 'setStep()'로 이름을 바꾸고 'void moveStep();'를 추가합니다.
(2) '.step()'의 안에 지역변수가 있는데 이것을 꺼내서 클래스 지역변수로 만듭니다.
/*
StepperMulti.h
( http://blog.danggun.net/2092 )
이 라이브러리는 아두이노의 'Stepper.h'를 개조한 라이브러리입니다.
(Stepper.h : http://arduino.cc/en/reference/stepper )
모든 내용은 'Stepper.h'와 거의 동일합니다.
(0.4버전 기준)
*/
// ensure this library description is only included once
#ifndef StepperMulti_h
#define StepperMulti_h
// library interface description
class StepperMulti
{
public:
// constructors:
StepperMulti(int number_of_steps, int motor_pin_1, int motor_pin_2);
StepperMulti(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4);
// speed setter method:
void setSpeed(long whatSpeed);
// mover method:
void setStep(int number_of_steps);
//'loop()'안에서 이 메소드를 호출해야 한다.
void moveStep();
private:
void stepMotor(int this_step);
int direction; // Direction of rotation
int speed; // Speed in RPMs
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; // whether you're driving the motor with 2 or 4 pins
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;
long last_step_time; // time stamp in ms of when the last step was taken
//스텝 저장
int steps_left;
};
#endif
'StepperMulti.h'에서 수정한 'setStep()'과 'void moveStep();'을 만들어야 합니다.
(1) 기존에 있던 'step()'의 이름을 'setStep()'로 바꿉니다.
(2) 'void moveStep()'을 만듭니다.
(3) 'setStep()'의 내용 중 'while()'문의 내용을 'void moveStep()'으로 옮깁니다.
(4) 'while()'를 if로 바꿉니다.
'while'의 역할을 'loop'가 대신 해주기 때문입니다.
#include "Arduino.h"
#include "StepperMulti.h"
/*
* two-wire constructor.
* Sets which wires should control the motor.
*/
StepperMulti::StepperMulti(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->speed = 0; // the motor speed, in revolutions per minute
this->direction = 0; // motor direction
this->last_step_time = 0; // time stamp in ms 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 other two to 0:
this->motor_pin_3 = 0;
this->motor_pin_4 = 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.
*/
StepperMulti::StepperMulti(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->speed = 0; // the motor speed, in revolutions per minute
this->direction = 0; // motor direction
this->last_step_time = 0; // time stamp in ms 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);
// pin_count is used by the stepMotor() method:
this->pin_count = 4;
}
/*
Sets the speed in revs per minute
*/
void StepperMulti::setSpeed(long whatSpeed)
{
this->step_delay = 60L * 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 StepperMulti::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();
}
void StepperMulti::moveStep()
{
//남은 스텝이 있는지?
if(this->steps_left > 0)
{
// move only if the appropriate delay has passed:
if (millis() - this->last_step_time >= this->step_delay)
{
// get the timeStamp of when you stepped:
this->last_step_time = millis();
// 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--;
}
// decrement the steps left:
this->steps_left--;
// step the motor to step number 0, 1, 2, or 3:
stepMotor(this->step_number % 4);
}
}
}
/*
* Moves the motor forward or backwards.
*/
void StepperMulti::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;
}
}
}
설마 여기까지 왔는데 라이브러리에 추가하는 것을 모르시는 건 아니겠죠?
모르시면 이전 글을 참고하시면 됩니다.
(참고 : [Arduino] 라이브러리 작성하기)
테스트용 프로그램을 만듭니다.
여기서 중요한 것은 'loop()'안에서 '.moveStep()'를 호출해야 합니다.
그 외에는 기존 'Stepper.h'와 비슷합니다.
#include <StepperMulti.h>
StepperMulti stepper(200, 8, 9, 10, 11);
StepperMulti stepper2(200, 4, 5, 6, 7);
void setup()
{
Serial.begin(9600);
stepper.setSpeed(30);
stepper2.setSpeed(60);
}
void loop()
{
if (Serial.available())
{
Serial.read();
stepper.setStep(200);
stepper2.setStep(200);
}
stepper.moveStep();
stepper2.moveStep();
}
이제 시리얼 모니터를 열고 데이터를 날려 봅시다.
잘 보시면 각각 모터가 속도가 다른걸 알 수 있습니다.
기존의 'Stepper.h'를 이용했다면 모터 한 개가 동작을 끝내야 다음 모터가 동작할 수 있죠.
하지만 우리가 개조한 'StepperMulti.h'는 그렇지 않습니다.
이전 글에서처럼 led를 연결해도 마치 안켜진 것 처럼 켜졌다 꺼집니다.
완성된 샘플 : Github dang-gun - Arduino_StepperMulti/StepperMulti/
이렇게 만든 라이브러리를 다운 받으세요 ㅎㅎㅎ
아두이노 폴더 밑에 'libraries'에 압축 푸시거나 '라이브러리 추가(Add Library...)'로 추가하시면 됩니다.
(참고 : [Arduino] 라이브러리 작성하기 )
여전히 왜 이런 자료를 못 찾은 것인지는 의문이지만 원하는 데로 작동하니 기분은 좋네요.
저번에도 말했다싶이 이렇게 수정한 코드는 'loop()'의 딜레이에 의해 잘못된 동작을 할 여지가 있습니다.
그건 각자 알아서 처리하셔야 합니다 ㅎㅎㅎ
#include <StepperMulti.h>
StepperMulti stepper(200, 8, 9, 10, 11);
StepperMulti stepper2(200, 4, 5, 6, 7);
int startButton = 13;
unsigned long step_delay;
void setup()
{
Serial.begin(9600);
stepper.setSpeed(500);
stepper2.setSpeed(1000);
pinMode(startButton, INPUT_PULLUP);
}
void loop()
{
if (digitalRead(startButton) == HIGH)
{
stepper.setStep(5000);
stepper2.setStep(20000);
delay(2000);
stepper.setStep(-5000);
stepper2.setStep(-20000);
}
stepper.moveStep();
stepper2.moveStep();
}
반대방향 회전이 안 되네요.
코드가 어떻게 잘못 된 건가요?
좋은글 감사합니다.
제가 아두이노 초보라 한가지 궁금한점이 있습니다.
동작을 올려주신대로 작동을 하였을 때, 모터가 0.몇초정도 떠는느낌만 나는데 이게 제가 스테핑모터를 잘못 연결해서 그렇다고 판단하였습니다. 그래서 질문을 드립니다.
보통 제가 스태핑모터의 IN1,2,3,4 를 우노의 8,9,10,11에 연결하였을 때,
Stepper myStepper(stepsPerRevolution, 11,9,10,8); 라고 적었습니다.
하지만 이 글에서는
StepperMulti stepper(200, 8, 9, 10, 11);
로 적어주셨습니다.
그래서 스테핑모터를 우노에 연결할 때, IN1,2,3,4를 8,9,10,11에 연결하고, 위처럼 StepperMulti stepper(200, 11, 9, 10, 8);로 적어서 실행도 해 보았으나 정상적으로 진행이 되지 않습니다.
저는 이 문제가 모터연결과 관련있다고 생각하였는데, 작성자님께선 어떻게 생각하시는가요 ㅠㅠ
안녕하세요 학교과제로 모터 돌리기를 하고있는데여 ㅠ
글은 정말 잘봤습니다 근데 궁금한게 있어서요
이게 소스인데- 모터가 서로 도는 속도가 조금은 다르더라구요
위에 딜레이로 조절하라고 하셨는데
제가 답을 모르곘어서.. 그냥 노가다로 모터마다 속도를 맞추면 되는건가요?
#include <StepperMulti.h>
StepperMulti stepper(200, 8, 9, 10, 11);
StepperMulti stepper2(200, 4, 5, 6, 7);
int startButton = 13;
void setup()
{
Serial.begin(9600);
stepper.setSpeed(50);
stepper2.setSpeed(50);
pinMode(startButton, INPUT_PULLUP);
}
void loop()
{
if (digitalRead(startButton) == HIGH)
{
Serial.println(startButton);
stepper.setStep(500);
stepper2.setStep(500);
}
stepper.moveStep();
stepper2.moveStep();
}
감사해요 ㅠㅠ 많이 배웠어요
저 그런데 혹시 얘가 역회전을 안하는데
뭐가 잘못된건지 말씀해주실수 있나요? 참고로 시리얼속도를 9600으로 하니까 엄청 천천히 끊기면서 돌길래 지금 속도가 74880 입니다
모터는 28byj-48 이에요
if ((tn>=0) && Y==0 && X==301) // X값이 301이고, 터치가 유지되면 [[ 모터 돌림 ]]
{
{
Serial.println("모터 돌리는중");
stepper2.setStep(256);
stepper1.setStep(-256);
}
stepper1.moveStep();
stepper2.moveStep();
}
#include <StepperMulti.h>
StepperMulti stepper(200, 5, 6, 7, 8) ; // A,A바,B,B바
StepperMulti stepper2(200, 9, 10, 11, 12);
int Button1 = 3;
int Button2 = 4;
void setup()
{
Serial.begin(9600);
pinMode(Button1,INPUT);
pinMode(Button2, INPUT);
}
void loop()
{
if(digitalRead(Button1) ==HIGH)
{
stepper.setSpeed(30);
stepper2.setSpeed(30);
stepper.setStep(100);
stepper2.setStep(100);
}
stepper.moveStep();
stepper2.moveStep();
stepper.setStep(0);
stepper2.setStep(0);
if(digitalRead(Button2) ==HIGH)
{
stepper.setSpeed(30);
stepper2.setSpeed(30);
stepper.setStep(-100);
stepper2.setStep(-100);
}
stepper.moveStep();
stepper2.moveStep();
stepper.setStep(0);
stepper2.setStep(0);
}
제가 지금 버튼 1을 눌렀을 때는 180도 정회전 하고 그대로 놔두고 버튼 2를 눌렀을 때
180도 역회전하는 코드를 작성하려는데 초보이다 보니깐 문법 신경안쓰고 코드르 작성했는데요
이 코드대로 하면 동작이 될지 모르겠습니다.
코드에 대해 도움 주시면 감사하겠습니다.
#include <StepperMulti.h>
StepperMulti stepper(200, 5, 6, 7, 8) ; // A,A바,B,B바
StepperMulti stepper2(200, 9, 10, 11, 12);
int Button1 = 3;
int Button2 = 4;
void setup()
{
Serial.begin(9600);
pinMode(Button1,INPUT);
pinMode(Button2, INPUT);
}
void loop()
{
if(digitalRead(Button1) ==HIGH)
{
stepper.setSpeed(60);
stepper2.setSpeed(60);
stepper.setStep(100);
stepper2.setStep(100);
}
if(digitalRead(Button2) ==HIGH)
{
stepper.setSpeed(60);
stepper2.setSpeed(60);
stepper.setStep(-100);
stepper2.setStep(-100);
}
}
정회전은 잘 되는데 역회전 버튼은 눌러도 꿈쩍도 안하는데 원인을 알 수 있을까요??
#include <StepperMulti.h>
#define LEFT 1
#define RIGHT 2
StepperMulti stepper(200, 9, 10);
StepperMulti stepper2(200, 11, 12);
void setup() {
// put your setup code here, to run once:
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
Serial.begin(9600);
stepper.setSpeed(150);
stepper2.setSpeed(150);
}
void loop() {
// put your main code here, to run repeatedly:
char dir;
if (Serial.available()){
dir = Serial.parseInt();
Serial.write(dir);
if (dir == LEFT){
Serial.println("LEFT Moving");
stepper.setStep(100);
stepper2.setStep(100);
} else if (dir == RIGHT){
Serial.println("RIGHT Moving");
stepper.setStep(-100);
stepper2.setStep(-100);
}
}
stepper.moveStep();
stepper2.moveStep();
}
제가 다음과 같이 코드를짜서 2개 모터를 돌려봤는데요
모터가 돌때 진동이 너무 심하게 나는데, 어떤 문제인지 알 수 있을까요?
http://www.devicemart.co.kr/goods/view?no=23051 모터이고
http://www.devicemart.co.kr/goods/view?no=9323 모듈입니다.
#include "StepperMulti.h"
#include "Arduino.h"
const int stepsPerRevolution = 200;
// change this to fit the number of steps per revolution
// for your motor
// initialize the stepper library on pins 8 through 11:
StepperMulti myStepperA(stepsPerRevolution, 10, 11, A0, A1);
StepperMulti myStepperB(stepsPerRevolution, 6, 7, A2, A3);
void setup() {
// set the speed at 60 rpm:
myStepperA.setSpeed(60);
myStepperB.setSpeed(60);
// initialize the serial port:
Serial.begin(9600);
}
void loop() {
int ReadVR=analogRead(A4);
if(ReadVR <512)
{
int motorSpeed = map(ReadVR,0,512,60,0);
Serial.println("clockwise");
myStepperB.setSpeed(motorSpeed);
myStepperA.setSpeed(motorSpeed);
myStepperA.setStep(stepsPerRevolution);
myStepperB.setStep(stepsPerRevolution);
}
// myStepper.step(stepsPerRevolution);
else {
int motorSpeed = map(ReadVR,512,1025,0,60);
myStepperA.setSpeed(motorSpeed);
myStepperB.setSpeed(motorSpeed);
myStepperA.setStep(-stepsPerRevolution);
myStepperB.setStep(-stepsPerRevolution);
}
myStepperA.moveStep();
myStepperB.moveStep();
}
안녕하세요 라이브러리 잘사용하고 있습니다. 감사합니다.
질문하나 하겠습니다. 가변저항이용해서 모터 속도제어 하고 있은데
정회전 , 역회전 속도 차이 있어요
원인을 알수 있을까요?
와 이렇게 라이브러리를 직접 수정하고 추가할수도 있네요. 저는 아직 초보라.;;ㅠ
제가 스텝모터랑 4digit FND를 동시에 작동하게 하려는데요. 코딩은 잘 몰라서 작성자분께서 올려놓으신 파일을 라이브러리로 추가하고 했는데 계속
보드 Arduino/Genuino Mega or Mega 2560 컴파일 에러
라고 뜨더라고요 이게 무슨 문제인지 모르겠어요..ㅠ 작성자분이 올려놓으신 라이브러리 지우고 기존의 스텝모터 라이브러리를 쓰면 컴파일 에러가 안나는데 왜 이런지 모르겠네요. 도와주세요
*방금 오류 메세지를 자세히 확인했는데 StepperMulti.h 헤더 파일에서
#include nested too deeply
라고 오류가 나네요
#include "Arduino.h"
#include <StepperMulti5.h>
StepperMulti5 stepper(200, 10, 7);
StepperMulti5 stepper2(200, 9, 6);
StepperMulti5 stepper3(200, 8, 5);
void setup()
{
Serial.begin(9600);
stepper.setSpeed(60);
stepper2.setSpeed(60);
stepper3.setSpeed(60);
}
void loop()
{
if (Serial.available())
{
int steps = Serial.parseInt();
if(steps != 0)
{
stepper.setStep(200);
stepper2.setStep(200);
stepper3.setStep(200);
//stepper.setStep(200);
//stepper2.setStep(200);
Serial.print("steps : ");
Serial.println(steps);
}
}
stepper.moveStep();
stepper2.moveStep();
}
동시에 3개의 스텝모터를 작동시키려하는데
모터드라이버 a4988쓰는데 왜 안될까요
#include "Arduino.h"
#include <StepperMulti5.h>
StepperMulti5 stepper(200, 10, 7);
StepperMulti5 stepper2(200, 9, 6);
StepperMulti5 stepper3(200, 8, 5);
void setup()
{
Serial.begin(9600);
stepper.setSpeed(60);
stepper2.setSpeed(60);
stepper3.setSpeed(60);
}
void loop()
{
stepper.setStep(200);
//정회전
Serial.println("clockwise");
delay(500);
//역회전
Serial.println("counterclockwise");
delay(500);
stepper2.setStep(200);
//정회전
Serial.println("clockwise");
delay(500);
//역회전
Serial.println("counterclockwise");
delay(500);
stepper3.setStep(200);
//정회전
Serial.println("clockwise");
delay(500);
//역회전
Serial.println("counterclockwise");
delay(500);
Serial.print("steps : 60");
Serial.println(60);
}
stepper.moveStep();
stepper2.moveStep();
stepper3.moveStep();
}
multi-test1:71:3: error: 'stepper' does not name a type
stepper.moveStep();
^~~~~~~
multi-test1:72:3: error: 'stepper2' does not name a type
stepper2.moveStep();
^~~~~~~~
multi-test1:73:3: error: 'stepper3' does not name a type
stepper3.moveStep();
^~~~~~~~
multi-test1:75:1: error: expected declaration before '}' token
}
^
exit status 1
'stepper' does not name a type
이런식의 오류가뜹니다..
#include "Arduino.h"
#include <StepperMulti5.h>
StepperMulti5 stepper(200, 10, 7); //a4988 모터드라이버와 연결된 핀
StepperMulti5 stepper2(200, 9, 6);
StepperMulti5 stepper3(200, 8, 5);
void setup()
{
Serial.begin(9600);
stepper.setSpeed(10);
stepper2.setSpeed(10);
stepper3.setSpeed(10);
}
void loop()
{
if (Serial.available())
{
int steps = Serial.parseInt();
if(steps > 0)
{
stepper.setStep(steps); //스텝모터 1번 회전수
stepper2.setStep(steps); //스텝모터 2번 회전수
stepper3.setStep(steps); //스텝모터 3번 회전수
Serial.print("steps : ");
Serial.println(steps);
}
}
stepper.moveStep();
stepper2.moveStep();
stepper3.moveStep();
}
에러코드나는 것도없고 이지드라이버 zip파일을 추가했는데 모터가 시리얼창에 값을 써도 아무런 반응이없습니다.. 모터드라이버는 a4988모델입니다.