[아두이노] Stepper Motor 제어

IOT/아두이노|2019. 4. 30. 09:00

[아두이노] Stepper Motor 제어



오늘은 Stepper Motor를 다뤄보려고 합니다. Motor편은 Servo Motor 이후 오랫만이죠. Servo Motor은 아두이노에서 바로 제어가 가능하기 때문에 따로 준비사항이 없었지만 Stepper Motor나 DC Motor는 모터 쉴드가 필요합니다. 아두이노에서 직접 Motor에 연결해서는 안됩니다. 직접 연결한다고 해서 작동을 안하는 것은 아니지만 아두이노에 문제가 생길 수 있기 때문에 직접 제어를 피해야 합니다. 그 이유는 Motor는 많은 전류를 필요하기 때문에 아두이노에 전류를 공급할 때 아두이노에서 일시적으로 전류가 불안정한 상태에 빠져 숏다운도 될 수 있습니다. 그리고 Motor의 역전류 현상에서 아두이노에 역전류가 흐르게 되면 아두이노는 치명적 손상을 입히게 됩니다. 그래서, Motor의 경우는 아두이노에 직접 Motor와 연결하지 않습니다. 그 사이에 모터 쉴드가 필요하고 모터 쉴드를 통해서 Motor를 제어하게 됩니다.

오늘 배우게 될 Stepper Motor는 참 재있는 부품입니다. Servo Motor와 유사하게 각도를 제어한 부품입니다. Servo Motor는 일반적으로 360도 회전이 안됩니다. 변형시키거나 특수 Motor의 경우는 회전이 가능하지만 일반적으로 일정 사이각 180도로 회전이 제한이 됩니다. 하지만 Stepper Motor는 360도 회전 뿐 아니라 각도를 정교하게 회전 시킬 수 있어 큰 장점을 지닌 Motor입니다.

이제 본격적으로 Stepper Motor에 대해서 살펴보도록 하겠습니다.


1. 5V 스템모터 + ULN2003 모터 드라이버



[ Fritzing 부품 그림 ]


Stepper Motor는 모터 내부의 고정자의 극 수에 따라서 1상, 2상, 3상, 4상, 5상, 6상 등 여러 종류로 나뉩니다.

그리고, 회로방식에서 Unipolar Steppers, Bipolar Steppers으로 나뉩니다. 아래 아두이노 공식 홈페이지의 튜토리얼에 자세히 나와 있으니깐 읽어주세요.



제 실험에서 Stepper Motor를 ULN 2003 모터 드라이브로 제어를 하게 됩니다.

Stepper Motor의 자세한 설명은 사실 포스트에 전체적인 내용을 쓰기에는 그림작업이 너무 힘들고 글로써 설명하자니 그림 없이 의미 전달하기에는 가독성이 너무 떨어지고 해서 괜찮은 글들을 소개하는 수준으로 Stepper Motor의 기본 개념 설명을 대신하고자 합니다. 사실 이태훈님의 블로그보다 더 쉽게 설명을 할 자신이 없어서 아래 참고할만한 사이트들을 링크 걸어놓습니다.


[출처]


참고로, pdf 파일로 만들어 놓은 세번째 링크 주소에서 유니플러 "1 상 여자 동작" 이 부분을 특히 잘 봐주시기 바랍니다. 이부분을 사용하여 Stepper Motor를 제어를 실험할 예정입니다. 1 step에 하나의 상만 전류가 공급되는 방식인데 이걸로 스템모터를 라이브러리 없이 모터를 제어할 수 있습니다.

1 step => A상(5V), B상(0V), C상(0V), D상(0)
2 step => A상(0V), B상(5V), C상(0V), D상(0)
3 step => A상(0V), B상(0V), C상(5V), D상(0)
4 step => A상(0V), B상(0V), C상(0V), D상(5V)

예) 1 step 일 경우 :

  digitalWrite(stepPin[0],HIGH);
  digitalWrite(stepPin[1],LOW);
  digitalWrite(stepPin[2],LOW);
  digitalWrite(stepPin[3],LOW);
  delay(10);

