Robotics

[Ball Balancing] 5. 아두이노 서보모터 2개 제어 코드 (MG996R) - 매트랩

로보고니 2025. 1. 13. 14:44
반응형

서론

로봇을 만들고 개발하고 연구하기 위해서는 액추에이터를 제어할 수 있어야 한다. 그리고 그 액추에이터의 대표적인 것이 바로 이 서보모터이다. 서보모터는 우리가 원하는 각도만큼 움직이거나 특정 각도를 유지하게 할 수 있다. 그렇기에 로봇의 액추에이터로 많이 사용되고 있다. 이러한 서보모터를 제어하기 위해서, 오늘 간단한 코드를 살펴볼 것이다. 특히, 아두이노에 서보모터를 연결할 것이고, 매트랩을 통해서 그 서보모터를 제어할 것이다.


아두이노 서보모터 (MG996R)

서보모터를 제어하기 전에 우리가 사용할 MG996R 서보모터에 대해서 살펴볼 것이다.

MG996R 서보모터 기본 스펙

MG996R 기본 스펙

MG996R 서보모터의 기본스펙은 위와 같다. 크기와 무게, 힘 모두 우리가 흔히 서보모터를 생각했을 때 기대할 수 있는 값들이다. 물론 더 크고 무거운 서보모터의 경우 더 좋은 토크와 정확도를 제공해 주지만, 가격 역시 올라간다. MG996R은 적당한 가격에 적당한 스펙을 가지고 있다고 볼 수 있다.

서보모터 작동 원리

위 그림은 모터의 동작 원리라고 볼 수 있다. 우선 서보모터에 VCC와 GND 선이 연결되어 있다. 이것은 빨간색과 갈색 선으로 표시가 되는데, 서보모터에 전원을 공급해준다고 생각하면 된다. 큰 전압을 공급한다면 서보모터의 토크가 더 커지게 된다. 그렇다고 무한정 전압을 올릴 수 있는 것은 아니고, 당연히 적정 범위가 존재한다. 서보모터의 선이 각각 어떤 역할을 하는지에 대해서는 이전 글에 자세히 설명되어 있다.

 

PWM

모든 모터에는 PWM이 있다. PWM은 Pulse Width Modulation이다. 0과 1의 디지털 신호를 특정 주기로 모터에 전달하는 것이다. 이때, 그 주기가 짧고 긴 정도에 따라서 정보가 전달된다. 서보모터의 경우에는 PWM이 짧다면 0도, PWM이 길다면 180도와 같이 서보모터를 제어하게 된다.

여담으로, 서보모터 뿐만 아니라 DC모터도 PWM 방식으로 제어한다. PWM이 짧다면 DC모터의 속도가 느려지고, PWM이 길다면 DC모터의 속도가 빨라진다. 이러한 PWM 제어 방식은 기존의 전압 제어보다 효율적이기에 널리 사용되고 있다.


서보모터 제어 코드

서보모터를 제어하기 위해서 우선 아두이노 코드를 작성해야 한다. 아두이노에서 서보모터에게 특정 각도로 이동하도록 명령하면, 그 서보모터는 코드에 맞게 동작하게 된다. 하지만, 나는 최종적으로 매트랩을 가지고 서보모터를 제어할 것이다. 왜냐하면 매트랩에서 다른 센서들의 값을 시각화하는 등 활용도가 더 높기 때문이다. 따라서, 매트랩->아두이노->서보모터의 과정을 거쳐서 매트랩에서 서보모터를 제어할 것이다. 그리고 이를 위해서 중간 다리 역할을 하는 아두이노 코드가 필요하다.

아두이노 코드

#include <Servo.h>

Servo servo_x, servo_y;  // 서보모터 객체 생성

void setup() {
  servo_x.attach(3);  // X축 서보모터 핀
  servo_x.write(90);  // 초기 위치 설정
  servo_y.attach(5);  // Y축 서보모터 핀
  servo_y.write(90);  // 초기 위치 설정
  
  Serial.begin(9600);  // MATLAB과의 통신 시작
}

