본문 바로가기

카테고리 없음

6DOF Robotic Arm (6관절 로봇암) 1차 테스트

 

알리에서 약 3만원에 구입한 6DOF 관절 로봇암, 거기에 6개의 MG996R 서보 모터를 달았다.

소스 코드는 아래 유튜브 채널의 코드를 크게 참고했다.

https://youtu.be/rS2N8bSlS1w?si=sI7e5br-Qjrbh3tw 

 

저렴한 만큼 단점이 있는 로봇암이다. Waist와 Shoulder가 모터로 바로 체결되어 있는데 너무 불안정해서 자주 흔들거린다. 특히 Shoulder의 모터 MG996R이 너무 약해서 긴 팔을 잘 들어올리지 못한다. 이것은 모터가 약해서 그런 것이니 2배 정도 힘이 센 TD-8125MG 모터로 교체해주면 될 일이다. 다른 조금 큰 로봇암이 있는데 Shoulder 모터를 TD-8125MG로 교체해주니 대번에 긴 팔을 들어올렸다. Elbow와 Wrist Pitch 사이에 있는 은색봉을 빼버렸는데, 그 이유는 숄더 모터가 너무 약해서 무게를 줄여주기 위함이었다.

 

아두이노 아노를 여기에 쓰고 있는데 서보 모터를 제어하는 PWM 아키텍처에 약간 아쉬운 점이 있어 보여 별도의 서보 모터 드라이버를 사용하려고 테스트하고 있다. 빨리 로봇암 작동을 그럴 듯하게 만든 다음, 카메라를 붙여서 딥러닝 기능을 돌려보고 싶다.

"빨간 색 공을 집어서 저 컵에 넣어라." 라는 명령을 내리면 그것을 알아듣고 그대로 행동하려면 한 1년은 걸리려나?

 

https://www.youtube.com/shorts/fLJ1BoiMPQQ

 

 

#include <Servo.h>

/*
#define SERVO_WAIST       11
#define SERVO_SHOULDER    10
#define SERVO_ELBOW       9
#define SERVO_WRIST_ROLL  8
#define SERVO_WRIST_PITCH 7
#define SERVO_GRIP        6
*/

#define SERVO_WAIST       11
#define SERVO_SHOULDER    8
#define SERVO_ELBOW       7
#define SERVO_WRIST_ROLL  6
#define SERVO_WRIST_PITCH 5
#define SERVO_GRIP        3

#define JOY_WAIST     A5
#define JOY_SHOULDER  A4
#define JOY_ELBOW     A2
#define JOY_ROLL      A3
#define JOY_PITCH     A0
#define JOY_GRIP      A1

#define INIT_POS      90
#define INCREMENT     1

#define GRIP_CLOSE  152
#define GRIP_OPEN   76

#define N_DOF   6

// 위치값을 저장할 전역변수들(초기 위치)
int                  pos_waist = 90, pos_shoulder = 45, pos_elbow = 90, pos_pitch = 90,   pos_roll = 90,    pos_grip = 90;
int *positions[] = { &pos_waist,     &pos_shoulder,     &pos_elbow,     &pos_pitch,       &pos_roll,        &pos_grip };
int servo_pins[] = { SERVO_WAIST,    SERVO_SHOULDER,   SERVO_ELBOW,    SERVO_WRIST_PITCH, SERVO_WRIST_ROLL, SERVO_GRIP };
Servo                servo_waist,    servo_shoulder,   servo_elbow,    servo_pitch,       servo_roll,       servo_grip;
Servo *servos[] = { &servo_waist, &servo_shoulder, &servo_elbow,  &servo_pitch,      &servo_roll,      &servo_grip };
    
unsigned long t = 0;
// 시작점과 끝점까지 한번 왕복해보는 운동 
void tmove(Servo *servo, int start, int end) {
  for (int angle = start; angle <= end; angle++) {
    servo->write(angle);
    delay(20);
  }
  for (int angle = end; angle >= end/2; angle--) {
    servo->write(angle);
    delay(20);
  }
}

void setup() {
  Serial.begin(9600);

  for (int i = 0; i < N_DOF; i++) {
    servos[i]->attach(servo_pins[i]);
  }
  delay(100);
  
  for (int i = 0; i < N_DOF; i++) {
    servos[i]->write(*positions[i]);
    delay(1000);   
  }
}

