<2020년도 하반기>

광운대학교 BARAM이라는 동아리의 활동으로 진행한 프로젝트입니다.

깃허브 https://github.com/Myoung-Jisoo/Robot-Arm-using-OpenPose

 

1. 주제 선정 동기

 전자의수족에 관심이 있어 종종 관련자료들을 찾아보고는 했습니다. 외부상황을 인식해 장갑형태의 로봇손, 절단부위의 잔존근육에서 발생하는 미세한 생체신호(근전도 신호)를 이용하여 컨트롤을 하는 등의 기술 등을 볼 수 있었습니다. 하지만 모든 사람들의 팔 상하단, 손바닥크기 손가락 마디들의 길이가 같지 않듯이, 사람들의 움직임 역시 일반화할 수 없을 것이라는 의문이 들었습니다. 그리고 한 사람의 팔의 움직임을 가장 유사하게 구사할 수 있는 것은 신체 비율이 비슷한 반대쪽 팔이지 않을까 싶은 생각을 가지게 되었습니다. 이에 영상처리를 이용하여 왼팔의 움직임을 읽어 그 정보를 로봇팔(왼쪽)로 전송해 오른팔과 움직임과 비슷하게 구현해내자는 목표를 설정하게 되었습니다.

 

2.  목표

- 카메라는 한 대만 사용

Open Pose가 한 프레임을 받아오는 시간이 결코 짧지 않기 때문에, 한 대를 사용하는 것이 효율적이라고 생각했습니다.

 

- 주먹 쥐었다 펴기

손가락을 5개의 모터를 이용해 다 제어하기에는 하드웨어 무게가 감당이 되지 않을 것 같았습니다. 그래서 서보모터 하나만 사용하여 주먹을 쥐었다 펴는 동작을 구현하고자 했습니다.

 

- 팔꿈치 아래인 팔 하안부 동작 구현

팔꿈치 부분의 모터 2개를 연결해주어야 아래의 1. 팔을 돌리는 동작 / 2. 팔을 구부리는 동작 을 구현하고 싶었습니다.

팔 동작

하지만 팔을 돌리는 동작의 경우 z축을 회전시켜 똑같이 구현하려 하게 된다면, 카메라 두 대가 필요했습니다. 그래서 오른쪽의 그림과 같이 모터를 수직으로 연결하는 방식으로 프로젝트를 진행해보기로 결정하게 되었습니다.

 

3.  Hardware Architecture

하드웨어 구상

 손 부분의 3D 모델링은 Thingivers에서 가져왔고 그 외 부분 모델링은 INVENTOR를 사용했습니다.

 

사용모터 스펙 :

RDS5160 65x30x48 무게 : 162g
동작전압 : 6.0V ~ 8.4V
동작속도(6V) : 0.17sec/60°
동작속도(7.4V) : 0.15sec/60°
동작속도(8.4V) : 0.13sec/60°
토크(6V) : 58kg/cm
토크(7.4V) : 65kg/cm
토크(8.4V) : 70kg/cm
회전각도 : 360°

 

4.  System Architecture

System Architecture

 

 

Open Pose 환경구축

https://myoungziis-study.tistory.com/category/%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95/Open%20Pose

 

'환경구축/Open Pose' 카테고리의 글 목록

진로를 위해 공부하고 있는 내용들을 정리하는 블로그입니다.

myoungziis-study.tistory.com

 

'BARAM 동아리 프로젝트 > 동작을 따라하는 2-DOF Robot Arm' 카테고리의 다른 글

[Atmega128] 서보모터 제어  (0) 2021.08.05
[Hardware] 손 만들기  (0) 2021.08.05
OpenPose로 좌표값 받아오기  (2) 2021.08.05
완성작  (0) 2021.08.05

