[62호]180도 방향을 한번에 탐지하여 interaction한 반응형 스마트 지팡이
2020 ICT 융합 프로젝트 공모전 우수상
180도 방향을 한번에 탐지하여interaction한
반응형 스마트 지팡이
글 | 한국과학기술원 김동주
1. 심사평
칩센 손잡이에 모터를 이용한 햅틱 기능을 포함한 것이 매우 인상적입니다. 단순히 장애물의 유무만을 진동을 통해 알려주는 것이 아닌, 거리와 방향 등도 함께 알려준다는 것이 참신한 아이디어로 와닿습니다. 다만 제품으로 생각하였을 때 모터부가 많이 포함됨에 따른 전류 소모와 무게 등이 조금 걱정입니다. 향후 추가 적용 가능한 기능들( TTS, 사우드, 디스플레이등)을 적용하면 더 열악한 요소가 될 소지가 있어 보여, 위의 사용성에 저해가 될만한 부분을 잘 해결해 나가는 것이 관건일듯 합니다.
펌테크 작품의 아이디어와 실용성 창의성이 돋보이는 작품으로 생각됩니다. 6개의 서보모터를 사용해 촉각피드백을 제공하는 내용은 신선했으며 전체척으로 기획 의도에 맞게 시스템을 안정적이고 완성도 높게 구현하였고 제출된 보고서 구성 내용도 명확하고, 충실했다고 생각이 듭니다. 전체적으로 기획의도, 기술 구현도, 완성도 등에서 상당히 우수한 작품으로 생각됩니다.
위드로봇 작품의 완성도는 높습니다만, 화이트케인 프로젝트는 과거에 매우 많은 팀들이 시도했던 전력이 있습니다. 기존 사례 연구를 진행한 뒤 보완점을 찾아 진행했으면 창의성에서 더 높은 점수를 받을 수 있습니다.
2. 작품 개요
작품은 기존의 굉장히 좁은 방향각도(15도)로 물체를 탐지하는 스마트 지팡이의 단점을 개선하고 다양한 햅틱 반응을 통해 사용자가 물체의 위치와 방향을 인식할 수 있도록 하는 시스템을 스마트 지팡이에 구현하고자 한다.
- 장애물 위치, 방향에 따른 햅틱 반응 (점자와 비슷한)
- 거리에 따른 손잡이 진동 반응
- 블루투스 통신을 통한 스마트폰의 음성 안내 및 진동
3. 작품 설명
3.1. 기존 제품의 문제점
일반 보조 지팡이의 경우 보행자의 감각에 의존하여 스스로 위험 수준을 판단하고 대처해야 하는 단점이 있다. 이러한 단점을 개선하고자 많은 사람이 노력해왔고 최근 들어 점점 센서의 가격이 낮아지고 있고 IOT가 넓은 영역에 적용할 수 있게 되자 스마트 지팡이라는 것을 만들게 되었다. 현재 잘 알려진 지팡이로는 we-walk라는 지팡이이다. 이 지팡이는 2015년에 등장하였고 초음파 센서와 진동센서, 스피커, 터치패드가 내장되어 있다. 주요 기능은 전방에 장애물이 있는 것을 진동과 사운드를 통해 경고 해주는 장점이 있다. 하지만 단점으로는 초음파센서의 물체 탐지하는 각도가 최대 15~30도로 굉장히 좁아 지팡이가 향하는 곳만 탐지가 가능하다.
시각장애인이 일반 사람과 달리 거리를 다닐 때 가장 크게 느낄 수 있는 불편한 점은 일반사람은 자신이 가는 길 부분 외에 범위도 볼 수 있어(넓은 화각) 쉽게 장애물 회피가 가능하다. 하지만 시각장애인은 지팡이에 의존하여 자신이 가는 길 좁은 부분에만 장애물의 존재를 알 수가 있다. 그래서 기존의 스마트 지팡이는 이러한 근본적 문제를 해결하지는 못하였다.
이러한 근본적인 문제를 해결하기 위해 새로운 지팡이를 설계하고자 하였고, 현재 자율주행기술에서 보면 자동차 천장상단에 보면 레이더가 360도로 매우 빠르게 도는 것을 볼 수가 있는데 이러한 원리를 지팡이에 도입하여 기존 방식에서 진화하여 사용자의 전방 180도 방향의 물체를 탐지하여 어느 곳에 위치( 거리, 방향에 따라 )가 있는지 알아내어 햅틱이나 진동 소리 등 다양한 감각으로 표현하고자 하였다.
3.2. 주요 동작 및 특징 및 전체 시스템 구성
3.2.1. 초음파 센서 동작
지팡이 하단에 있는 초음파 센서는 서보 모터와 연결되어 있어 150도를 움직일 수 있다. 1.5초의 시간동안 150도를 회전하게 되는데 이는 우리의 눈으로 봤을 때이고 프로그램에서는 사실은 서보모터는 0.15초마다 10도씩 움직이고 멈추고, 멈추었을 때 해당각도에서 초음파를 보내게 되고 반사되는 시간을 측정하여 거리로 환산한다. 이때 해당 각도와 거리에 따라 3*3 Array에 물체가 탐지되었으면 1로, 물체가 탐지되지 않으면 0으로 하여 매 순간 정보를 업데이트 한다. 근데 이때 이미 배열에 1이 저장되어 있는데 순식간에 0으로 탐지 된다고 하면, 0으로 바꾸지 않는다. 즉 한번 전방을 훑는 과정에서 그 위치에 무언가 탐지되어 1로 바뀌면, 그 훑는 과정에서는 계속 1로 저장된다. 그래야 순식간에 지나가는 장애물도 1.5초 동안 인식했다고 하여, 만의 하나의 위험을 막을 수 있게 된다.
이런 방식으로 동작을 하게 되면 1.5초 간격마다는 사용자 앞의 중심으로 150도 각도로 탐지되어 대략 몇 도 방향에 몇 cm 거리에 해당하는 배열을 통해 장애물이 어디에 있는지 정보를 인지 할 수 있게 된다.
초음파 센서를 2개 쓰는 이유는 각 초음파 센서의 위아래 탐지 각도가 15도 이내이므로 2개를 사용함으로써 총 30도이상의 각도가 탐지가 가능하게 하였고 한 센서의 탐지가 잘못되어 일어나지 않는다면 다른 센서가 이를 탐지 할 수 있게 하기 위함이다.
3.2.2. 6개의 서보모터
3.2.1 초음파 센서 동작에서 얻은 초음파센서의 3*3 array 정보 중 가까운 거리의 2*3 array만을 이용하여 6개의 서보모터를 통해서 촉각 피드백을 제공한다.
아래 표와 그림3과 같이 해당 array에 0의 값이 있으면 서보모터의 각도를 1이 있으면 90도로 설정한다. 그렇게 되면 바깥쪽으로 component가 튀어나오게 되어 촉각적인 정보를 제공할 수 있게 된다.
즉 사용자의 입장에서 1.5초 동안 좌측 0~50도 방향에만 15~70cm 거리 부근에 장애물이 탐지되었다면 배열은 다음과 같이 정보를 저장하고, 서보 모터는 그 배열의 정보를 바탕으로 (점자 비슷하게) 1인 부분만 돌아간다.
3.2.3. 블루투스 모듈
서보 모터와 마찬가지로 초음파 센서가 update시킨 3*3 array 0,1 정보를 바탕으로 블루투스 모듈이 해당 거리 정보를 폰으로 송신하여, 스마트폰에서 그 정보를 읽을 수 있도록 해준다.
3.2.4 스마트 기기
블루투스로 수신된 데이터를 바탕으로 스마트폰 디스플레이에 정보를 표시하고 진동 피드백과 Google의 text to speech를 이용하여 청각적인 정보로도 명확히 알 수 있게 한다.
탐지 거리에 따른 앱 인터페이스 속 표시되는 이미지
4. 개발과정 및 기타
4.1. 하드웨어 구성
다음은 회로 구성도이다.
사용된 부품은 a. 7개의 servo motor b. 2개의 초음파 센서(HC-SR04) c. 스위치 d. 블루투스 모듈 (HC-06) e. Servo motor 6개의 제어를 위한 pca9685 chip f. Vibration motor g. AAA 건전지 4개 h. 아두이노 이다.
4.2. 외형도 (모델링 과정 및 햅틱을 위한 부품 제작)
외형은 다음과 같이 AUTOCAD사의 fusion360 프로그램으로 설계하고 SINDOH 3D프린터로 외형을 제작했다.
시각장애인을 촉각을 느끼게 할 수 있는 햅틱을 위한 서보모터에 부착하는 COMPONENT는 illustrator로 제작을 하여 레이저 컷팅기로 아크릴 5T를 잘라 만들었다. 그리고 로고를 MDF 3T를 레이저 컷팅기로 음각을 새겨내 손잡이 전면부 동그란 부분에 끼워 붙였다.
모델을 다 뽑았으면, 아두이노와 서보모터, 기타 센서들을 회로와 같이 만들 모델 케이스 안에 부착한다.
그 후 지름 2cm 길이 90cm의 나무 막대기를 모델하단부에 붙여준다.
4.3. 완성된 모델의 랜더링
랜더링은 keyshot을 이용했다.
4.4. 코딩 작업 #define WINDOW_SIZE 5 SoftwareSerial BTSerial(2,3); //tx rx핀 순서로 설정 //#define SERVOMIN 150 // This is the ‘minimum’ pulse length count (out of 4096) Servo myservo; //서보모터 각도 //전방에 있는 물체 int echoPin1 = 12; //초록색 핀 int vibration = 6; //진동모터 int sw=5; //함수 선언하는 곳 void setup(){ // 초음파를 보낸다. 다 보내면 echo가 HIGH 상태로 대기하게 된다. delayMicroseconds(2); delayMicroseconds(10); delayMicroseconds(2); delayMicroseconds(10); float distance1 = ((float)(340 * duration1) / 10000) / 2; Serial.print(“filter_dis1: “); if((distance1<=90 && distance1>50) || (distance2<=90 && distance2>50)){ else if((distance1<=70 && distance1>20) || (distance2<=70 && distance2>20)){ else if(search[1][0]==0){ if(55<=angle && angle<110){ else if(search[1][1]==0){ if(110<=angle && angle<165){ else if(search[1][2]==0){ if(110<=angle && angle<165){ if(angle>=180){ }
4.4.1. Arduino coding
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <SoftwareSerial.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
//#define SERVOMAX 600 // This is the ‘maximum’ pulse length count (out of 4096)
#define SERVOMID 400
#define SERVOMIN 130
#define SERVOMAX 633
int opp=0;
int angle=0;
int search[3][3]={0,};
int trigPin1 = 13; //노란색 핀
int echoPin2 = 7; //흰색 핀
int trigPin2 = 8; //
void vibrate(float f_distance1, float f_distance2);
myservo.attach(9); //
Serial.begin(9600);
BTSerial.begin(9600);
pinMode(trigPin1, OUTPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(echoPin2, INPUT);
pinMode(sw, INPUT_PULLUP);
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~50 Hz updates
delay(10);
}
void loop(){
//myservo.attach(9);
if (digitalRead(sw) == LOW) {
Serial.print(“ANGLE:”);
Serial.println(angle);
if(!opp){
angle+=10;
}
else{
angle-=10;
}
myservo.write(angle);
digitalWrite(trigPin1, LOW);
digitalWrite(echoPin1, LOW);
digitalWrite(trigPin1, HIGH);
digitalWrite(trigPin1, LOW);
// echoPin 이 HIGH를 유지한 시간을 저장 한다.
unsigned long duration1 = pulseIn(echoPin1, HIGH);
digitalWrite(trigPin2, LOW);
digitalWrite(echoPin2, LOW);
digitalWrite(trigPin2, HIGH);
digitalWrite(trigPin2, LOW);
unsigned long duration2 = pulseIn(echoPin2, HIGH);
float distance2 = ((float)(340 * duration2) / 10000) / 2;
Serial.println(distance1);
Serial.print(“filter_dis2: “);
Serial.println(distance2);
vibrate(distance1,distance2);
if(0<=angle && angle<55){
search[2][0]=1;
}
else if(search[2][0]==0){
search[2][0]=0;
}
if(55<=angle && angle<110){
search[2][1]=1;
}
else if(search[2][1]==0){
search[2][1]=0;
}
if(110<=angle && angle<165){
search[2][2]=1;
}
else if(search[2][2]==0){
search[2][2]=0;
}
}
if(0<=angle && angle<55){
search[1][0]=1;
}
search[1][0]=0;
}
search[1][1]=1;
}
search[1][1]=0;
}
search[1][2]=1;
}
search[1][2]=0;
}
}
else if((distance1<=20 && distance1>1) || (distance2<=20 && distance2>1)){
if(0<=angle && angle<55){
search[0][0]=1;
}
else if(search[0][0]==0){
search[0][0]=0;
}
if(55<=angle && angle<110){
search[0][1]=1;
}
else if(search[0][1]==0){
search[0][1]=0;
}
search[0][2]=1;
}
else if(search[0][2]==0){
search[0][2]=0;
}
}
int b_send=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
uint8_t servonum = 1+j+i*3;
if(search[i][j]==1){
if(i==0 && b_send==0){
BTSerial.write(“a”);
b_send=1;
}
else if(i==1 && b_send==0){
BTSerial.write(“b”);
b_send=1;
}
else if(i==2 && b_send==0){
BTSerial.write(“c”);
b_send=1;
}
pwm.setPWM(servonum,0,SERVOMID);
}
else{
pwm.setPWM(servonum,0,SERVOMIN);
}
search[i][j]=0;
}
}
b_send=0;
opp=1;
}
if(angle<=0){
int b_send=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
uint8_t servonum = 1+j+i*3;
if(search[i][j]==1){
if(i==0 && b_send==0){
BTSerial.write(“a”);
b_send=1;
}
else if(i==1 && b_send==0){
BTSerial.write(“b”);
b_send=1;
}
else if(i==2 && b_send==0){
BTSerial.write(“c”);
b_send=1;
}
pwm.setPWM(servonum,0,SERVOMID);
}
else{
pwm.setPWM(servonum,0,SERVOMIN);
}
search[i][j]=0;
}
}
b_send=0;
opp=0;
}
delay(100);
//myservo.detach();
}
else{
analogWrite(vibration,0);
}
}
void vibrate(float f_distance1, float f_distance2){
if((f_distance1 <= 100 && f_distance1 > 60) || (f_distance2 <= 100 && f_distance2 > 60)){
analogWrite(vibration, 100);// 진동모터를 200/255의 파워로 작동시킵니다.
}
else if(f_distance1<=70 && f_distance1>15 && f_distance2<=70 && f_distance2>15){
analogWrite(vibration,180);
}
else if((f_distance1<=15 && f_distance1>1) || (f_distance2<=15 && f_distance2>1)){
analogWrite(vibration,240);
else{
analogWrite(vibration,0);
}
}
4.4.2. App inventor coding (안드로이드 앱 구현)
A. 앱 및 인터페이스 디자인
시각장애인 안내견의 이미지를 지팡이로 표현하여 친숙한 이미지를 나타내고자 하였다.
B. 변수 및 함수 선언
C. Screen1에 대한 설정
D. Clock (반복문)에 대한 설정
E. 여러 컴포넌트에 대한 설정
4.5. 테스트 작업
수많은 테스트를 통해, 초음파 센서 최대각도 중 150을 얼만큼의 단위 각도로 나누어서 돌릴지, 그 단위 각도를 몇 초 동안 움직이게 할 것인지, 초음파 센서위치와 각도를 어떻게 하면 수직으로 더 넓은 범위의 물체를 탐지할 수 있는지, 진동모터의 세기는 얼마로 할 것인지, 얼마나 먼 거리의 물체부터 탐지해야 되는지에 대한 값을 구하고자 하였다.
5. 기대효과
매우 좁은 범위의 상황만 인지할 수 있는 시각장애인들의 근본적인 불편한 점을 자율주행자동차의 전방향의 도로 상황을 탐지하는 원리를 이용하여 해결함으로써 시각장애인들이 앞에 놓여진 상황에 대한 다양한 물체 정보과 피드백을 제공할 수 있게 된다. 스마트폰의 블루투스 기능을 연동하여 TTS기능, 사운드, 진동, 디스플레이 등의 더욱 확장성 있는 사용과 시각, 촉각, 청각 등 다양한 피드백 제공이 가능해진다. 처음에만 페어링하면 블루투스 주소를 계속 저장하고 있어 에어팟과 같이 지팡이와 스마트폰의 각각의 블루투스 기능만 켜져 있으면 자동으로 연결하여 매번 연결하는 불편한 점을 해소한다.
6. 추후 연구
초음파 센서가 달린 서보모터의 경우 계속 움직여야 하기 때문에 전력소모가 매우 심하고 소음도 살짝 존재한다. 이러한 문제를 해결하기 위해서 딥러닝의 영상처리능력을 이용하여 전방의 물체와 배경을 잘 구분하여 대략적인 거리를 유추하여 가까이 있다고 판단되면 그 때 서보 모터를 움직여 초음파 센서나 혹은 Tof 센서로 정확한 거리를 측정하게 되면 이러한 전력 문제와 소음 문제도 해결가능 할 것으로 보인다.
현재의 작품의 경우 0~50도, 50~100도, 100~150도 범위0 안의 물체가 있다라는 것을 인지 할 수 있지만 더욱 세분화하여 각도를 나누어 전방의 정보를 완벽히 인식하여 사용자의 앞 상황을 촉각적인 증강현실로 구현함으로써 시각장애인의 보행 중 문제 뿐만 아니라 전반적인 삶의 질 향상에 기여 할 수 있게 될 것 이다.
7. 참고 문헌
가. https://www.youtube.com/watch?v=y8X9X10Tn1k
나. https://learn.adafruit.com/16-channel-pwm-servo-driver/hooking-it-up
다. 함수사용
라. https://blog.naver.com/roboholic84/10186975566
마. https://cafe.naver.com/mechawiki/104
바. https://kocoafab.cc/tutorial/view/704