지난강좌

.

아두이노 로봇팔 만들기를 위해 필요한 내용들을 하나씩 알아보는 시리즈 강좌입니다. 지난번에 손 만드는 법에 대해서 알아봤으니 이번엔 관절을 한 번 만들어 보겠습니다. 아래와 같이 2개 축으로 상하좌우 회전하는 관절을 만듭니다.

assembled

1. 준비물

사용되는 부품은 아래와 같습니다.

parts

  • 관절 프레임 세트
  • 서보모터 2개 (MG995)
  • 서보모터에 포함된 악세사리
  • M3 나사, 너트, 원형 베어링 1개
  • 서보모터 회전축에 끼울 디스크 2개 (위 사진에 없음)

부품 세트 구매처는 aliexpress 에서 robot arm joint로 검색하면 볼 수 있습니다. (아래 링크에 있는 제품 구성을 참고)

http://www.aliexpress.com/item/2-DOF-Long-Pan-And-Tilt-Robot-Joint-With-2-MG995-Servos-Sensor-Mount-Kit-For/1309107594.html

2. 조립순서

2.1. 하부관절 조립

먼저 좌우 회전할 아래부분을 만듭니다.

xy_axis

서보모터 회전축에 디스크를 끼웁니다. 이 상태에서 디스크를 좌우로 돌려보고 정확히 중앙(90′ ) 위치에서 아래와 같이 십자 형태를 이루도록 조절해줍니다. 만약 손대중으로 맞추기 힘들다면 지난 Claw 만들기 강좌에서 썼던 예제를 실행해서 서보모터가 90′ 위치에 놓이도록 만들어 주는 것이 좋습니다. (2개의 서보모터 전부)

xy_axis_2

아래와 같이 관절 하부 프레임에 구멍을 맞추고

xy_axis_3

3개의 나사로 서보모터, 디스크, 프레임이 고정되도록 해줍니다. 로봇팔의 하중을 서보모터 축으로 모두 감당해야 하므로 단단히 조여줍니다.

xy_axis_4

2.2. 상부관절 조립

아래와 같이 서보모터를 하부관절에 대고 나사와 너트로 조여줍니다. 서보모터 회전축에 디스크를 끼웁니다. 서보모터가 90′ 위치에 있을 때 X 모양이 되어야 합니다.

z_axis_2

서보모터 고정이 끝나면 상부 관절에 해당하는 부품들을 준비합니다. 아래 사진 참고.

z_axis_3

이제 상부관절 프레임을 서보모터 디스크와 맞추고 나사로 고정합니다. 서보모터와 디스크도 고정되도록 나사로 조여줍니다.

z_axis_4

이제 반대쪽으로 돌려보면 아래와 같이 될겁니다. 서보모터와 뒷면과 프레임 사이에 1cm 조금 안되는 간격이 있어야 합니다.

여기에 나사-너트-원형베어링-상부관절 프레임-너트 순서로 연결해 줍니다. 연결하면 아래 사진처럼 됩니다.

z_axis_6

이제 조립이 모두 끝났습니다. 서보모터를 돌려보면서 헐거운 곳은 없는지 동작 범위가 잘 맞는지 확인해봅니다.

2.3. 손 조립

관절만 테스트하기 밋밋하니까 미리 조립해 둔 손을 같이 연결해 줍니다. 총 3개의 서보모터로 간단한 팔처럼 동작시킬 수 있습니다.

z_axis_7

3. 테스트

지난 손 조립 과정에서 사용한 회로도에 2개의 서보모터를 더해줍니다. 새로 추가된 2개의 서보모터에 들어갈 신호선은 아두이노의 D5, D6 핀에 연결해주세요.

RobotArm_joint_circuit_2

이제 소스코드를 올려 동작을 확인할 차례입니다.

손 조립할 때 사용했던 소스코드를 대거 수정했습니다.

#include <Servo.h> 

Servo servo_joint1;
Servo servo_joint2;
Servo servo_claw;

int servo_joint1_pin = 5;
int servo_joint2_pin = 6;
int servo_claw_pin = 9;

int cur_angle_joint1 = 0; // current servo position in degrees
int cur_angle_joint2 = 0;
int cur_angle_claw = 0;

int current_servo_index;    // [1: joint1], [2: joint2], [3: claw]

int CENTER_SERVO = 90;  // center servo position
int joint1_min_angle     =  55;  // minimum servo position
int joint1_max_angle     =  125; // maximum servo position
int joint2_min_angle     =  55;  // minimum servo position
int joint2_max_angle     =  125; // maximum servo position
int claw_min_angle     =  55;  // minimum servo position
int claw_max_angle     =  125; // maximum servo position
int turnRate     =  5;  // servo turn rate increment (larger value, faster rate)  