1. 서보모터

 서보모터를 제어하기 위해서는 20ms의 간격으로 1~2ms 폭의 펄스(사각파)를 생성 해야 하며, 펄스의 폭에 의해서 각도가 정해집니다. 구동 범위가 0~180°인 서보모터의 경우 아래와 같이 최소값을 1.0ms 최대값을 2.0ms로 잡고 백분위를 이용해 계산하여 제어를 할 수 있습니다.

 이번 프로젝트에서 사용하는 RDS5160의 경우에는 360° 구동이 가능한 모터이기 때문에 0°를 1.0ms, 그리고 360°를 2.0ms로 계산하면 됩니다.

 

2. 360도 서보모터 제어하기

 서보모터는 Timer 3의 Fast PWM mode를 이용해 주기를 맞춰주었습니다.

 

[main.c]

#include "mcu_init.h"

int cnt = 0;
int adc_array[8] = {0, };
int i = 0;
float servo1 = .080;
float servo2 = .075;
int duty1, duty2;
// duty 2.5~12.5

int num1 = 0;
int num2 = 0;
char a = 13;
int flag;
int number = 0;
int sign = 0;
// UART 통신

ISR(TIMER2_OVF_vect)
{
	cnt++;
	TCNT0 = 131;	// 4ms
	
	a = UART1_Receive();
	
	if(a == ',')
	{
		if(sign == 1) num1 = -num1;
		flag = 1; sign = 0;
	}
	else if(a == 13)
	{
		if(sign == 1) num2 = -num2;
		flag = 2; sign = 0;
	}
	
	if(flag == 0) Receive_num1();
	else if(flag == 1) Receive_num2();
	else if(flag == 2)
	{
		UART1_TransNum(num1);
		UART1_Transmit(',');
		UART1_TransNum(num2);
		UART1_Transmit(13);
		
		if((num1 >= 40) && (num1 <= 110)) servo1 = (double)num1 / 1000;
		if((num1 >= 35) && (num1 <= 105)) servo2 = (double)num2 / 1000;
		
		num1 = 0; num2 = 0; flag = 0;
	}
	
	MOTOR_Direction(servo1, servo2);
	
	if(cnt == 25) // 100ms
		cnt = 0;
}


void Receive_num1() // 첫번째 수를 입력받는다.
{
	num1 *= 10;
	number = a - 48;
	if(a == '-') sign = 1;
	if((number >= 0) && (number <= 9)) num1 += number;
}

void Receive_num2() // 두번째 수를 입력받는다.
{
	num2 *= 10;
	number = a - 48;
	if(a == '-') sign = 1;
	if((number >= 0) && (number <= 9)) num2 += number;
}

ISR(INT0_vect) // 인터럽트 0번 발생시 1번 서보모터 duty비 80%
{
	servo1 = .080;
}

ISR(INT1_vect) // 인터럽트 1번 발생시 2번 서보모터 duty비 75%
{
	servo2 = .075;
}

int main(void)
{
	UART1_INIT();
	Timer2_INIT();
	BUTTON_INIT();
	SERVO_MOTOR_INIT();
	ADC_INIT();
	
	sei();
	
	while(1);
}

터미널을 통해 두 모터의 duty값 전송

 서보모터가 UART 통신을 통해 수신받은 값으로 잘 움직이는 것을 확인할 수 있었습니다. 그러나, 속도는 조절할 수 없다는 단점 때문에 움직임이 뚝뚝 끊겨보이는 문제가 생겼습니다.

 이 문제는 다음과 같이 서보모터가 목표값에 도달할 때까지 제어주기마다 1씩 OCR값을 변화시켜주는 방법으로 해결할 수 있었습니다.

	if(abs(OCR3C - (1250 * servo1)) > 1) {
		if(OCR3C < (1250 * servo1)) OCR3C += 1;
		else if(OCR3C > (1250 * servo1)) OCR3C -= 1;
	}
	if(abs(OCR3B - (1250 * servo2)) > 1) {
		if(OCR3B < (1250 * servo2)) OCR3B += 1;
		else if(OCR3B > (1250 * servo2)) OCR3B -= 1;
	}