void loop() {
  // MATLAB으로부터 서보모터 각도 수신
  if (Serial.available() >= 4) {  // 각도 데이터 2바이트씩 2개
    int servoX_angle = Serial.parseInt();
    int servoY_angle = Serial.parseInt();

    // 수신된 각도로 서보모터 이동
    servo_x.write(servoX_angle);
    servo_y.write(servoY_angle);
  }

  delay(30);  // 데이터 송수신 간 간격
}

이 코드에서는 두 개의 서보모터를 제어하는 코드이다. 우선 서보모터의 객체를 생성해 준다. 그리고 각 서보모터가 어디에 연결되어 있는지를 정의해 준다. 그리고, 각 서보모터를 원하는 초기위치로 이동하도록 설정한다. 마지막으로, 매트랩과의 시리얼 통신을 위해서 9600으로 설정해 주면 셋업이 끝난다.

 

그다음부터는 매트랩으로부터 신호가 넘어왔을 때, 그 신호가 4바이트 이상이라면, 각 신호들을 각 서보모터 각도로 저장한다. 그리고 그 값을 서보모터에게 전달하면 된다.

 

위 코드는 아주 간단한 코드이다. 사실 실제로 우리가 아두이노로 서보모터를 제어할 때는 이렇게 간단한 코드로도 충분히 제어가 가능하다. 하지만 만약 조금 더 깊이 있게 서보모터를 제어하고 싶다면 말이 달라진다.

 

우선 위의 코드의 경우 아두이노에 전원이 연결될 때 setup 부분의 코드 때문에 서보모터가 초기에 튀는 현상이 있다. 이것은 아두이노가 서보모터를 지정할 때 갑자기 전원이 흘러가서 생기는 현상이다. 이를 막기 위해서 sleep() 코드를 넣어 시간을 벌어주는 등의 과정이 필요하다.

 

매트랩 코드

% 시리얼 포트 설정
serialPort = 'COM4'; % Arduino가 연결된 포트 (필요시 변경)
baudRate = 9600; % Arduino와 동일한 속도
serialObj = serialport(serialPort, baudRate);

% 버퍼 크기 조정
configureTerminator(serialObj, "LF"); % 줄바꿈 기준으로 데이터 수신
flush(serialObj); % 기존 데이터 제거

% 데이터 송신 루프
disp("Press Ctrl+C to stop");
try
    while true
        % 서보모터 각도를 Arduino로 송신
        servoX_angle = 90; % 예시 각도 값
        servoY_angle = 45; % 예시 각도 값
        write(serialObj, sprintf('%d,%d\n', servoX_angle, servoY_angle), "string");
    end
catch ME
    disp("Stopping communication...");
    delete(serialObj); % 시리얼 포트 정리
    rethrow(ME);
end

매트랩 코드에서 아두이노와 통신하는 부분만 가져왔다. 우선 시리얼 포트를 설정해야 한다. 이 포트는 아두이노와 내 컴퓨터가 어느 포트에 연결되어 있는지를 확인하면 된다. 그다음 앞서 아두이노 코드에 입력했던 9600 값을 입력해 주면 된다. 

 

그다음으로는 write()를 활용해서 각도 값을 전달해 주면 된다. 이때 각도의 정보가 string 자료형으로 넘어가는 것을 잘 확인해야 한다. 데이터의 크기가 크기 때문이다.

 

사실 이렇게 간단한 코드를 사용한다면, 굳이 매트랩을 사용할 이유가 없다. 하지만, 이 코드는 아주 기초 코드이고, 여기에 각도를 어떻게 계산할 것이고, 그 계산한 각도를 시각화하면서, 아두이노에서 센서 값을 받아와서 같이 시각화를 해준다면, 제어를 함에 있어 더욱 편리하고 정확해질 것이다. 그리고 이것이 매트랩을 사용하는 이유이다.


마무리

오늘은 매트랩과 아두이노를 활용해서 서보모터를 제어하는 방법에 대해서 알아보았다. 서보모터를 제어하는 것은 사실 아주 간단했다. 하지만 우리가 집중해야 할 것은 이 서보모터를 어떻게 활용할지이다. 서보모터를 동작시킬 수 있게 되었으니, 서보모터에게 어떤 값으로 동작하라고 각도를 정해주는 것이 우리의 역할이다. 그리고 그 방법에 대해서는 추후에 더 다룰 것이다.

반응형