[아두이노] MPU-6050 + Stepper Motor 제어

IOT/아두이노|2019. 5. 15. 09:00

[아두이노] MPU-6050 + Stepper Motor 제어



MPU-6050 가속도/자이로 센서를 그냥 끝내기가 아쉬워서 간단히 실제 뭔가를 움직이게 하는 실험을 하면 좋을 것 같아서 오늘 Post 주제로 결정했습니다. 복잡한 제어는 아니고 간단히 원리만 이해하는 차원으로 하나의 패턴 동작만 수행하도록 제어하는 코딩을 실험 할 예정입니다. 설정은 MPU-6050 모듈의 기울기 각도 중 하나 X축의 각도값에 따라 Stepper Motor를 회전 시키는 조건입니다. 이 회전은 각도의 변화 크기에 따라 회전시키는 각의 결정하는 명령입니다. 즉, X축의 기울기 각도가 커지면 커질수로 회전의 각도 변화는 크게 회전시키고 X축의 기울기 각도가 작아지면 작아질수로 회전의 각도 변화는 작게 회전 시킵니다. 여기서, X축의 기울기가 반대로 기울려졌을 때는 역방향으로 회전 시키게 됩니다.

복잡한 설정을 하면 코딩량이 늘어나고 오히려 가독성이 떨어지고 의미 전달이 되지 않기 때문에 간단히 MPU-6050 모듈의 기울기에 따라서 Stepper Motor의 회전각을 제어하는 실험입니다. 이 원리를 꼭 기억해 두셨다가 나중에 이 원리를 회전의 속도로 변형해서 실험 해보세요. 그리고 드론에서의 x,y,z 회전각을 통해서 4개의 Motor의 회전 속도 제어를 통한 수평 조절에 대한 구상을 머리속에서 상상 코딩을 해보세요.

그러면, MPU-6050 모듈로 Stepper Motor를 제어하는 실험을 해보겠습니다.


1. MPU-6050 + Stepper Motor 회로도




2. 코딩



1) 기본 소스


[기본베이스 소스] - GetAngle (tockn님 소스 기반)

#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu6050(Wire);
void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu6050.begin();
  //mpu6050.calcGyroOffsets(true);
   mpu6050.setGyroOffsets(0.75, 0.05, 0.05);
}
void loop() {
  mpu6050.update();
  int val=mpu6050.getAngleX();
  Serial.println(angle); 
}

mpu6050.setGyroOffsets(0.75, 0.05, 0.05);

여기서, 위 인자값은 mpu6050.calcGyroOffsets(true) 함수로 사전에 계산된 값입니다.

지난시간 복습차원으로 다시 설명 드리면, 처음에는 setGyroOffsets()함수는 주석 처리하고 calcGyroOffsets()함수의 주석을 풀고 해당 찍히는 값을 출력해 주세요. 거기서 측정 된 값은 GyroOffsets값을 메모장에 다 적어놓고 setGyroOffsets() 함수의 인자값으로 넣으면 사전에 calcGyroOffsets()함수에서의 계산 시간을 줄일 수 있습니다.

아래 그림은 MPU6050_tockn 라이브러리의 GetAngle를 돌렸던 결과 이미지 입니다. 지난시간의 이미지인데 약간 위 코딩의 인자값하고 다른데, 처음 측정된 위치가 다르기 때문에 해당 값은 다를 수 밖에 없습니다.


지금 다시 측정을 하면 위치가 좀 달라지면 또 다른 값으로 바뀌겠지요. 원래는 계산하면 좋지만 빠르게 실험을 하기 위해서 한번 계산하고 그 값을 기준으로 세팅해놓고 실험하시면 빠르게 테스트 할 수 있습니다. 나중에 정교한 제어를 한다면 계산이 필요하겠지만 간단히, 원리 테스트에서는 처음 한번만 calcGyroOffsets()함수로 x,y,z GyroOffset 값을 구해 놓고 setGyroOffsets()함수에 인자로 넣고 두번째 부터는 빠르게 테스트 하는게 더 좋겠죠.

2) MPU-6050의 X축 회전각에 따른 Stepper Motor 회전


변화각 구해서 그 변화각 만큼 회전을 시켜 보자.

  int val=mpu6050.getAngleX();
  angle = angle + val-previousAngle;
  previousAngle=val;  
  stepper.step(angle);