이렇게 계속 반복을 하고 각도를 회전하게 됩니다 위 step 순서로 전류가 공급되었을 때 이 방향을 정방향이라고 하면 역방향은 위 과정을 역순으로 진행하면 역방향이 되겠죠. 링크된 pdf 파일에 있는 곳에서 그림으로 보시면 대충 어떤식으로 진행되는지만 파악해 두세요. 이걸 코딩으로 표현한다면 어떻게 할지도 여러분들이 공곰히 생각해보세요.

힘든 분들은 이부분을 그냥 잊어주세요. 편하게 라이브러리를 처음에 사용하시는 것이 좋겠죠.

스템 모터 쉴드


위 그림을 보시면 대충 위치는 파악 하실 수 있겠죠. 참고로 Stepper Motor선 연결은 연결부분이 구별되어 있어서 개별핀의 위치는 신경 안쓰셔도 됩니다. 회로도를 그릴 때 만 연결 핀 위치를 명확하게 표현 해야하지만요. 참고로 아두이노에서 IN1에 전류가 공급되면 입력 핀에 신호가 온 것을 해당 LED에 불이 들어오게 하여 입력 신호 상태를 알 수 있는 모터 드라이브네요. 실제로 구매하시면 전원 담당 부분은 +, -가 표기가 제대로 안되어 있으니깐 +, -위치는 암기해 주세요. 나머지 선은 순서대로 연결만 하면 됩니다.

자세히 세부적인 핀 연결은 아래 그림을 잘 확인하시면 됩니다. 연결 선은 Color Name으로 표시 되어 있기 때문에 맞춰서 연결하시면 됩니다. 이 동작은 위에 링크 걸린 곳에 가시면 다른분이 자세한 설명이 있으니깐 깊게 공부하실 분들은 가셔서 필독하시면 됩니다.


제가 생각하기에는 처음에는 우선 스템 모터를 회전시키는 동작에만 초점을 두었으면 합니다. 뭔가 실제로 돌아가는 걸 보고 나서 스템 모터의 내부 원리에 대해서 이해하시는게 더 좋을 듯 싶네요. 나중에 이걸로 다양한 표현을 하다가 좀 더 깊게 공부하고 싶은 욕구가 생길 때 정석으로 공부하시고 지금은 그냥 모터를 회전시킬 수 있는 것에만 관심을 가지시면 됩니다. 스템 모터 라이브러리를 직접 여러분들이 만들 필요가 없으니깐요. 우리는 단지 이 부품을 가지고 회전만 시킬 수 있는 능력을 갖추시면 됩니다. 그리고 회전을 시켰을때 이것을 어디에 써먹을지에 좀 더 초점을 두었으면 합니다.

2. Stepper Motor 회로도


  • 준비물 : 5V 스템모터, ULN2003 모터드라이버, 아두이노우노
  • 내용 : 8,9,10,11핀을 순서대로 IN1, IN2, IN3, IN4에 연결하고 스템모터와 UNL2003 모터쉴드에 연결하시오.

여기서 전원부분은 아두이노에서 빼냈습니다. 참고로 전원은 아두이노보다는 따로 외부 전원을 사용하시는 것이 좋습니다. 귀찮아서 실제로도 아두이노에 연결해서 사용했지만 Stepper Motor를 여러개 연결 할 경우 아두이노에 문제가 생길 수도 있습니다.


3. 코딩


  • 내용 : stepper 라이브러리 없이 1상 여자 방식으로 회전 시켜보자.

함수

pinMode(사용핀,사용모드) : 사용핀을 INPUT/OUTPUT 모드를 설정
digitalWrite(사용핀,출력상태) : 사용핀을 HIGH(5V) or LOW(0V) 설정
delay(시간값) : 시간값만큼 대기




1상 여자 방식은 전류의 흐름을 아래 그래프와 같습니다.


이걸 표로 살펴보면,


위 표처럼 4개의 핀에 전류를 순서대로 공급하면 됩니다.

회로도에서 핀 8(A), 9(B), 10(C), 11(D)의 핀을 전류 공급 순서를 step 순서대로 순차적으로 공급하면 Stepper Motor가 회전을 하게 됩니다.