void loop() {

  // 시간 간격을 두고 체크   
  if(millis() -t > 20) {
    t = millis();

    // 조이스틱 값을 가져와서 어디로 이동할지 결정한다.    
    if (analogRead(JOY_WAIST) < 300) {
      //Waist: counter-clockwise
      Serial.print("Waist: ");
      Serial.println(pos_waist);
      pos_waist += INCREMENT;
      if (pos_waist > 180) pos_waist = 180;
      servo_waist.write(pos_waist);
    } else if (analogRead(JOY_WAIST) > 800) {
      // waist: clockwise 
      Serial.print("Waist: ");
      Serial.println(pos_waist);
      pos_waist -= INCREMENT;
      if (pos_waist < 0) pos_waist = 0;
      servo_waist.write(pos_waist);
    } else if (analogRead(JOY_SHOULDER) > 800) {
      // shoulder: up
      Serial.print("shoulder: ");
      Serial.println(pos_shoulder);
      pos_shoulder -= INCREMENT;
      if (pos_shoulder < 0) pos_shoulder = 0;
      servo_shoulder.write(pos_shoulder);  
    } else if (analogRead(JOY_SHOULDER) < 300) {
      // shoulder: down
      Serial.print("shoulder: ");
      Serial.println(pos_shoulder);
      pos_shoulder += INCREMENT;
      if (pos_shoulder > 180) pos_shoulder = 180;
      servo_shoulder.write(pos_shoulder); 
    }
    
    if (analogRead(JOY_ELBOW) > 800) {
      // elbow: up
      Serial.print("elbow: ");
      Serial.println(pos_elbow);
      pos_elbow += INCREMENT;
      if (pos_elbow > 180) pos_elbow = 180;
      servo_elbow.write(pos_elbow); 
    } else if (analogRead(JOY_ELBOW) < 300) {
      // elbow: down
      Serial.print("elbow: ");
      Serial.println(pos_elbow);
      pos_elbow -= INCREMENT;
      if (pos_elbow < 0) pos_elbow = 0;
      servo_elbow.write(pos_elbow); 
    } else if (analogRead(JOY_PITCH) < 300) {
      // wrist: up
      Serial.print("wrist pitch: ");
      Serial.println(pos_pitch);
      pos_pitch -= INCREMENT;
      if (pos_pitch < 0) pos_pitch = 0;
      servo_pitch.write(pos_pitch);
    } else if (analogRead(JOY_PITCH) > 800) {
      // wrist: down
      Serial.print("wrist pitch: ");
      Serial.println(pos_pitch);
      pos_pitch += INCREMENT;
      if (pos_pitch > 180) pos_pitch = 180;
      servo_pitch.write(pos_pitch);
    }
     
    if (analogRead(JOY_ROLL) < 300) {
      // wrist roll: clockwise
      Serial.print("wrist roll: ");
      Serial.println(pos_roll);
      pos_roll -= INCREMENT;
      if (pos_roll < 0) pos_roll = 0;
      servo_roll.write(pos_roll);
    } else if (analogRead(JOY_ROLL) > 800) {
      // wrist roll: counter-clockwise
      Serial.print("wrist roll: ");
      Serial.println(pos_roll);
      pos_roll += INCREMENT;
      if (pos_roll > 180) pos_roll = 180;
      servo_roll.write(pos_roll);
    } else if (analogRead(JOY_GRIP) < 300) {
      // griper: open
      Serial.print("griper: ");
      Serial.println(pos_grip);
      pos_grip -= INCREMENT;
      if (pos_grip < GRIP_OPEN) pos_grip = GRIP_OPEN;
      servo_grip.write(pos_grip);
    } else if (analogRead(JOY_GRIP) > 800) {
      // griper: close
      Serial.print("griper: ");
      Serial.println(pos_grip);
      pos_grip += INCREMENT;
      if (pos_grip > GRIP_CLOSE) pos_grip = GRIP_CLOSE;
      servo_grip.write(pos_grip);
    }
  }

/*
  tmove(&servo_waist, 45, 135);
 // tmove(&servo_shoulder, 45, 135);
  delay(500);
  tmove(&servo_elbow, 0, 90);
  delay(500);
  tmove(&servo_roll, 0, 180);
  delay(500);
  tmove(&servo_pitch, 0, 180);
  delay(500);
  tmove(&servo_grip, 0, 180);
  delay(500);
*/

}