이 튜토리얼에서는 서보 모터로 아두이노 짐벌(Gimbal) 또는 자율 안정화 플랫폼을 만드는 방법을 배웁니다. 이 튜토리얼은 이전 MPU6050 튜토리얼의 연장선입니다.
다음 영상을 시청하거나 아래 작성된 튜토리얼을 읽어보세요.
개요
3D 모델링 소프트웨어로 짐벌을 설계했습니다. 3축 제어용 MG996R 서보 모터 3개와 MPU6050 센서, 아두이노, 배터리를 올릴 베이스로 구성됩니다.
Thangs에서 3D 모델을 찾아 다운로드하거나 브라우저에서 탐색할 수 있습니다.
STL 파일:
Creality CR-10 3D 프린터로 모든 부품을 프린팅했는데 완벽하게 나왔습니다.
조립
짐벌 조립은 꽤 간단했습니다. 요(Yaw) 서보부터 설치했습니다. M3 볼트와 너트로 베이스에 고정했습니다.
같은 방식으로 롤(Roll) 서보를 고정했습니다. 파트들이 MG996R 서보에 딱 맞게 설계됐습니다.
파트 간 연결에는 서보 액세서리로 제공되는 원형 혼(round horn)을 사용했습니다.
먼저 원형 혼을 볼트 두 개로 베이스에 고정하고, 이전 서보에 다른 볼트로 연결합니다.
같은 과정으로 피치(Pitch) 서보와 상단 플랫폼까지 조립했습니다.
서보 선들을 홀더 구멍으로 통과시켜 정리했습니다. MPU6050 센서를 베이스에 볼트와 너트로 고정했습니다.
전원용으로 리튬이온 배터리 2개를 배터리 홀더에 넣고 베이스에 볼트/너트 2개로 고정했습니다.
리튬이온 배터리 2개는 약 7.4V를 출력하지만 아두이노와 서보에는 5V가 필요합니다.
그래서 7.4V를 5V로 낮춰주는 벅 컨버터(강압 컨버터)를 사용했습니다.
아두이노 짐벌 회로도
남은 건 모든 걸 연결하는 일입니다. 프로젝트 회로도와 연결 방법입니다.
필요한 부품:
- MPU6050 IMU
- MG996R 서보
- 벅 컨버터
- 아두이노 보드
- 브레드보드와 점퍼 와이어
전자 부품과 선들을 베이스 안에 넣고 하단 커버로 덮었습니다.
자체 균형 플랫폼 또는 아두이노 짐벌이 완성됐으며 예상대로 잘 작동합니다. 이제 프로그램을 살펴보겠습니다.
아두이노 코드
이 예제의 아두이노 코드는 Jeff Rowberg의 i2cdevlib 라이브러리에 있는 MPU6050_DMP6 예제를 수정한 것입니다.
코드 다운로드:
코드 설명: yaw, pitch, roll 가독성 출력값을 사용합니다.
// Yaw, Pitch, Roll 값 가져오기
#ifdef OUTPUT_READABLE_YAWPITCHROLL
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
// Yaw, Pitch, Roll 값 - 라디안을 도(degree)로 변환
ypr[0] = ypr[0] * 180 / M_PI;
ypr[1] = ypr[1] * 180 / M_PI;
ypr[2] = ypr[2] * 180 / M_PI;
// 300회 읽기 건너뛰기 (자체 캘리브레이션 과정)
if (j <= 300) {
correct = ypr[0]; // Yaw는 초기에 랜덤 값, 300회 읽기 후 마지막 값 저장
j++;
}
// 300회 읽기 후
else {
ypr[0] = ypr[0] - correct; // Yaw를 0도로 설정 - 현재 값에서 마지막 랜덤 Yaw 값 빼기
// MPU6050 센서 값 -90~90도를 서보 제어용 0~180도로 매핑
int servo0Value = map(ypr[0], -90, 90, 0, 180);
int servo1Value = map(ypr[1], -90, 90, 0, 180);
int servo2Value = map(ypr[2], -90, 90, 180, 0); // 피치는 반전 필요
// MPU6050 방향에 따라 서보 제어
servo0.write(servo0Value);
servo1.write(servo1Value);
servo2.write(servo2Value);
}
#endif
값을 얻으면 먼저 라디안에서 도로 변환합니다.
// Yaw, Pitch, Roll 값 - 라디안을 도로 변환
ypr[0] = ypr[0] * 180 / M_PI;
ypr[1] = ypr[1] * 180 / M_PI;
ypr[2] = ypr[2] * 180 / M_PI;
센서가 아직 자체 캘리브레이션 중이므로 300회 읽기 동안 대기합니다. 또한 Yaw 값은 초기에 Pitch/Roll처럼 0이 아니라 항상 어떤 랜덤 값으로 시작하므로 이 값을 캡처합니다.
// 300회 읽기 건너뛰기 (자체 캘리브레이션 과정)
if (j <= 300) {
correct = ypr[0]; // Yaw는 랜덤 값으로 시작, 300회 읽기 후 마지막 값 캡처
j++;
}
300회 읽기 후, 먼저 캡처한 랜덤 값을 빼서 Yaw를 0도로 맞춥니다. 그런 다음 Yaw, Pitch, Roll 값을 -90~+90도에서 서보 제어용 0~180도로 매핑합니다.
// 300회 읽기 후
else {
ypr[0] = ypr[0] - correct; // Yaw를 0도로 설정
// MPU6050 센서 값 -90~90도를 서보 제어용 0~180도로 매핑
int servo0Value = map(ypr[0], -90, 90, 0, 180);
int servo1Value = map(ypr[1], -90, 90, 0, 180);
int servo2Value = map(ypr[2], -90, 90, 180, 0);
// MPU6050 방향에 따라 서보 제어
servo0.write(servo0Value);
servo1.write(servo1Value);
servo2.write(servo2Value);
}
마지막으로 write() 함수로 이 값들을 서보 제어 신호로 보냅니다. 원한다면 Yaw 서보를 비활성화해 X, Y축만 안정화하는 카메라 짐벌로 쓸 수도 있습니다.
주의: 이 프로젝트는 좋은 카메라 짐벌과는 거리가 멉니다. 움직임이 부드럽지 않은데, 이 서보들은 그런 용도로 만들어진 게 아니기 때문입니다. 진짜 카메라 짐벌은 부드러운 움직임을 위해 특수 BLDC 모터를 사용합니다. 이 프로젝트는 교육용으로만 고려하세요.
이 튜토리얼은 여기까지입니다. 즐겁고 유익했길 바랍니다. 질문은 댓글로 남겨주시고 아두이노 프로젝트 모음도 확인해보세요.