'BARAM 동아리 프로젝트 > 동작을 따라하는 2-DOF Robot Arm' 카테고리의 다른 글

프로젝트 기획  (0) 2021.08.05
[Hardware] 손 만들기  (0) 2021.08.05
OpenPose로 좌표값 받아오기  (2) 2021.08.05
완성작  (0) 2021.08.05

손은 Thingiverse에서 찾은 파일을 사용했습니다. (손 모델링 파일은 아래 링크에서 받았습니다.)

https://www.thingiverse.com/thing:242639

 

Flexy-Hand by Gyrobot

A proof of concept printable hand with "live hinge" flexible joints. Individually activated fingers using Filaflex filament as tendons. Printed in Makerbot Translucent Red and Filaflex hinges. Re-mix this idea into your own robotic or prosthetic project. F

www.thingiverse.com

 

 그래서 왼쪽 사진과 같이 출력해서 조립해주었는데... 안 움직입니다.

 애초에 조립이 제대로 되지도 않았고, 생각을 잘못했던 게 구조상 실을 당겼다 놓으면 다시 손이 펴져야 하는 구조인데, 탄성이 없으니 돌아올리가 없었습니다.

 

 그래서 무엇을 사용할 지 고민을 하다가 몰드용 액상 실리콘을 사용하게 되었습니다. 실리콘을 구매하는 것 자체가 처음인지라, 인터넷을 찾아보고 구매하고 직접 사용해보면서 경도를 맞춰나갔습니다.

실리콘을 마디에 넣어 사용한 모습

 위의 사진은 아래 경도 25의 실리콘을 사용하였을 때의 모습입니다. 움직임이 부드럽지만, 탄성이 떨어져 사용에는 부적합하다 판단했습니다.

 다음으로는 경도 40의 실리콘을 사용하였으나, 역시나 탄성이 부족한 느낌이 들어 사용하기에는 어렵다는 생각이 들었습니다.

 

 마지막으로 선택하게 된 게 퍼티형 실리콘이였습니다. 액상실리콘의 경화시간이 너무 긴데다가 시간이 얼마 남지 않아 내린 결론이었습니다. (경도 60정도의 실리콘을 사용하고 싶었으나 구매처를 찾지 못했습니다.)

 

 결과적으로는 실리콘 퍼티가 가장 적당하다고 생각은 들었으나, 신율이 작은 것인지, 너무 많이 늘어나면 부서지는 모습을 보여서 아쉬웠습니다. 판매처에 경도와 경화시간 외에 다른 정보들이 없어 고려하지 못했으나, 경도보다는 신율와 수축율을 중점적으로 고려했으면 더 좋았을거라는 아쉬움이 남았습니다.

  경도 인장강도 신율 수축율 경화시간
shore A MPa % %
몰드몬스터 25 25 >= 3.2 >= 500 >= 0.3 180
몰드몬스터 하드 40 >= 4 >= 450 >= 0.3 300
몰드용 실리콘퍼티 70       6
더보기

- 경도 : 규정 하중하에서 표면이 규정된 크기에 압침 침입에 저항하는 정도

- 인장강도 : 표준시편을 일정한 강도로 잡아당겼을 때, 절단되는 힘 또는 응력

- 신율(신장율) : 시험 표준편에 가해지는 인장력에 의해 늘어나는 길이로 초기 길이에 대한 백분율

* 아래 블로그 포스팅를 참고했습니다.

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=dy_chun&logNo=140023575560 

 

실리콘 고무의 특성

>> 실리콘고무의 개요 고무는 유용한 특성들을 독특하게 조합시켜 나타내는 복잡한 물질이다. 그 중 ...

blog.naver.com

 

 

'BARAM 동아리 프로젝트 > 동작을 따라하는 2-DOF Robot Arm' 카테고리의 다른 글

프로젝트 기획  (0) 2021.08.05
[Atmega128] 서보모터 제어  (0) 2021.08.05
OpenPose로 좌표값 받아오기  (2) 2021.08.05
완성작  (0) 2021.08.05

 OpenPose에서 제공해주는 예제 코드를 활용했고, visual studio로 Serial 통신을 하는 코드는 다른 분이 뚫어두신 코드를 활용했습니다.

 

