April 26, 2024

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[14호] 2011 캡스톤 디자인 공모전 우수상- 보행보조기구 2부

1부 보러 가기

 

4. 제어부

4.1 작동 프로세스
4.1.1 작동 프로세스 개요

2011capstonef02

RF MODEM A3007B는 UART 통신 방식을 지원하므로 목발의 MCU와 UART 방식의 통신을 한다. 목발의 MCU는 목발 밑에 부착된 스위치가 ON이 되거나 일어서기/앉기 스위치가 ON이 될 경우에 RF Modem이 해당 모드에 맞는 신호를 보내도록 한다. RF Modem 간의 통신을 통해 메인 MCU가 신호를 받아들이면 RS485 통신 방식을 사용하여 2개의 모터컨트롤러가 작동될 수 있도록 한다. RS485는 1:n의 통신방식을 지원하기 때문에 2개의 통신포트를 가지고도 여러 개의 통신을 할 수 있다. 메인 MCU의 UART0 포트는 RF Modem의 수신부와, UART1의 포트는 2개의 컨트롤러와 각각 연결된다.

2011capstonef03

기존목발에 스위치를 부착하여 양 목발이 순차적으로 ON 상태가 되면 모터가 작동하여 걸음이 가능하도록 설계한다. 스위치와 모터의 연결은 RF Modem을 사용한 무선통신으로, 보행에 방해가 되지 않게 한다.

4.1.2 걷기

양 목발이 동시에 땅을 짚을 경우, 4점 보행법으로 작동한다. 고관절부의 엉치뼈에 장착된 모터가 1차로 구동이 되어 허벅지 부분을 들어 올려주며, 순차적으로 무릎 부분의 모터가 구동을 시작하여 무릎을 일정한 각도까지 굽혀준다. 허벅지 부분의 모터 구동이 잠시 멈추면 무릎 부분의 모터가 작동하여 보행이 가능한 일정각도까지 무릎을 펴줌과 동시에 장애인은 목발에 하중을 싣고 몸을 앞으로 숙여 발바닥이 땅에 닿도록 한다. 한쪽 발바닥이 발바닥에 고정되고 목발에 일정한 압력이 다시 가해지면 반대쪽 발이 같은 원리로 구동을 시작한다.

4.1.3 앉기/일어나기

의자에 앉거나 일어나는 경우는 목발에 부착된 별도의 스위치를 사용하여 구동하도록 한다. 스위치를 사용하여 앉는 경우엔 무릎부의 모터가 중심이 되기 때문에 걸을 때에 비해 큰 각도로 회전하며, 엉치뼈 부분의 모터가 추가적으로 회전하여 허리를 숙이게 함으로써 의자에 앉는 것이 가능하게끔 한다.

일어나는 경우, 모터가 앉는 경우와 반대로 회전하여 일어서는 것을 도와준다. 이 때, 사용자는 최대한 목발에 의지해 몸의 무게중심을 앞으로 쏠리게 하여 무릎부분 관절에 가해지는 힘을 분산시키도록 한다.

4.2 회로도

4.2.1 전원부

2011capstonef54

4.2.2 스위치 및 LED

스위치 및 LED회로

스위치 및 LED회로

외부 스위치 회로

외부 스위치 회로

4.2.3 RF Modem 회로

RF 송수신 회로

RF 송수신 회로

4.3 작동 소스

사용 프로그램 | ATMEL사에서 제공하는 AVR Studio프로그램을 사용.
4.3.1 RF Modem(송신부)

RF Modem 송신부(앉기/일어나기) 소스보기

#include <avr/io.h>
#include <util/delay.h>

