커뮤니티

  • 제 목 [로봇팔 제어 프로젝트 (완성)] 3개의 조이스틱을 이용한 6관절 로봇팔 제어
  • 작성자 이은* 조회 : 9,812 좋아요 : 2 댓글 : 0
  • 작성일 2019-11-18 오후 6:06:54
  • 첨부파일 robotarm_final.ino
  • 본 프로젝트는 가이드에 올라간 로봇팔 프로젝트 1, 2, 3, 4를 토대로 제작하였다. 

     

    준비물 : Arduino, 조이스틱, 서보모터 6개, 배터리, 로봇팔 프레임

    내용 : 3개의 조이스틱을 이용하여 서보모터 6개를 동작시킨다. 각각의 조이스틱 입력에 따라 서보모터의 속도 또한 조절 가능하다. 

     

    회로 연결은 다음과 같다.

     

    로봇팔의 프레임 무게를 견디기 위해 동작전압 6~7.2V인 서보모터를 사용하였다. 그렇기 때문에 별도의 전원이 필요하였고, 파워 서플라이를 이용하여 별도의 전원을 공급하였다. 꼭 파워 서플라이가 아니더라도 전원을 공급할 수 있는 배터리만 있어도 동작 가능하다. 또한 조이스틱의 경우 디지털 입력을 사용하지 않기 때문에 디지털 입출력핀인 SEL은 연결하지 않았다.

     

    조이스틱의 연결의 경우 다음과 같다.

    1번(왼쪽) 조이스틱의 경우

    x축 -> A0 (아날로그 입력핀)

    y축 -> A1 (아날로그 입력핀)

     

    2번(중앙) 조이스틱의 경우

    x축 -> A2 (아날로그 입력핀)

    y축 -> A3 (아날로그 입력핀)

     

    3번(오른쪽) 조이스틱의 경우

    x축 -> A4 (아날로그 입력핀)

    y축 -> A5 (아날로그 입력핀)

     

    서보모터의 경우 PWM 방식을 사용하기 때문에 입출력핀은 위에서부터 3, 5, 6, 9, 10, 11으로 연결하였다.

     

    코드는 다음과 같다.

    #include<Servo.h> //헤더파일 포함
    Servo servo1; //변수 선언
    Servo servo2;
    Servo servo3;
    Servo servo4;
    Servo servo5;
    Servo servo6;
    
    int motor1 = A0; // 모터1(회전축을 담당하는 모터)의 조종을 담당하는 아두이노 A0핀에 연결
    int motor2 = A1; // 모터2(아래 관절을 담당하는 모터)의 조종을 담당하는 아두이노 A1핀에 연결
    int motor3 = A3; // 모터3(로봇팔 중앙 관절 모터)의 조종을 담당하는 아두이노 A3핀에 연결
    int motor4 = A2; // 모터4(집게를 위아래로 조종하는 모터)의 조종을 담당하는 아두이노 A2핀에 연결
    int motor5 = A4; // 모터5(집게를 조종하는 모터)의 조종을 담당하는 아두이노 A4핀에 연결
    int motor6 = A5; // 모터6(집게를 좌우로 돌리는 모터)의 조종을 담당하는 아두이노 A5핀에 연결
    int angle1, angle2, angle3, angle4, angle5, angle6;
    void setup() {
      // put your setup code here, to run ongnce:
      servo1.attach(5); //회전축을 담당하는 모터 => 5번 지정
      servo1.write(90);  
      servo2.attach(3); //아래 관절을 담당하는 모터 => 3번 지정
      servo2.write(70);
      servo3.attach(6); //로봇팔 중앙 관절 모터 => 6번 지정
      servo3.write(70);
      servo4.attach(9); //집게를 위아래로 조종하는 관절을 담당하는 모터 => 9번 지정
      servo4.write(60);
      servo5.attach(11); //집게를 담당하는 모터 => 11번 지정
      servo5.write(90);
      servo6.attach(10); //집게를 좌우로 돌리는 관절을 담당하는 모터 => 10번 지정
      servo6.write(90);
    }
    
    void loop() {
        if ((analogRead(motor1) <= 450) && (analogRead(motor1) >= 0))
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 조이스틱 아날로그 입력값이 중간 값의 -50까지 범위를 제외시킴
      {
        angle1 = angle1 - ((analogRead(motor1) - 500)/50 ); 
        //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
        if (angle1 <= 0)
        {
            angle1 = 0;
        }
        servo1.write(angle1);
      }
      else if((analogRead(motor1) >= 600) && (analogRead(motor1) <= 1023))
      //사용자가 원치 않는 조이스틱의 입력을 막기 위해 조이스틱 아날로그 입력값이 중간 값의 +100까지 법위를 제외시킴
      {
        angle1 = angle1 + ((500 - analogRead(motor1))/50 );
        if (angle1 >= 180)
        {
            angle1 = 180;
        }
        servo1.write(angle1);
      }
      delay(15);
      if ((analogRead(motor2) <= 450) && (analogRead(motor2) >= 0))
      {   
        angle2 = angle2 + ((500 - analogRead(motor2))/150 );
        //중앙 관절을 담당하는 motor2의 경우 속도가 빠를 경우 물체를 집을 때 컨트롤 하기가 어렵기 때문에 다른 모터에 비해 속도를 낮춤
        if (angle2 >= 180)
        {
            angle2 = 180;
        }
        servo2.write(angle2);
      }
      else if((analogRead(motor2) >= 600) && (analogRead(motor2) <= 1023))
      {
        angle2 = angle2 - ((analogRead(motor2) - 500)/150 );
        if (angle2 <= 0)
        {
            angle2 = 0;
        }
        servo2.write(angle2);
      }
      delay(15);
    
      if ((analogRead(motor3) <= 450) && (analogRead(motor3) >= 0))
      {
        angle3 = angle3 + ((500 - analogRead(motor3))/150 );
        if (angle3 >= 170)
        {
            angle3 = 170;
        }
        servo3.write(angle3);
      }
      else if((analogRead(motor3) >= 600) && (analogRead(motor3) <= 1023))
      {
     
            angle3 = angle3 - ((analogRead(motor3) - 500)/150 );
        if (angle3 <= 0)
        {
            angle3 = 0;
        }
        servo3.write(angle3);
      }
      delay(15);
    
      
      if ((analogRead(motor4) <= 450) && (analogRead(motor4) >= 0))
      {
        angle4 = angle4 - ((analogRead(motor4) - 500)/50);
        if (angle4 <= 0)
        {
            angle4 = 0;
        }
        servo4.write(angle4);
      }
      else if((analogRead(motor4) >= 600) && (analogRead(motor4) <= 1023))
      {
            angle4 = angle4 + ((500 - analogRead(motor4))/50 );
        if (angle4 >= 170)
        {
            angle4 = 170; 
        }
        servo4.write(angle4);
      }
      delay(15);
      
      if ((analogRead(motor5) <= 450) && (analogRead(motor5) >= 0))
      {
        angle5 = angle5 - ((analogRead(motor5) - 500)/150);
        if (angle5 <= 0)
        {
            angle5 = 0;
        }
        servo5.write(angle5);
      }
      else if((analogRead(motor5) >= 600) && (analogRead(motor5) <= 1023))
      {
            angle5 = angle5 + ((500 - analogRead(motor5))/150 );
        if (angle5 >= 180)
        {
            angle5 = 180; 
        }
        servo5.write(angle5);
      }
     delay(15);
    
        if ((analogRead(motor6) <= 450) && (analogRead(motor6) >= 0))
      {
        angle6 = angle6 - ((analogRead(motor6) - 500)/50);
        if (angle6 <= 0)
        {
            angle6 = 0;
        }
        servo6.write(angle6);
      }
      else if((analogRead(motor6) >= 600) && (analogRead(motor6) <= 1023))
      {
            angle6 = angle6 + ((500 - analogRead(motor6))/50 );
        if (angle6 >= 170)
        {
            angle6 = 170; 
        }
        servo6.write(angle6);
      }
      delay(15);  
    }
      

     

    코딩의 경우 각각의 서보모터를 실험해보며 실험을 통해 나오는 속도 값을 계산하여 입력해 주는 것이 로봇팔 제어에 유리하다. 그렇기 때문에 프로젝트를 읽고 실습할 경우에 여러번의 실험을 통하여 각각 모터마다 최적의 속도 값을 부여해주는 것이 좋다.

     

    동작 영상은 다음과 같다.

     

    각각의 조이스틱은 2개의 서보모터 동작을 담당한다. 그렇기 때문에 6개의 서보모터를 3개의 조이스틱으로 제어하였다. 5관절보다 6관절을 사용한 로봇팔은 더욱 다양한 상황에서 물건을 집는데 유리하다. 이 프로젝트를 하며 센서에 대한 이해, 회로 연결, 코딩에 관한 전반적인 이해와 로봇팔의 무게에 따른 서보모터의 치우침 등 기계적인 요소도 경험할 수 있었다. 보는 것과 달리 직접 제작하면서 발생하는 예기치 못한 문제들을 해결하며 도전해보길 바란다.

  • #로봇 #아두이노 #모터제어