void setup() {
  Serial.begin(9600);
  Serial.println("Robot Arm Control");
  Serial.println("By pressing 1, 2, 3 you can select servo");
  Serial.println("Press a or s to move, spacebar to center");
  Serial.println();
  
  servo_joint1.attach(servo_joint1_pin);
  servo_joint2.attach(servo_joint2_pin);
  servo_claw.attach(servo_claw_pin);
  
  cur_angle_joint1 = CENTER_SERVO;
  cur_angle_joint2 = CENTER_SERVO;
  cur_angle_claw = CENTER_SERVO;
  
  servo_joint1.write(cur_angle_joint1);
  servo_joint2.write(cur_angle_joint2);
  servo_claw.write(cur_angle_claw);
  
  changeServo(1);    // Set joint1 as current servo
}


void loop()
{
  if (Serial.available() > 0) {
    char command = Serial.read();

    // Servo control command: 'a'==97, 's'==115, ' '==32
    if (command == 97) { moveServo(-1); }  // move -1 step
    else if (command == 115) { moveServo(1); }  // move 1 step
    else if (command == 32) { moveServo(0); }  // 0 step means 'move to center position'
    // Select servo command: '1'==49, '2'==50, '3'==51
    else if (command == 49) { changeServo(1); }  // select joint1 servo
    else if (command == 50) { changeServo(2); }  // select joint2 servo
    else if (command == 51) { changeServo(3); }  // select claw servo
  }
}


void changeServo(int index) {
  if(index == 1) {
    current_servo_index = 1;
    Serial.println("# Joint1 servo selected");
  } else if(index == 2) {
    current_servo_index = 2;
    Serial.println("# Joint2 servo selected");
  } else {
    current_servo_index = 3;
    Serial.println("# Claw servo selected");
  }
}

// Move servo to target angle
void moveServo(int steps) {
  int c_angle = 0;
  int target_angle = 0;
  
  if(current_servo_index == 1) {
    c_angle = cur_angle_joint1;
    if(steps == 0)
      target_angle = CENTER_SERVO;
    else
      target_angle = cur_angle_joint1 + steps*turnRate;
    if(target_angle > joint1_max_angle) target_angle = joint1_max_angle;
    if(target_angle < joint1_min_angle) target_angle = joint1_min_angle;
  }
  else if(current_servo_index == 2) {
    c_angle = cur_angle_joint2;
    if(steps == 0)
      target_angle = CENTER_SERVO;
    else
      target_angle = cur_angle_joint2 + steps*turnRate;
    if(target_angle > joint2_max_angle) target_angle = joint2_max_angle;
    if(target_angle < joint2_min_angle) target_angle = joint2_min_angle;
  }
  else {
    c_angle = cur_angle_claw;
    if(steps == 0)
      target_angle = CENTER_SERVO;
    else
      target_angle = cur_angle_claw + steps*turnRate;
    if(target_angle > claw_max_angle) target_angle = claw_max_angle;
    if(target_angle < claw_min_angle) target_angle = claw_min_angle;
  }
  
  int step_angle = 1;
  if(target_angle < c_angle) { step_angle = -1; }
  
  // This code makes smooth movement
  for(int i = c_angle; i != target_angle; i+=step_angle) {
    //if((target_angle - i) < step_angle && (target_angle - i) > step_angle * -1)  // close to target position, break this loop
    //  break;
    if(current_servo_index == 1) {
      servo_joint1.write(i);
    }
    else if(current_servo_index == 2) {
      servo_joint2.write(i);
    }
    else {
      servo_claw.write(i);
    }
    delay(15);
  }
  
  if(current_servo_index == 1) {
    cur_angle_joint1 = target_angle;
  }
  else if(current_servo_index == 2) {
    cur_angle_joint2 = target_angle;
  }
  else {
    cur_angle_claw = target_angle;
  }
}

소스코드 업로드 후 Serial Monitor 창을 켭니다. 시리얼 모니터 창으로 아래 명령어를 내리면 3개의 서보모터를 조절할 수 있습니다.

  • 1 : 하부관절 서보모터를 선택 (좌우회전용)
  • 2 : 상부관절 서보모터를 선택 (상하회전용)
  • 3 : 손 서보모터를 선택 (열기, 닫기)
  • a : 서보모터의 회전축 위치를 5′ 줄임
  • s : 서보모터의 회전축 위치를 5′ 늘림

여러개의 명령어를 동시에 내릴수도 있습니다. [1aaaa] 이렇게 입력하고 전송하면 1번 서보모터의 회전각을 20′ 줄입니다.

손과 관절을 구성하는 방법을 배웠으니.. 이 내용을 응용하면 다양한 로봇팔을 만들 수 있습니다. 다음 강좌에서는 오픈소스로 프레임 디자인과 소스코드가 모두 제공되는 프로젝트를 실제 따라하면서 로봇팔을 만들어 보겠습니다.