// RF로 송신 할 값을 캐릭터 함수로 설정
//HEAD(0xAA,0xBB, OP code(주파수 311/송신 12 + 송신할 문자)
char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //주파수 세팅
char RF_TX0_STAND[6]={0xAA,0xBB,1,2,1,1}; //일어서기 모드
char RF_TX0_SIT[6]={0xAA,0xBB,1,2,7,7}; //앉기 모드
char RF_TX0_WALK[6]={0xAA,0xBB,1,2,5,5}; //걷기 모드
void TX0_CH(char ch){ while(!(UCSR0A&0×20)); UDR0=ch; }
int main(void) //메인 함수 구문
{
char i; //캐릭터함수 i 설정
DDRA=0xFF; DDRF=0×00; DDRE=2;
//PORTA 출력, PORTF 출력 TXD0 PORTE.1
UCSR0A=0; UCSR0B=0×18; UCSR0C=6; UBRR0H=0;
UBRR0L=103;
// UART0 통신관련 레지스터 설정 , BAUD RATE 9600bps
_delay_ms(100);
// RF 주파수 세팅
for(i=0;i<5;i++)TX0_CH(RF_FREQ_SET[i]);
_delay_ms(1000);
while(1)
{
//delay();
if((PINF&0×04)==0×00) // PORTF에 연결된 2번 스위치를 누르면
{
for(i=0;i<6;i++)TX0_CH(RF_TX0_STAND[i]); //STAND값 송신
_delay_ms(1000);
}
if((PINF&0×10)==0×00) // PORTF에 연결된 4번 스위치를 누르면
{
for(i=0;i<6;i++)TX0_CH(RF_TX0_SIT[i]); //SIT 값 송신
_delay_ms(1000);
}
if((PINF&0×01)!=0×00) // PORTF에 연결된 1번 스위치를 누르면
{
for(i=0;i<6;i++)TX0_CH(RF_TX0_WALK[i]); //WALK 값 송신(left_on)
_delay_ms(1000); }
while(PINF&1); // 누르고 있는 동안은 한 번만 함수 호출
}
}

RF Modem 송신부 소스보기

#include <avr/io.h>
#include <util/delay.h>

// RF로 송신 할 값을 캐릭터 함수로 설정
//HEAD(0xAA,0xBB, OP code + (주파수 311/송신 12 + 송신할 문자)
char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //주파수 세팅
char RF_TX0_WALK[6]={0xAA,0xBB,1,2,4,4}; //걷기 모드
void TX0_CH(char ch){ while(!(UCSR0A&0×20)); UDR0=ch; }
int main(void) //메인 함수 구문
{
char i; //캐릭터함수 i 설정
DDRA=0xFF; DDRF=0×00; DDRE=2;
//PORTA 출력, PORTF 출력 TXD0 PORTE.1
UCSR0A=0; UCSR0B=0×18; UCSR0C=6; UBRR0H=0; UBRR0L=103;
// UART0 레지스터 설정 , BAUD RATE 9600bps
_delay_ms(100); //딜레이 1초
for(i=0;i<5;i++)TX0_CH(RF_FREQ_SET[i]);
// i의 숫자가 0에서 4까지 커지는 동안 RF는 주파수 세팅
_delay_ms(1000);
while(1)
{

if((PINF&0×01)!=0×00) // PORTF에 연결된 1번 스위치를 누르면
{
for(i=0;i<6;i++)TX0_CH(RF_TX0_WALK[i]); //WALK 값 송신(right_on)
_delay_ms(1000); }
while(PINF&1); // 누르고 있는 동안은 한 번만 함수 호출
}
}

4.3.2 RF modem(수신부) :main MCU