val에서 우선 MPU-6050 모듈에서 X축의 회전각을 구하게 됩니다. 현재의 회전각은 val에 저장됩니다. 여기서, previousAngle 변수는 이전 getAngleX() 각을 저장되어 있습니다. 매 loop()함수가 돌 때마다 getAngleX() 각을 previousAngle 변수에 저장합니다.

그러면,

현재 X회전각 - 이전X회전각 = X회전각의 변화값

이렇게 얼마만큼의 변화가 발생했는지 그 차이 값을 구할 수 있게 됩니다.

이때,

angle = angle + val-previousAngle;

이렇게 하면 angle은 X회전각의 변화값을 누적하는 변수입니다. + 방향으로 변화각이 계속 커질 때 angle의 값은 그 변화각만큼 계속 증가하게 되고 만약에 - 방향으로 변화각이 계속 변할때 그 변화각만큼 angle의 값은 그 변화각 만큼 계속 감소하게 됩니다.

stepper.step(angle);

그리고, angle을 Stepper Motor의 회전각으로 설정하면 그 방향 각도만큼 정방향 회전이나 역방향 회전을 하게 됩니다.

참고로, 위 stepper.step(angle)에서 angle은 스템수입니다. 즉 180값이라고 하면 180도 회전하는게 아닙니다. 180 스템수만큼 정방향으로 회전 시키는 것일 뿐입니다. 180도 만큼의 회전을 주고 싶다면 1024스템수로 회전 시켜야 합니다.

stepper.step(map(angle,0,360,0,2048));

이렇게 되어야 정상적인 각도 회전이 되겠죠.

3) Stepper Motor


#include <Stepper.h>

const int STEPS = 2048;
Stepper stepper(STEPS, 8,10,9,11);

void setup() {
 stepper.setSpeed(12); 
}
void loop() {
 stepper.step(angle);
}

헤더파일, Stepper 객체변수 선언하고 setup()함수안에서 stepper.setSpeed() 로 스피드를 설정합니다. 그리고 나서 실제적으로 Stepper Motor를 stepper.step() 함수로 실제 회전을 시키게 됩니다. 이 코딩 부분은 위에 MPU-6050의 코딩과 합쳐야 겠죠.

4) 코딩 합치기


#include <Stepper.h>
#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu6050(Wire);

const int STEPS = 2048;
Stepper stepper(STEPS, 8,10,9,11);
int angle = 0;
int previousAngle=0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu6050.begin();
  //mpu6050.calcGyroOffsets(true);
  mpu6050.setGyroOffsets(0.75, 0.05, 0.05);
  stepper.setSpeed(12); 
}
void loop() {
  mpu6050.update();
 
  int val=mpu6050.getAngleX();
  angle = angle + val-previousAngle;
  previousAngle=val;  
     
  stepper.step(angle);
  Serial.println(angle); 
  delay(50);
}

삽입해야 할 위치에 코딩을 배치하면 됩니다. 완성된 소스는 좀 복잡해 보일 수 있지만 각 부품에 대해 의미만 제대로 이해하고 있다면 해당 위치에 삽입하는데 어려움이 없을 거라 생각 됩니다.

3. 실험 결과


아래 움짤 이미지는 회전각의 변화를 시리얼모니터로 출력한 결과물입니다. MPU-6050의 X축 회전각의 변화가 실제 Stepper Motor에 회전각의 값이 어떻게 변화되는지 잘 살펴보세요.



다음은 실제 MPU-6050모듈을 움직일 때 X축 회전각에 의해 Stepper Motor 회전되는 모습입니다.

마무리


간단히 MPU-6050 모듈에서 측정된 X축 회전각의 값을 통해서 Stepper Motor를 회전 시켰습니다. 여기서, 중요한 것은 MPU-6050의 값이 다른 부품의 움직임을 만들었다는 것이고 그것을 코딩으로 표현했다는데 의미가 있습니다.

오늘 실험은 Stepper Motor를 움직이게하는 첫발을 내딛는 코딩입니다. 여기서 부터 여러분들이 코딩에 살을 붙여가면서 상상력을 동원해서 뭔가를 하나씩 추가해보셨으면 합니다.

첫발은 내딛는데까지는 안내해드렸고 두번째 발은 어려분들이 내딛을 차례입니다.
한번 상상의 나래를 펼쳐 보세요.


댓글()