1 step => A상(5V), B상(0V), C상(0V), D상(0)
2 step => A상(0V), B상(5V), C상(0V), D상(0)
3 step => A상(0V), B상(0V), C상(5V), D상(0)
4 step => A상(0V), B상(0V), C상(0V), D상(5V)

1 Step : 1,0,0,0 으로 사용자 정의 함수를 하나 phasesate()함수를 하나 만들어 봅시다.

void phasesate(int a, int b, int c, int d, int delayval){
  digitalWrite(stepPin[0],a);
  digitalWrite(stepPin[1],b);
  digitalWrite(stepPin[2],c);
  digitalWrite(stepPin[3],d);
  delay(delayval);
}

이렇게 함수를 하나 정의해 놓으면 이 함수를 호출함으로서 아래와 같이 간단히 표현할 수 있습니다.

phasesate(1,0,0,0,10);

phasesate(1번핀,2번핀,3번핀,4번핀,속도)로 이렇게 표현이 됩니다.

패턴을 하나의 함수로 묶으면,

void stepmovea(){
  phasesate(1,0,0,0,10);
  phasesate(0,1,0,0,10);
  phasesate(0,0,1,0,10);
  phasesate(0,0,0,1,10);
}

이제 회전을 시켜볼까요.

void loop() {
  for(int i=0;i<500;i++){
    stepmovea();
  }
}

약 500정도에 360도 근처정도의 회전을 시키게 됩니다. 정확히 360도 회전을 하지 않습니다.

역회전을 한다면, stepmovea() 패턴 함수를 역순으로 진행하면 됩니다.

void stepmoveb(){
  phasesate(0,0,0,1,10);
  phasesate(0,0,1,0,10);
  phasesate(0,1,0,0,10);
  phasesate(1,0,0,0,10);
}

이렇게 하면 역순으로 회전이 되겠죠.

코드를 종합해 보면.

const int stepPin[4] = {8,9,10,11};

void setup() {

  for(int i=0;i<4;i++){
    pinMode(stepPin[i],OUTPUT);
  }
}

void loop() {
 
  for(int i=0;i<500;i++){
    stepmovea();
  }
  for(int i=0;i<500;i++){
    stepmoveb();
  }
}
void phasesate(int a, int b, int c, int d, int delayval){
  digitalWrite(stepPin[0],a);
  digitalWrite(stepPin[1],b);
  digitalWrite(stepPin[2],c);
  digitalWrite(stepPin[3],d);
  delay(delayval);
}

void stepmovea(){
  phasesate(1,0,0,0,10);
  phasesate(0,1,0,0,10);
  phasesate(0,0,1,0,10);
  phasesate(0,0,0,1,10);
}

void stepmoveb(){
  phasesate(0,0,0,1,10);
  phasesate(0,0,1,0,10);
  phasesate(0,1,0,0,10);
  phasesate(1,0,0,0,10);
}

4. 결과


회전 속도를 10으로 해서 그런지 좀 느리게 회전을 하네요. 그리고 500번의 루프를 돌았는데 약 360도 정방향으로 회전 했다가 역방향으로 회전하고 이렇게 반복적으로 회전을 수행한 결과입니다.

마무리


오늘은 Stepper 라이브러리 없이 회전을 직접 시도 했습니다. 회전시 문제점은 정교한 회전을 하기 위해서는 Stepper Motor의 사양과 delay(시간)값을 수학적으로 계산해야 합니다. 이런 복잡한 부분을 직접 코딩하는 것은 귀찮은 일이죠. Stepper Motor의 종류에 따라서 접근 방식과 계산이 달라지기 때문에 시간적으로 낭비입니다. 그렇기 때문에 우리는 편하게 Stepper 라이브러리를 사용해야 합니다. Stepper Motor로 뭘 만들지 상상해야지 Stepper Motor를 직접 라이브러리를 만드는데 시간을 낭비하면 안되겠죠.

Stepper Motor가 어떻게 회전을 했는지만 의미만 이해하시고 이론적인 부분은 위에 링크로 소개한 게시물들로 가셔서 이론을 배우세요.


댓글()