전체 코드는 너무 길어 깃허드 링크로 걸어두었습니다.

https://github.com/Myoung-Jisoo/Robot-Arm-using-OpenPose/blob/main/Visual%20studio%202017/openpose.cpp

이미지의 Keypoints의 좌표를 띄운 모습

이미지의 각 좌표가 나타난 모습입니다.

 

그리고 OpenPose 기본 예제코드인 openpose demo의 실행결과는 다음과 같습니다.

OpenPose 실행결과

 영상에서 보시다시피 튀는 값들이 보입니다. 필터처리가 필요해 보입니다. 때문에 아래와 같이 미디언 필터를 이용해 처리했습니다. (연속으로 들어온 다섯개의 값들을 정렬 후에 가운데 값 사용)

			if (filter > 5) {
				filter = 0;
				// 크기순 정렬
				sort(shoulderX.begin(), shoulderX.end());
				sort(shoulderY.begin(), shoulderY.end());
				sort(elbowX.begin(), elbowX.end());
				sort(elbowY.begin(), elbowY.end());
				sort(wristX.begin(), wristX.end());
				sort(wristY.begin(), wristY.end());
				// 중간값 담기
				if ((abs(shoulder.x - shoulderX.at(2)) < 10) && (abs(shoulder.y - shoulderY.at(2)) < 10)) shoulder_count++;
				if (shoulder_count > 4) {
					f_shoulder.x = shoulder.x;
					f_shoulder.y = shoulder.y;
				}
				else {
					shoulder.x = shoulderX.at(2);
					shoulder.y = shoulderY.at(2);
					//shoulder_count = 0;
				}

				if ((abs(elbow.x - elbowX.at(2)) < 20) && (abs(elbow.y - elbowY.at(2)) < 20)) elbow_count++;
				if (elbow_count > 4) {
					f_elbow.x = elbow.x;
					f_elbow.y = elbow.y;
				}
				else {
					elbow.x = elbowX.at(2);
					elbow.y = elbowY.at(2);
				}

				wrist.x = wristX.at(2);
				wrist.y = wristY.at(2);
				// vector 비우기
				shoulderX.clear();
				shoulderY.clear();
				elbowX.clear();
				elbowY.clear();
				wristX.clear();
				wristY.clear();
			}

 

그리고 위에서 얻은 데이터들을 토대로 아래와 같이 각 서보모터의 값들을 구한 후에 Uart통신을 통해 atmega128로 전송해주었습니다.

void getAngleAndSend() {
	angle1 = acos(downLength / downLength_Max);

	
	//double dz = downLength * tan(angle1);
	//double a = sqrt(pow(dx2, 2) + pow(dz, 2));

	angle2 = asin((f_elbow.x - wrist.x) / downLength_Max);

	if ((elbow.y - wrist.y) > 0) angle1 = 3.14 - angle1; // 1.5708은 90도

	std::string angle = std::to_string((int)(angle1 * (180.0 / 3.14))) + "," + std::to_string((int)(angle2 * (180.0 / 3.14)));

	op::opLog("\n" + angle);

	angle = "s" + angle + "e";

	char Angle[100];
	strcpy(Angle, angle.c_str());

	if (uart.isOpen()) {
		op::opLog("connected!");
		uart.Write(Angle, angle.length());
	}
	else op::opLog("not connected :(");
}

'BARAM 동아리 프로젝트 > 동작을 따라하는 2-DOF Robot Arm' 카테고리의 다른 글

프로젝트 기획  (0) 2021.08.05
[Atmega128] 서보모터 제어  (0) 2021.08.05
[Hardware] 손 만들기  (0) 2021.08.05
완성작  (0) 2021.08.05

1. 최종 하드웨어

완성한 모습

 

2. 동작영상

동작 영상

+ Recent posts