RF Modem 수신부 소스보기

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
typedef unsigned char BYTE;
#define BAUD_HIGH 00 //baudrate가 high일때 설정
#define BAUD_LOW_M 8 // 모터의 bps는 115200으로 설정
#define BAUD_LOW_RF 103 // RF모뎀의 bps는 9600으로 설정
#define ALL_FLAG_CLEAR 0×00
#define USATR_RECEIVER_ENABLE 0×10
#define USATR_TRANSMITTER_ENABLE 0×08
#define USATR_CHARACTER_SIZE 0×06
//TXD, RXD 설정
#define RXC_FLAG 0×80
#define TXC_FLAG 0×20
#define COM1 1
//
static int uart_putchar(char c, FILE *stream);
static FILE mystdout=FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
volatile BYTE movement;
volatile char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //RF 주파수 세팅
volatile int MODE, right_on=0, left_on=0, standing=0, sitting=0;
//
void TX0_CH(char ch){ while(!(UCSR0A&0×20)); UDR0=ch; } // UART0 송신 함수
//
ISR(USART0_RX_vect){ // Interrupt Service Routine
char ch;
ch=UDR0; //UDR0의 값을 ch에 저장
if(ch==7)sitting=1; // 만약 ch가 7이면 sitting ==1
else if(ch==1)standing=1; // ch가 1이면 standing ==1
else if(ch==4)right_on=1; // ch가 4이면 right_on ==1
else if(ch==5)left_on=1; //ch가 5이면 left_on ==1
}
//
void initialize_serial(void){ // initialize_serial 함수 정의
UBRR1H=BAUD_HIGH; UBRR1L=BAUD_LOW_M; // UDR1 레지스터 설정
UCSR1A=ALL_FLAG_CLEAR; //
UCSR1B=USATR_RECEIVER_ENABLE | USATR_TRANSMITTER_ENABLE;
UCSR1C=USATR_CHARACTER_SIZE;
}
//
static int uart_putchar(char c, FILE *stream){
if(c==’\n’) uart_putchar(‘\r’, stream);
if(MODE==COM1){ loop_until_bit_is_set(UCSR1A, UDRE); UDR1=c; }
return 0;
}
//
void TX1_CH(char ch){ while(!(UCSR1A&0×20)); UDR1=ch; }
// UART1의 송신함수
//
void setting(){ // 모터 세팅 함수
unsigned volatile char i;
BYTE SendBuff[256]={0};
PORTA=0xff;
MODE=COM1;
// 컨트롤러 세팅값 (SS2000,2000, Ss200,200, SM0202, PE0001 .. ) 전송
// 모터 컨트롤러에 각각 채널 1,2로 값을 전송함
// 0×01 :1번 컨트롤러ID 0×02 : 2번 컨트롤러 ID
memset(SendBuff,0,sizeof(BYTE)*256); //초기화
SendBuff[0]=0×01; sprintf(&SendBuff[1],”SS2000,2000!”); _delay_ms(1); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”Ss200,200!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”SM0202!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PE0001!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”SS2000,2000!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”Ss200,200!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”SM0202!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PE0002!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1000);

_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
}
//
void standing_M(){ // 모터의 일어나기 동작을 정의
unsigned volatile char i;
BYTE SendBuff[256]={0};
MODE=COM1;
//위치 제어 PA 명령어를 사용하여 위치값 전송
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5200000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA4800000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1000);

_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(10000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5200000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA4800000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);
memset(SendBuff,0,sizeof(BYTE)*256);

_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(1000000);
_delay_ms(100000);
_delay_ms(10000);
_delay_ms(100000);
_delay_ms(10000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);

SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA4800000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA5200000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(100);

}
//
void walking_M(){ // 모터의 걷기 동작을 정의
unsigned volatile char i; // 캐릭터 함수 i 설정
BYTE SendBuff[256]={0};
PORTA=0×00; // PORTA의 LED가 꺼짐
MODE=COM1;
_delay_ms(100);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5200000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(1000);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5200000,5100000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5200000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA4800000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(100);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA4700000,4500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(100);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA4700000,5000000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA5200000,4500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);

_delay_ms(10);
}

//
void sit_M(){ // 앉기 동작 정의
unsigned volatile char i;
BYTE SendBuff[256]={0};
PORTA=0×00;
MODE=COM1;
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA4800000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA5200000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);

_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(100000);
_delay_ms(10000);
_delay_ms(10000);
_delay_ms(10000);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA4800000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA5200000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);

_delay_ms(100000); _delay_ms(100000); _delay_ms(100000); _delay_ms(100000);
_delay_ms(100000); delay_ms(100000); _delay_ms(100000); _delay_ms(10000);
_delay_ms(100000); _delay_ms(100000); _delay_ms(100000); _delay_ms(1000);
_delay_ms(1000); _delay_ms(10000);

memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×01; sprintf(&SendBuff[1],”PA5000000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);
memset(SendBuff,0,sizeof(BYTE)*256);
SendBuff[0]=0×02; sprintf(&SendBuff[1],”PA5000000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);
}
//
int main(void){
char i;
left_on=right_on=sitting=standing=0;
DDRA=0xff;
DDRE=2;
DDRG=0b11000000;
UCSR0A=0; UCSR0B=0×98; UCSR0C=6; UBRR0H=0; UBRR0L=103;
//UART0 레지스터 설정, BAUD RATE 9600bps
PORTA=0xff;
initialize_serial(); //초기화
_delay_ms(1);
stdout=&mystdout;
_delay_ms(1000);
for(i=0;i<5;i++)TX0_CH(RF_FREQ_SET[i]); //RF 주파수 세팅
_delay_ms(1000);
sei(); //인터럽트 허용
while(standing==0); //standing==1이 될 때 까지 대기
while(left_on==0); //right_on 과 left_on 둘다 1이 될 때까지 대기
PORTA=0×00;
setting(); // 모터 세팅 호출
_delay_ms(10000);
_delay_ms(10000);
standing_M(); //딜레이 후 일어서는 동작 호출
while(1){
//left_on과 right_on이 둘다 1이라면 걷기 동작 호출
left_on==0;
if((left_on&right_on)==1){
walking_M(); left_on=0; right_on=0; } //함수 호출 후 left_on=0으로 초기화
//sitting==1이 되면 앉기 동작 호출
if(sitting==1){
sit_M(); sitting=0;
}
}
return 0;
}

5. 제작 과정

5.1 부품 사진

5.1.1 설계부

135 브라켓

135 브라켓

허벅지 관절부와 무릎 관절부 발목을 잇고, 지탱해주면서 몸에 최대한 밀접하게 붙게 하는 뼈대 브라켓이다.

베벨기어박스

베벨기어박스

Base plate(고 관절부)

Base plate(고 관절부)

모터 크라켓

모터 크라켓

허리 관절면

허리 관절면

Base plate(무릎 관절부)

Base plate(무릎 관절부)

모터 브라켓

모터 브라켓

무릎 관절면

무릎 관절면

기어

기어

Gear Box(하단 기어 중심 고정부)

Gear Box(하단 기어 중심 고정부)

Gear Box(측면 기어 중심 고정부)

Gear Box(측면 기어 중심 고정부)

Gear Box(옆면 고정부)

Gear Box(옆면 고정부)

Shaft(하단 기어)

Shaft(하단 기어)

Shaft(측면기어)

Shaft(측면기어)

로터 플랜지

로터 플랜지

렉 플레이트

렉 플레이트

풋 플레이트

풋 플레이트

2011capstonef76

힌지 핀

5.1.2 제어부

90W

90W

150W

150W

모터 컨트롤러

모터 컨트롤러

MOXA 232 to 485 컨버터

MOXA 232 to 485 컨버터

RF 모뎀을 부착시킨 AVR 보드

RF 모뎀을 부착시킨 AVR 보드

5.2 조립 사진

직접 제어한 기어 박스 내부

직접 제어한 기어 박스 내부

목발 바닥에 부착한 스위치

목발 바닥에 부착한 스위치

모터와 컨트롤러 연결 사진

모터와 컨트롤러 연결 사진

고관절부 착용 사진

고관절부 착용 사진

발목부분 착용 사진

발목부분 착용 사진

보드를 부착한 목발

보드를 부착한 목발

조립완성한 사진 1

조립완성한 사진 1

조립완성한 사진 2

조립완성한 사진 2

5.3 제작 과정

브래드보드 시험 중인 Atmega128

브래드보드 시험 중인 Atmega128

송신 테스트 중인 A3007B과 직접 만들었던 회로의 실험 모습

송신 테스트 중인 A3007B과 직접 만들었던 회로의 실험 모습

착용 후 모습

착용 후 모습

착용 후 일어나는 과정

착용 후 일어나는 과정

6. 결론

6.1 설계 쪽 실패과정 & 해결방안

전체적인 기구부가 커지는 것을 막기 위해 모듈1의 베벨기어박스를 사용하였으나, 소형 베벨기어였기 때문에 큰 토크에서 견디는 힘이 부족했다. 기구부만 작동시키는 데에는 큰 무리가 가해지지 않았으나 사람이 착용하고 구동한 경우, 앉기 동작에서 문제가 발생하였다. 사람이 의자에 앉는 경우 하중이 뒤로 자연스레 쏠리는 것을 미처 계산하지 못한 바람에 기어 이빨이 손상된 일이 있었다.

따라서 무릎에 가해지는 토크를 보다 잘 견딜 수 있도록 기존보다 큰 2.5 모듈의 베벨기어로 바꾸었다. 결과적으로 이빨의 크기가 커져서 전체적인 기어박스 및 기구부의 크기도 덩달아 커졌지만 상대적으로 견딜 수 있는 토크의 크기도 커졌다.

6.2 제어 쪽 실패과정 & 해결방안

ATmega128 보드를 직접 만들기 위해 브래드 보드에 꽂아 실험할 수 있는 UST-MPB-ATmega128 제품을 이용하여 기본적인 회로들을 확인하였다. 납땜을 하기 전 RF 모뎀 회로를 체크하기 위해 브래드 보드로 전원 회로 및 기본적인 송수신 회로를 작성한 후, PCB에 납땜을 하였다. 기본적인 RF 회로 및 스위치 회로는 납땜을 하여 확인을 하였으나, max232 회로 등이 제대로 작동을 하지 않았으며 잦은 브래드 보드 실험 및 전원 회로부에서 꼬인 회로들로 인해 대부분이 쇼트가 나서 max232의 회로를 확인할 수가 없었다. 보드를 다시 제작하려 했으나, 시간상의 문제로 보드를 다시 만들 수 없다고 판단하여 보드 옆에 회로 판이 부착된 개발보드 기능의 AVR 모듈을 이용하였다. 이 AVR 보드에 RF modem 회로 및 필요한 스위치 회로만 추가로 납땜을 해서 필요한 보드를 완성하였다.

기존의 통신방식은 RS232통신을 이용하는 것이어서 추가의 회로가 필요하지 않았지만 후에 RS485로 통신방식을 바꾸면서 RS485와 관련된 회로가 필요하게 되었다. SN75176이란 IC를 사용하여 통신을 할 생각이었으나, 추가적인 회로를 납땜하는 것보다 컨버터를 이용하는 편이 효율적이라 판단하여 MOXA사의 TCC-80 이라는 RS232 to RS485 컨버터를 사용하였다.

구동 프로세스가 목발에 연결된 스위치에 힘을 가하면 목발 쪽 RF가 메인보드에 신호를 송신하고 이러한 RF신호 2개가 메인보드에 수신되어야만 모터가 작동하는 것이라서 컨트롤러 2개, RF modem까지 총 3개의 통신포트가 필요했다. 모터 제어부와 RF 제어부를 따로 작업하다보니 UART방식과 RS232 통신 방식이 충돌이 날거라는 것을 고려하지 못하였다. 그 문제점을 해결하기 위해 메인 MCU를 2개 사용하는 것으로 진행하였었다. MCU를 2개 사용하여 연동하는 것보다 1:n의 통신이 가능한 RS485방식을 택하는 게 효율적이라 판단하였고, 이를 통해 포트 2개로 2개의 컨트롤러 RF modem까지 3개의 통신을 해결할 수 있게 되었다.

6.3. 결론

무릎 부분에 힘이 많이 걸리는 것을 고려하여 무릎부 기어를 2.5 베벨 기어로 선정하였고 통신방식은 RS485방식을 선택하여 보드의 개수를 줄일 수 있었다. 실제적인 작동의 경우 기구부만으로 앉고 일어서기 및 걷기 동작은 구현이 가능하며, 현재 사람이 착용한 채 동작을 구현하는 것은 부분적으로 가능하다. 앉기 및 일어서기 동작의 경우 사람이 착용한 채 동작을 구현할 수 있었으나, 걷기 동작의 경우 기구부를 착용하는 팀원이 아직 목발 사용에 익숙치 않아 걷기 움직임이 조금 부자연스러운 관계로 일반적인 걸음걸이의 형태로 각도를 제어하였다. 사람마다 걸음걸이 방식이 조금씩 다르기 때문에 팀원의 목발사용 연습과 함께 차후에 구현할 팀원의 걸음걸이에 맞춰 시연할 예정이다.

7. 팀원 소개 및 역할 분담

이수영 : 해석 및 RF 통신

홍준호 : 가공 및 조립

정그림 : 해석 및 3D Modeling

한솔 : 모터 제어

Leave A Comment

*