May 28, 2020

디바이스마트 미디어:

[30호] 너무 쉬운 아두이노 DIY ② – 카멜레온 반지 + 빨노파 게임기 만들기

30 아두이노 카멜레온

30 아두이노 카멜레온

             글 ㅣ 신상석 ssshin@jcnet.co.kr

 

  여러분, 안녕하세요. 앞으로 1년에 걸쳐(6번 정도) [너무 쉬운 아두이노 DIY(Do It Yourself)] 강의를 진행할 강사 신상석입니다.
제 소개 간단히 드립니다.
· 서울대 제어계측공학과(학사) →, KAIST 전산과(석사) → KAIST 전산과(박사 수료)
· ETRI 책임연구원 → 해동정보통신 연구소장 → 욱성전자 연구소장 → (현재) 제이씨넷 연구소장, 상명대학교 컴퓨터시스템공학과 겸임교수, 임베디드홀릭 카페(http://cafe.naver.com/lazydigital) 부매니저, 아두이노 / AVR 강사
· 자격증 : 전자계산기 기술사
· 취미 : 영화보기, 바둑두기, 책읽기, 글쓰기(?), 여행하기, 이야기하기
· 연락처 : ssshin@jcnet.co.kr, 있는그대(cafe.naver.com/lazydigital)이 강의는 아두이노를 가지고 간단하게 생활에 필요한 용품을 만들어 보는 강의입니다. 뚝딱뚝딱 뭔가 자신만의 DIY 용품을 만들어 보는 쏠쏠한 재미가 있는 강의라고나 할까요? 이미 주변에 아두이노와 관련한 많은 책이 출간되었고 카페나 블로그를 통하여 강의가 진행된 경우도 꽤나 많이 있는데도 불구하고, 이 지면을 통하여 강의를 개설한 이유는 다음과 같습니다. 

1. 아두이노의 초보자들을 위한 쉽고 재미있는 강의가 거의 없는 것 같아, 가능하면 초등학생(?)까지도 함께 해 볼 수 있는 그런 강의를 한 번 해보고 싶어서…
2. 아두이노를 가지고 뭔가 조금은 다른, 자신만의 창의적인(?) DIY를 할 수 있는 자리를 만들어주고 싶어서…
3. 디바이스마트매거진은 임베디드와 관련된 독자들이 많고, 발행 부수도 많아, 저와 제가 속한 회사(제이씨넷) 그리고 임베디드홀릭 카페의 홍보에 도움이 될 것 같아서…

아두이노 계획표현재 구상하고 있는 회차별 내용을 간략하게 정리해 보면 다음과 같습니다. (변경될 수 있습니다.) 앞으로 즐겁고 알찬 강의가 될 수 있도록 최선을 다할 것을 약속 드리며, 이 강의를 보는 독자들도 메일이나 카페를  통하여 Q&A(Question & Answer)나 피드백을 주셔서, 함께 정감을 나눌 수 있는 계기가 되기를 기대해 봅니다.

   여러분, 안녕하세요. 신상석 강사입니다. 이번 회에서는 컬러 LED를 가지고 만들 수 있는 DIY 작품을 2가지를 만들어 보겠습니다. 하나는 여러가지 색깔로 변하는 ‘카멜레온 반지’이고, 또 하나는 가위 바위 보 게임과 비슷한 ‘빨노파 게임기’입니다. 간단하고 재미있는 DIY이므로, 이를 약간씩 응용하여 최종적으로는 각자 자신만의 개성있는 DIY 작품을 만들어 보면 좋겠습니다.

 

 ■ 카멜레온 반지                                                                                            

   카멜레온(chameleon)을 아시나요? ‘땅 위의 사자’라는 뜻을 가진 그리이스어에서 유래한 카멜레온은 주변의 색에 따라 아주 비슷한 보호색으로 변하는 능력을 가진 재주꾼입니다. 자신의 감정을 표현하기 위하여 자신이 원하는 색깔로 변할 수도 있다고 하니, 세상에는 인간 말고도 오묘한 동물이 정말 많은 것 같네요.

30 카멜레온반지 02

 그런데 “카멜레온 반지”가 뭐냐구요? 아마도 다들 모르실텐데요. 왜냐하면 제가 얼마 전에 작명한 이름이어서요. 카멜레온 반지는 카멜레온처럼 반지의 색깔이 자유자재로 변하는 반지를 말합니다. 가만히 있으면 저절로 색깔이 변하는 반지라고나 할까요?.

 

아래 그림은 12개의 달을 상징하는 보석으로 탄생석입니다. 에머랄드, 다이아몬드, 루비… 참 아름답지요. 무엇보다도 알록달록한 색깔이 압권입니다.

 

30 카멜레온반지 03

 

   그래서 오늘은 이렇게 멋진 보석이 콕 박혀있는 반지를 상상하며 12개의 보석으로 변신이 가능한 카멜레온 반지를 만들어볼까 합니다. 반지의 링은 준비가 되었다고 가정하고 보석 부분만 카멜레온처럼 색깔이 변하도록 만들면 될 것 같네요. 그런데, 어떻게 만드냐구요? 예. 컬러 LED로 만들지요.

 ■ 컬러 LED                                                                                              

   컬러 LED는 빨강, 녹색, 파랑 LED 3개를 하나로 모아 1개의 캡슐로 씌운 LED입니다. 그러니까 3개의 LED를 바짝 붙여서 한 개의 전구 속에 넣은 것이지요. 요렇게요.

30 카멜레온반지 04

다리가 가장 긴 것이 공통 애노드(Anode, +), 또는 공통 캐소드(Cathode, -)로 공통 애노드 타입의 경우는 (+) 핀을 High(VCC, 5V)에 연결하고, R, G, B 핀에는 Low(GND, 0V) 값을 연결하는 경우에만 불이 들어오고, 공통 캐소드 타입의 경우는 반대로 (-) 핀을 Low(GND, 0V)에 연결하고, R, G, B 핀에는 High(VCC, 5V) 값을 연결하는 경우만 불이 들어옵니다. (물론, 지난번 설명처럼 직렬 저항은 연결한다고 가정하였습니다.) 여기서는 아래와 같이 공통 캐소드 타입의 컬러 LED를 사용하여 제작해 보는 것으로 하겠습니다.

30 카멜레온반지 05

 

(53N RGB 262C-9001, 참조 : 디바이스마트)

 

  어 그런데, LED가 3개면 다리가 6개라야 되는 것 아닌가요? 다리가 4개 밖에 없는데…

  예, 원래는 6개지만 (-)에 해당되는 다리는 공통이니까(공통 캐소드), 빨강, 녹색, 파랑, 공통 (-), 이렇게 다리를 4개로 줄일 수 있겠습니다. 지난번 3색 신호등을 만들 때 각 LED의 (-)에 해당되는 것은 모두 GND로 함께 연결한 것을 생각해 보면 쉽게 이해가 갈 겁니다..

  그렇다면, 이 컬러 LED는 빨강, 녹색, 파랑으로 색깔이 고정되어 있는데, 어떻게 카멜레온처럼 여러가지 오묘한 색깔을 나타낼 수 있을까요?

  이 질문에 대한 해답은 바로 빛의 혼합에 있습니다.

  아래 그림은 누구나 초등학교 시절에 한 번은 보았을 것입니다.

30 카멜레온반지 06

 

  왼쪽은 빛의 삼원색(빨강(Red), 녹색(Green), 파랑(Blue), RGB)이고, 오른쪽은 색의 삼원색(자홍(Magenta), 청록(Cyan), 노랑(Yellow))입니다. 우리는 LED를 가지고 색깔을 만들 예정이므로 빛의 3원색의 경우만 보면, 3개의 빛이 합해지는 부분에 다른 색이 나타나는 것을 볼 수 있습니다.

 

   ■ 빨강 + 녹색 = 노랑

   ■ 녹색 + 파랑 = 청록

   ■ 파랑 + 빨강 = 자홍

   ■ 빨강 + 녹색 + 파랑 = 흰색

 

  오. 그렇네요. 이렇게 하니까 4개의 색이 더 만들어졌습니다. 하지만, 탄생석과 같이 알록달록한 여러가지 색은 아직도 만들어지지 않았는데 이것은 어떻게 만들 수 있을까요?

  이것은 광량(빛의 양)에 해답이 있습니다.

  즉, 빨강과 녹색, 파랑을 각각 100%씩 섞으면 흰색이 나오지만, 예를 들어 빨강 100% + 녹색 75% + 파랑 75% 로 빛을 섞으면 핑크(Pink)색이 나오는 원리입니다.

  결국 관건은 우리가 3가지 LED의 광량을 강하게 했다 약하게 했다 조절할 수 있느냐 하는 것인데 결론은 “할 수 있다” 입니다.

  아래 그림을 보시지요.

30 카멜레온반지 07

 

  원래 디지털 값은 High(1, 5V, 100%), Low(0, GND, 0%)의 2가지 값밖에 존재하지 않지만, 위 그림과 같이 어떤 핀의 값을 High ▶ Low ▶ High ▶ Low … 형태로 상태를 변환시키게 되면, 출력 전압의 평균(%)은 빨강색 점선과 같은 값을 갖게 됩니다. 예를 들어 High를 유지하는 시간과 Low를 유지하는 시간의 비율이 3:7이라면 평균값은 High값의 30%가 된다고 말할 수 있는 것이지요. 이렇게 주기적으로 High ▶ Low를 반복하는 신호를 펄스(Pulse)라고 하는데, 이 펄스(Pulse)의 폭(Width)을 조절(Modulation)하여 평균값을 조절하는 방법을 PWM(Pulse Width Modulation)이라고 합니다. 즉, PWM을 이용하면 디지털 출력인 High(1)와 Low(0)을 가지고 0.3(30%), 0.85(85%)와 같은 아날로그 값을 만들 수 있게 되는 것입니다. 핑크색을 컬러 LED로 표현해 본다면 아래와 같이 되겠네요.

    ■ 핑크 = 빨강 PWM 100% + 녹색 PWM 75% + 파랑 PWM 75%

 

 

 ■ PWM 출력을 만드는 방법                                                                   

  이제 PWM 출력을 만드는 방법을 알아봅시다. 아두이노에서는 다음과 같은 analogWirte( ) 라이브러리 함수를 제공하는데 이것을 이용하면 PWM 0% ~ PWM 100% 까지의 펄스를 아주 쉽게 만들 수 있습니다. 단, analogWrite( ) 함수를 사용할 수 있는 핀은 핀 번호 앞에 틸드(~) 표시가 있는 핀으로 한정되어 있다는 점은 주의하셔야 합니다.

 

    ■ analogWrite(pin, value)

    ■ pin : 입출력핀 번호에 해당되는 숫자, 틸드(~) 표시가 되어 있는 핀만 가능

    ■ value : 0~255까지의 값으로 0이면 PWM 0%, 255이면 PWM 100%를 의미함

 

  예를 들어 “analogWrite(5, 128)”으로 프로그램 한다면, 핀 5번의 출력을 PWM 50%(128/256 = 0.5 = 50%)로 출력한다는 의미가 되겠습니다.

  왜 value 값으로 알기 쉽게 0~100을 사용하지 않고 0~255를 사용하게 되었을까요? 사실 그렇게 라이브러리를 만들 수도 있겠지만 디지털 세계는 2진법으로 이루어져 있어, 1, 2, 4, 8, 16, 32, 64, 128, 256 이렇게 만들어지는 수를 더욱 좋아한답니다. 아두이노 내부적으로 본다면 Atmega328, 타이머, ADC(Analog Digital Converter) 등 좀 더 자세하게 알아야 할 것이 많지만 우리는 그냥 이 정도만 알고 넘어가는 것으로 하겠습니다.

  이제 색의 배합을 %로 할 수 있다는 것을 배웠으므로, 간단히 한 번 연습해 보지요.

  노랑과 흰색, 핑크를 R, G, B의 value 값으로 표현해 보세요. 아래와 같이 나오면 정답!.

 

   ▶ 노랑 : R(255), G(255), B(0)

   ▶ 흰색 : R(255), G(255), B(255)

   ▶ 핑크 : R(255), G(192), B(192) // 192/256 = 0.75 = 75%

 

 ■ 컬러 LED 연결                                                                    

 

  자, 그럼 이제 기본 원리는 모두 이해했으니, 프로그램을 하기 전에 컬러 LED를 아두이노와 연결해 보겠습니다. 컬러 LED는 시중에서 구할 수 있는 것 아무거나 구하셔도 됩니다.  R, G, B 및 (-) 핀을 아래와 같이 연결하면 되겠네요.

 

    ■ R (가장 왼쪽) ←→ 330오옴 저항 ←→ 아두이노 6번핀

    ■ (-) (왼쪽에서 2번째, 길이가 가장 긴 다리) ←→ 아두이노 GND

    ■ G (오른쪽에서 2번째) ←→ 330오옴 저항 ←→ 아두이노 5번핀

    ■ B (가장 오른쪽) ←→ 330오옴 저항 ←→ 아두이노 3번핀

 

  우리가 연결한 아두이노 6번, 5번, 3번 핀의 옆쪽에 실크로 쓰여진 숫자에는 틸드(~) 표시가 되어 있는데, 이것은 아두이노 핀 중에서 analog_write( ) 함수로 PWM 신호를 만들어 낼 수 있는 핀이라는 것은 앞에서 설명하였습니다. 우리는 3개 핀에 모두 PWM을 사용하여야 하므로 반드시 틸드(~) 표시가 연결된 핀을 R, G, B에 연결해야 합니다. 아래의 그림처럼 연결이 되겠네요.

 30 카멜레온반지 08

 

 

 ■ 연습 프로그램 작성                                                                   

  이제 연결은 끝났으니 프로그램을 작성하여 실행할 차례입니다.

  최종 목표는 카멜레온 반지이지만 기왕 회로를 꾸몄으니 지난번 배운 것도 복습할 겸 7가지 색(빨강, 녹색, 파랑, 노랑, 청록, 자홍, 흰색)을 먼저 만들어 보도록 하겠습니다.

  아래는 기능 규격입니다.

 

[7가지 색 만들기 기능 규격]

  1. LED가 ON되는 순서는 빨강 ▶ 녹색 ▶ 파랑 ▶ 노랑 ▶ 청록 ▶ 자홍 ▶ 흰색 ▶ 빨강 ▶ … 으로 무한 반복됨

  2. LED는 어떤 한 순간 한가지 색깔만 표시함

  3. 표시된 색깔은 1초 동안 켜진 상태를 유지함

 

  위의 7가지 색 중 노랑, 청록, 자홍은 동시에 2개의 LED를 ON 하면 얻을 수 있고 흰색은 3개의 LED를 동시에 ON하면 얻을 수 있으므로 analogWrite( ) 함수를 사용하지 않고 digitalWrite( ) 함수만 사용하여도 충분히 구현이 가능하겠습니다. 스스로 혼자 구현해 보신 후 10분 후에 함께 해보도록 하지요. (10분간 실시!)

(1분), (2분), ……, (10분)

모두 잘 되셨으리라 생각합니다. 함께 해 보겠습니다.

#define RED_LED 6

#define GREEN_LED 5

#define BLUE_LED 3

void setup()

{

 pinMode(RED_LED, OUTPUT);

 pinMode(GREEN_LED, OUTPUT);

 pinMode(BLUE_LED, OUTPUT);

}

void loop()

{

 digitalWrite(RED_LED, HIGH);     digitalWrite(GREEN_LED, LOW);   digitalWrite(BLUE_LED, LOW); // R=ON, G=OFF, B=OFF –> 빨강(Red)

 delay(1000);

 digitalWrite(RED_LED, LOW);     digitalWrite(GREEN_LED, HIGH);   digitalWrite(BLUE_LED, LOW); // R=OFF, G=ON, B=OFF –> 녹색(Green)

 delay(1000);

 digitalWrite(RED_LED, LOW);     digitalWrite(GREEN_LED, LOW);   digitalWrite(BLUE_LED, HIGH); // R=OFF, G=OFF, B=ON –> 파랑(Blue)

 delay(1000);

 digitalWrite(RED_LED, HIGH);     digitalWrite(GREEN_LED, HIGH);   digitalWrite(BLUE_LED, LOW); // R=ON, G=ON, B=OFF –> 노랑(Yellow)

 delay(1000);

digitalWrite(RED_LED, LOW);     digitalWrite(GREEN_LED, HIGH);   digitalWrite(BLUE_LED, HIGH); // R=OFF, G=ON, B=ON –> 청록(Cyan)

 delay(1000);

digitalWrite(RED_LED, HIGH);     digitalWrite(GREEN_LED, LOW);   digitalWrite(BLUE_LED, HIGH); // R=ON, G=OFF, B=ON –> 다홍(Magenta)

 delay(1000);

digitalWrite(RED_LED, HIGH);   digitalWrite(GREEN_LED, HIGH);    digitalWrite(BLUE_LED, HIGH); // R=ON, G=ON, B=ON –> 흰색(White)

 delay(1000);

}

약간 긴 듯하지만 알고리즘은 지난번과 거의 비슷하고 간단합니다.

자, 컴파일 ▶ 업로드 ▶ 실행해 봅시다. 그리고 결과는 ?

동영상에서는 LED 빛이 너무 밝아서 색깔 구별이 또렷하지 않지만, 실제 눈으로 보면 아주 예쁜 7가지 색깔이 나옵니다. 이 정도면 만족스럽네요.

 ■ 컬러 및 컬러값 선택                                                                   

  연습으로 몸을 풀었으니, 이제 본격적으로 카멜레온 반지를 D.I.Y.하러 가겠습니다. 우리가 할 일은 12개 탄생석의 대표색을 찾아서 이것이 R, G, B의 어떤 값(어떤 세기, %)으로 표현되는지를 알아낸 다음 이것을 analog_write( ) 함수를 이용하여 구현하면 될 것 같습니다.

  자, 이제 탄생석의 색깔에 알맞은 R, G, B의 값을 찾아내면 되겠는데… 2가지 방법이 있습니다.

1. 색상표를 이용하는 방법

  아래와 같이 색상표가 있으므로 이것을 보고 탄생석과 가장 비슷한 색깔을 찾아 그 코드값을 추출하는 방법입니다. 6개의 숫자는 16진법으로 나타낸 코드 값으로 앞의 2개는 R(Red), 중간 2개는 G(Green), 마지막 2개는 B(Blue)에 해당되는 값을 나타냅니다. (혹, 2진법, 10진법, 16진법의 표기법이나 변환이 익숙하지 않은 분은 이 부분에 대하여 따로 각자 공부하신 후 다시 오시기 바랍니다.) 가장 왼쪽 줄의 위에서 6번째 색상이 노랑인데, 이 값을 보면 FFFF00 으로 표기되어 있으니까 [R(FF), G(FF) B(00)] ▶ [R(255), G(255), B(0)]가 되어 노랑색 PWM 표기값과 동일하다는 것을 확인할 수 있습니다.

 

30 카멜레온반지 10

2. 컬러 추출 응용프로그램을 이용하는 방법

  PC 상에서 특정 컬러에 대한 코드값을 추출해 내는 응용프로그램을 실행시켜서 원하는 색상을 클릭하여 코드값을 추출하는 방법입니다.

 

30 카멜레온반지 11

   탄생석은 코드표로 똑 떨어지는 색상이 아니고 우리가 색상을 직접 추출해보는 것도 재미있을 것 같으니까 우리는 두번째 방법을 사용하도록 하지요. 여러가지 프로그램이 있겠지만 여기서는 그냥 간단하게 실행시킬 수 있는 컬러캅(ColorCop)이라는 무료 프로그램을 사용하는 것으로 하겠습니다. (인터넷에서 찾아 다운로드받아 실행하면 됩니다.) 아래와 같은 화면이 나오는데요. 중간 왼쪽에 있는 스포이드처럼 생긴 아이콘을 드래그(클릭한 후 끌기)하여 원하는 컬러 위치에 가져다 놓으면 10진수로 표시된 R, G, B 값이 나타나게 됩니다. 참 쉽네요.

  자, 그러면 지금부터는 탄생석의 대표색에 대한 코드값를 추출해 보는 시간입니다. 색깔도 감상해 가면서 즐거운 마음으로 표를 작성해 보면 더욱 좋겠네요.

  코드 추출은 혼자서도 가능하겠지요? 12분 드립니다.

 

1분, 2분, …, 11분, 12분

 

  제가 직접 찍어서 추출한 값은 아래와 같습니다. (각자 다를 수 있습니다.)

한글 이름 영어 이름 R G B
1 가넷 garnet 254 26 27
2 자수정 amethyst 179 117 180
3 아쿠아마린 aquamarine 211 146 251
4 다이아몬드 diamond 254 155 255
5 에메랄드 emerald 14 219 133
6 진주 pearl 246 241 237
7 루비 ruby 206 3 163
8 페리도트 peridot 167 212 31
9 사파이어 sapphaire 26 27 216
10 오팔 opal 203 200 149
11 토파즈 topaz 254 198 40
12 터키석 turquoise 58 197 189

참, 가넷이라는 보석은 얼마전 종료된 ‘지니어스’라는 TV 프로에 이름이 소개되었던 짙은 자주색계통의 보석이지요. 꽤나 재미있었던 시리즈물이었는데 여러분들도 기회가 되면 꼭 한 번 시청해 보시기 바랍니다.

 

 

 ■ 카멜레온 반지 프로그램 작성                                                                          

 

  모든 준비가 끝났으니 이제 목표 프로그램을 작성하여 실행할 차례입니다. 우리가 원하는 기능 규격을 작성해 보지요.

 

[12가지 탄생석의 대표색을 디스플레이하는 카멜레온 반지 기능 규격]

  1. 컬러 LED로 12개 탄생석의 대표색 12개를 차례대로 ON하며, 무한 반복된다.

  2. 한 가지의 색은 1초 동안 켜진 상태를 유지한다.

 

  지난번에는 digitalWrite( ) 함수를 사용했지만 이번에는 analogWrite( )를 사용하고 작성된 표를 참조하여 R, G, B에 해당하는 PWM value값을 정해주는 것만 조금 다를 것 같습니다.

  같이 한 번 작성해 보시지요.

#define RED_LED 6

#define GREEN_LED 5

#define BLUE_LED 3

void setup()

{

 pinMode(RED_LED, OUTPUT);

 pinMode(GREEN_LED, OUTPUT);

 pinMode(BLUE_LED, OUTPUT);

}

void loop()

{

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 26);  analogWrite(BLUE_LED, 27);  // 가넷

delay(1000);

 analogWrite(RED_LED, 179);  analogWrite(GREEN_LED, 117);  analogWrite(BLUE_LED, 180);  // 자수정

delay(1000);

 analogWrite(RED_LED, 211);  analogWrite(GREEN_LED, 246);  analogWrite(BLUE_LED, 251);  // 아쿠아마린

delay(1000);

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 255);  analogWrite(BLUE_LED, 255);  // 다이아몬드

delay(1000);

 analogWrite(RED_LED, 14);  analogWrite(GREEN_LED, 219);  analogWrite(BLUE_LED, 133);  // 에메랄드

delay(1000);

 analogWrite(RED_LED, 246);  analogWrite(GREEN_LED, 241);  analogWrite(BLUE_LED, 237);  // 진주

delay(1000);

 analogWrite(RED_LED, 206);  analogWrite(GREEN_LED, 3);  analogWrite(BLUE_LED, 163);  // 루비

delay(1000);

 analogWrite(RED_LED, 167);  analogWrite(GREEN_LED, 212);  analogWrite(BLUE_LED, 31);  // 페리도트

delay(1000);

 analogWrite(RED_LED, 26);  analogWrite(GREEN_LED, 27);  analogWrite(BLUE_LED, 216);  // 사파이어

delay(1000);

 analogWrite(RED_LED, 203);  analogWrite(GREEN_LED, 200);  analogWrite(BLUE_LED, 149);  // 오팔

delay(1000);

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 198);  analogWrite(BLUE_LED, 40);  // 토파즈

delay(1000);

 analogWrite(RED_LED, 58);  analogWrite(GREEN_LED, 197);  analogWrite(BLUE_LED, 189);  // 터키석

delay(1000);

}

  음. 조금 많이 길긴 하지만…

  일단, 컴파일 ▶ 업로드 ▶ 실행해 봅시다. 결과는?

  카메라에 찍힌 것은 색깔 구별이 또렷하지는 않은데, 실제로 보면 아름다운 색깔이 구분되어 나타납니다. 보석에 비할 수는 없지만 그래도 아주 색상이 화려하고 아름답습니다.

  그런데 프로그램 짜면서 조금 마음에 걸리는 것이 있습니다.

  무엇이냐구요? 비슷한 내용이 12번이나 반복되고 코드 값을 일일이 입력해 주는 것이 조금 불편한 듯 하네요. 그래서, 12번 반복하는 것은 for 문을 이용하여 수정하고, 코드 값은 미리 어레이에 지정해 놓았다가 사용하도록 하여 위 코드를 조금 단순화시켜 보겠습니다. 아래와 같이 될 것 같습니다.

#define RED_LED 6

#define GREEN_LED 5

#define BLUE_LED 3

void setup()

{

 pinMode(RED_LED, OUTPUT);

 pinMode(GREEN_LED, OUTPUT);

 pinMode(BLUE_LED, OUTPUT);

}

void loop()

{

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 26);  analogWrite(BLUE_LED, 27);  // 가넷

delay(1000);

 analogWrite(RED_LED, 179);  analogWrite(GREEN_LED, 117);  analogWrite(BLUE_LED, 180);  // 자수정

delay(1000);

 analogWrite(RED_LED, 211);  analogWrite(GREEN_LED, 246);  analogWrite(BLUE_LED, 251);  // 아쿠아마린

delay(1000);

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 255);  analogWrite(BLUE_LED, 255);  // 다이아몬드

delay(1000);

 analogWrite(RED_LED, 14);  analogWrite(GREEN_LED, 219);  analogWrite(BLUE_LED, 133);  // 에메랄드

delay(1000);

 analogWrite(RED_LED, 246);  analogWrite(GREEN_LED, 241);  analogWrite(BLUE_LED, 237);  // 진주

delay(1000);

 analogWrite(RED_LED, 206);  analogWrite(GREEN_LED, 3);  analogWrite(BLUE_LED, 163);  // 루비

delay(1000);

 analogWrite(RED_LED, 167);  analogWrite(GREEN_LED, 212);  analogWrite(BLUE_LED, 31);  // 페리도트

delay(1000);

 analogWrite(RED_LED, 26);  analogWrite(GREEN_LED, 27);  analogWrite(BLUE_LED, 216);  // 사파이어

delay(1000);

 analogWrite(RED_LED, 203);  analogWrite(GREEN_LED, 200);  analogWrite(BLUE_LED, 149);  // 오팔

delay(1000);

 analogWrite(RED_LED, 254);  analogWrite(GREEN_LED, 198);  analogWrite(BLUE_LED, 40);  // 토파즈

delay(1000);

 analogWrite(RED_LED, 58);  analogWrite(GREEN_LED, 197);  analogWrite(BLUE_LED, 189);  // 터키석

delay(1000);

}

  예. 요렇게 작성해서 다시 실행시켜보면… 처음 프로그램하고 똑같이 실행되는 것을 알 수 있습니다. 이것도 당근 성공이겠죠?

  그럼, 마지막으로… 이 반지를 진짜 반지처럼 한 번 연출해 볼까요?

  손가락에 켜보는 형태로 흉내를 내보지요.

  컬러 LED를 뽑아서 4개의 다리에 선을 연결하고 이선을 원래 LED가 위치했던 브레드보드의 핀 위치에 꼽으면 원래 회로와 똑같은 회로입니다. 이것을 반지 모양으로 손가락 앞쪽으로 LED만 보이게 만들고 아두이노에 전원을 넣으면?

30 카멜레온반지 14

30 카멜레온반지 15

 

  야호~~~ 카멜레온 반지가 완성되었습니다.

  소품을 이용하여 잘 만들면 어느 정도 쓸만한 것도 만들 수 있을 것 같은데, 이것은 여러분들이 D.I.Y. 해보시기 바랍니다. 잘 만들어졌으면 주변에 자랑도 한 번 해 보시구요.

  시간나실 때 아래 과제도 한 번 해보시면 더욱 좋겠죠?

 [과제-카멜레온반지-1]

 R, G, B 색이 임의로 변하는 카멜레온 링을 만들어 보세요.

 [과제-카멜레온반지-1]

 R, G, B 각각이 0~255까지 짧은 시간 내에 계속 변화하면서 모든 색상을 디스플레이할 수 있는 카  멜레온링을 만들어 보세요. 총 256 x 256 x 256 = 16,777,226 가지의 색깔을 만들수 있을까요?

 

 

 

 ■ 스위치 연결                                                                                

  바로 전 강의까지 우리는 아두이노로 할 수 있는 2가지 기초 기능을 다루어 보았습니다. 디지털 출력(digitalWrite())과 아날로그 출력(analogWrite())이지요. 여기서의 아날로그 출력은 엄밀히 말하면 디지털 출력을 PWM을 이용하여 만든 유사 아날로그 출력이지만요.

 

  기본적인 출력을 2가지 해보았으니 이번에는 기본적인 입력을 이용하여 ‘빨노파 게임기’ D.I.Y.에 도전해 보겠습니다. 빨노파게임기란 빨강 ▶ 노랑 ▶ 파랑 순으로 LED 색깔이 상당히 빠르게(0.1초 이내) 변하다가 스위치를 누르는 순간 빨강, 노랑, 파랑 중의 1가지로 약 5초 정도 고정되는 LED 디스플레이어입니다. 아주 빠르게 색깔이 변하므로 사람이 임의로 색깔의 변화를 읽어서 스위치를 누른다는 것은 불가능하다고 볼 수 있으므로 임의의 색깔이 나타나는 상황이 됩니다. 그러므로 가위바위보 게임과 비슷하게 빨강은 파랑을 이기고, 노랑은 빨강을 이기고, 파랑은 노랑을 이긴다고 룰을 정한 후 두 사람이 스위치를 순서대로 눌러서 나온 색깔로 승부를 가린다면 간단한 게임기가 될 수 있겠습니다.

  아 참, 이건 여담인데, 빨노파… 하니까 생각나는게 하나 있네요. ‘개그콘서트’라는 TV 프로의 ‘나는 킬러다’ 코너에 등장하는 빨노파 3형제…  ‘일소일소(一笑一少)’라는 말이 있는데 한 번 웃으면 한 번 젊어진다고 하니, 여러분도 틈나는 대로 개그 프로 열심히 보면서 많이 웃으시기 바랍니다.

  LED가 대표적인 기본 디지털 출력 부품이라면, 스위치는 대표적인 기본 디지털 입력 부품입니다. 스위치를 모르는 사람은 천지(天地)에 없겠지만, 기왕 말이 나왔으니까 많이 쓰는 스위치 2-3가지만 조금 살펴보고 가는 것도 나쁘지는 않을 듯 합니다.

  우리가 제일 흔하게 많이 보고 많이 쓰는 스위치는 무엇일까요?

  요렇게 생긴 것이겠죠? 전자기기 전원 껐다 켰다 하는 스위치, 형광등 껐다 켰다 스위치.

30 카멜레온반지 16

(KCD1-101A RED, 상품코드: 1790)

  실생활에서 가장 많이 쓰이는 스위치로 이름은 로커(Locker) 스위치입니다. 잠긴(lock) 것처럼 ON이거나 OFF이거나 한가지 상태로 존재하지요.

  또, 어떤 스위치가 있을까요? 아래와 같이 생긴 슬라이드(Slide) 스위치도 많이 사용됩니다. 왼쪽이나 오른쪽으로 옮기면 각각 가운데 신호가 왼쪽이나 오른쪽에 연결된 신호와 연결되는 구조를 가진 스위치입니다. 요건 2단으로 되어 있어 2개의 서로 다른 신호가 동시에 왼쪽 또는 오른쪽으로 연결되는 형태네요.

30 카멜레온반지 17

 

(MSL-1C2P(듀얼)-2mm, 상품코드: 30530)

  이번 강의에서 사용할 스위치는 아래와 같이 생긴 택트(Tact) 스위치입니다. 이것도 굉장히 많이 사용됩니다. 아마도 contact에서 이름이 유래(?)된 듯한데, 손가락으로 누르면(contact 되면) ON, 떼면 OFF 상태가 되는 스위치이지요.

  아래 것은 다리가 4개가 있어서 2쌍의 신호가 한꺼번에 연결되거나(ON), 끊어지거나(OFF) 하는 스위치가 되겠습니다.

30 카멜레온반지 18

(ITS-1105-5mm, 상품코드: 34555)

  자, 스위치가 결정되었으니 그럼 이제 스위치를 연결해 볼까요?

  스위치 심볼은 보통 아래와 같은 2가지 형태를 취합니다. 스위치가 눌려지면 왼쪽과 오른쪽에 연결된 전선이 연결되는 것이지요. 스위치를 놓으면 양쪽의 연결은 끊어지는 것이구요.

30 카멜레온반지 19

30 카멜레온반지 20

  스위치가 디지털 입력이라고 하였고, 스위치는 양쪽 끝이 있으니까 한 쪽은 당연히 아두이노의 디지털 신호선 중 하나에 연결하여야 할 것이고, 다른 한쪽은 어디에 연결해야 할까요? 스위치를 눌렀을 때 ‘1’(HIGH)이나 ‘0’(LOW)이 입력되어야 하므로, ‘1’이 연결되려면 VCC(+5V)가 연결되어야 하고, ‘0’이 입력되려면 GND(0V, Ground)가 연결되어야 할 것입니다.

  그러면 이렇게 연결이 되겠네요.

 30 카멜레온반지 21

 

30 카멜레온반지 22

 

  그런데 가만히 보니까, 스위치를 눌렀을 때는 연결된 상태에 따라서 +5V 또는 0V(GND)가 연결되지만 스위치가 눌리지 않았을 때는 선이 끊어진 상태(floating 상태)가 되는데… 어라, 이렇게 되면 아두이노는 이 핀의 값을 HIGH(1)로 판단할까요? 아니면, LOW(0)로 판단할까요? 조금 어려운 문제인데 이것은 아두이노의 내부 로직과 상태에 따라 값이 결정될 수 있으므로 정확하게 HIGH 또는 LOW라고 단정지어 말할 수 없습니다. 즉, 상황에 따라 HIGH가 될 수도 있고 LOW로 될 수도 있다는 뜻인데, 이렇게 되면 값이 확정되지 않으므로 프로그램을 작성하는 사람은 대략난감(大略難堪, 이러지도 저러지도 못하는 당황스러운 상황)하게 됩니다. 그래서, 이렇게 선이 끊어진 상태가 될 때는 아두이노가 HIGH 또는 LOW 중, 하나의 값으로만 결정되도록 만들어 주는 조치가 필요합니다. 즉, 스위치를 눌렀을 때 HIGH가 되는 회로는 눌러지지 않았을 때 LOW가 되도록 조치해 놓아야 하고, 반대로 스위치를 눌렸을 때 LOW가 되는 회로는 눌러지지 않았을 때는 HIGH가 되도록 조치해 놓아야 하겠습니다. 아래와 같이 될 것 같습니다.

30 카멜레온반지 23

30 카멜레온반지 24

  하지만 위 그림도 아직은 문제가 있어 보입니다. 왜냐하면 스위치가 눌려졌다고 생각하면 위 2개 회로 모두가 +5V와 GND가 직접 연결되는 형상이 되어 버리니까요.

  뿌직~~~ 번쩍! 푸쉬푸쉬~~~

  무엇인가 터지던지… 불꽃이 튀던지… 연기가 나던지… 뭔가 문제가 생길 것 같습니다. 그래서 이런 경우를 방지하기 위한 대비책이 필요한데 이 역할을 수행하는 것은 저항입니다. 아래와 같이 스위치가 눌렸을 때와 눌려지지 않았을 때의 값이 서로 다르게 입력되는 위치에 저항을 달면 문제가 해결되겠습니다. (저항값은 보통 1K~10K 정도를 사용합니다.) 참고로 GND에 저항이 연결되는 것을 풀다운(pull down) 저항이라고 하고, VCC(+5V)에 연결되는 것을 풀업(pull up) 저항이라고 합니다.

30 카멜레온반지 25

 

30 카멜레온반지 26

 

 

  하나 하나 설명하다보니 조금 장황해졌는데요. 어쨌든 이제 연결 방법은 알았으니, 실제로 회로를 아두이노에 연결해 봅시다. 조금 전에 만들었던 카멜레온반지 회로에 스위치 한 개를 추가하여 2번핀(D2)에 연결하는 것으로 하겠습니다. 아래와 같이 되겠네요.

 30 카멜레온반지 27

  오, 그럴듯하게 잘 꾸며진 것 같습니다. 만족? 만족!

 

 

 ■ 신호등 게임기 프로그램 작성                                                  

 

  이제 프로그램을 작성하여야 하는데요. 언제나 마찬가지로 일단 원하는 기능 규격을 작성해 봅시다.

 

[신호등 게임기 기능 규격]

  1. 컬러 LED,의 색깔은 0.1초 마다 빨강 ▶ 노랑 ▶ 파랑 ▶ 빨강 ▶ 노랑 ▶ 파랑… 의 순으로 계속 바뀐다..

  2. 스위치를 누르는 순간 5초 동안만 현재의 LED 색이 유지되었다가 다시 ‘1’번을 수행한다.

 

  컬러 LED의 색깔이 바뀌는 것은 지난번에 했으니까 별 문제가 없을 것이고, 스위치 값을 읽어서 그 값이 0(LOW, 스위치 눌림)인지 1(HIGH, 스위치 눌리지 않음)인지를 검사할 수만 있으면 쉽게 해결될 것 같습니다. 이런 경우에 대비해서 아두이노에서는 digitalRead(pin)라는 기능의 함수를 제공하므로 이것을 이용하도록 합니다.

 

digitalRead(pin)

  ■  pin : 핀 번호

  ■  return 값 : pin을 통하여 들어온 디지털 값으로 0 또는 1

 

  이제 기능 규격을 만족할 수 있는 프로그램의 알고리즘을 만들어 보지요. 아래를 보기 전에 각자 먼저 5분 정도 생각해 보시구요.

… (1분) … (2분) … (3분) … (4분) … (5분)

  아래와 같은 모습이 될 것 같습니다.

30 카멜레온반지 28

  이제 프로그램을 함께 해볼까요?

int SW=2; // #define을 이용해도 되지만 이와 같이 변수로 선언하는 것도 방법

int BLUE_LED=3

int GREEN_LED=5;

int RED_LED=6;

void setup()

{

 pinMode(SW, INPUT); // 2번핀은 스위치 입력

 pinMode(BLUE_LED, OUTPUT); // 3번핀은 파랑 LED 출력

 pinMode(GREEN_LED, OUTPUT); // 5번핀은 녹색 LED 출력

 pinMode(RED_LED, OUTPUT); // 6번핀은 빨강 LED 출력

}

void loop()

{

analogWrite(RED_LED, 255);  analogWrite(GREEN_LED, 0);  analogWrite(BLUE_LED, 0); // 빨강

if (digitalRead() == 0)

   delay(5000); // 스위치를 눌렀으면 5초 대기

else

delay(100); // 스위치를 누르지 않았으면 0.1초만 대기

analogWrite(RED_LED, 255);  analogWrite(GREEN_LED, 255);  analogWrite(BLUE_LED, 0);   // 노랑

if (digitalRead() == 0)

   delay(5000);

else

delay(100);

analogWrite(RED_LED, 0);  analogWrite(GREEN_LED, 0);  analogWrite(BLUE_LED, 255); // 파랑

if (digitalRead() == 0)

   delay(5000);

else

delay(100);

}

  digitalRead()를 수행하여 값이 ‘0’인 상태가 나타나면 스위치가 눌려진 것이니까 그 상태에서 delay(5000); (5초 동안 아무것도 하지 않음)을 수행하게 되므로 LED가 5초 동안 한가지 색깔을 유지하게 됩니다. 자신의 색깔이 결정되는 것이지요.

  작성이 다 되었으면… 컴파일 ▶ 업로드 ▶ 실행! 잘 나오나요?

 30 카멜레온반지 29

  옆에 있는 가족/친구/상사/동료와 간단히 게임 한 번 해 보시지요! 나는 빨강, 상대는 파랑, 야호~ 내가 이겼다. 밥 먹으러 갑시다.

  오늘은 여기까지입니다. 다음 시간에는 FND(Flexible Numeric Display)를 가지고 007 영화에 항상 등장하는 카운트다운 계수기 D.I.Y.에 도전해 보겠습니다. 아래 과제는 짬을 내서 해보시고 다음 강의에서 예쁜 얼굴로 또 만나겠습니다. 감사합니다.

 [과제-빨노파게임기-1]

 스위치를 누르면 ‘1’이 되도록 연결하고 프로그램해 보세요.

 [과제-빨노파게임기-2]

 스위치를 2개 사용하여 더 재미있는 DIY 작품을 만들어 보세요.

 

 

 

아두이노 구매하러 가기 : 클릭!

[58호]자동회전, 자동신고 기능이 있는 소화기 거치대 및 소화기 경보기

58 ict 자동화소화전 (1)

58 ict 자동화소화전 (1)

2019 ICT 융합 프로젝트 공모전 참가상

자동회전, 자동신고 기능이 있는

소화기 거치대 및 소화기 경보기

글 | 전남대학교 이정원, 정수연, 정찬환

1. 심사평
칩센 창의적 발상과 시제품의 제작 완성도가 높아 보입니다. 또한 무선 통신을 통한 경보기와 소화기 거치대간의 효율적 사용 부분도 아이디어가 돋보입니다. 개발 작품에 있어 화재시 소방기관에 알려주는 기능에 있어 설명이 부족하여 이 부분에 대하여 구성을 어떻게 진행한 것인지 궁금증이 남아 있네요. 소화기 거치대의 동작과 관련한 시연 동영상등이 있었으면 더 좋았을듯 합니다.
뉴티씨 평소에 직접 뒤집어서 흔들어주고 했었는데, 이것을 자동으로 해줄수 있다니 참 좋은 아이디어 같습니다. 매우 간단하면서도 좋은 아이템으로, 소방기구로 활용이 될 수 있는 가능성이 매우 높다고 생각되며 각 아파트 단지나, 주요한 건물 등에서도 반드시 구비하였으면 좋겠습니다. 이에 높은 점수를 드립니다.
위드로봇 소화기의 수명 연장을 위해 자동 회전 기능을 구현하였기에 부분을 실용성 측면에서 높은 점수를 부여하였습니다. 반면 구현한 결과에 대한 분석이 보고서에 나타나지 않은 점이 아쉽습니다.
펌테크 단순한 구성이지만 세심한 관찰력이 반영된 실생활과 밀접한 아이디어와 독창성 및 실용성이 아주 뛰어난 작품이라고 생각합니다. 단 일반적인 소화기 무게가 통상 3KG 이상인 점은 감안한다면 이를 감안한 구동모터 선정과 감속기어 박스 구성이 우선적으로 고려되어 할 것으로 판단이 되는데 이 부분은 작품에 반영이 되지 않은 것 같습니다. 또한 제출된 문서 내용을 감안해 볼 때 최종적인 작품의 완성은 되지는 않은 것으로 판단됩니다.

2. 작품 개요
2.1. 발명 목적

58 ict 자동화소화전 (2)

1) 화재에 대한 안전불감증이 만연한 우리 사회에서 안전에 대한 관심도를 높이고자 한다.
2) 화재 발생 시, 원활하게 화재를 진압하고 신속한 초기대응을 통하여 인적·물적 피해를 최소화하고자 한다.
3) 분말소화기의 적절한 보관방법을 사용하여 소화기의 수명을 늘리는 동시에 폐소화기를 줄여 환경 보호에 기여하고자 한다.
4) 분말소화기의 점유율은 71%로 국내 소화기 중 가장 많은 점유율을 차지하고 있으며, 이를 기반으로 한 창업 아이템은 충분히 수요가 있을 것으로 판단한다.

2.2. 발명아이템의 선정동기 및 배경

58 ict 자동화소화전 (3)

분말소화기의 경우 관리방법 중에 ‘한달에 한번 위아래로 흔들어주어야 함.’이라는 항목이 존재한다. 이는 소화 약제가 굳지 않도록 하기 위함인데, 많은 사람들은 이러한 관리방법에 대해 무지하다. 실제로 분말이 굳어 기능을 상실한 소화기 때문에 화재 진압에 어려움을 겪은 수많은 사례는 우리에게 경각심을 일깨워주었다. 한편, 화재 발생 시 골든타임은 5분이며 이후에는 심각한 인명피해와 재산피해가 발생할 수 있다. 실제로 골든타임을 놓쳐 연마다 4000건 이상의 화재가 일어나고 있고, 2000명 이상의 인명피해가 발생하고 있다. 따라서 제대로 된 소화기의 작동과 신속한 119신고를 통한 화재 초기대응의 필요성을 느끼게 되었고, 앞서 언급한 문제점을 해결하기 위해 ‘한달 주기로 분말형 소화기를 섞어주는 장치’와 ‘화재를 인식하여 자동으로 119신고가 이루어지는 시스템’을 접목한 아이템을 구상하게 되었다.

2.3. 발명아이템의 독창성
소방산업의 발전이 정체되어있는 탓에 시장에 유사제품이 존재하지 않다. 잘 인식하지 못하는 부분에서 불편함을 해소해주는 소방 신기술을 갖춘 제품이며, 디자인 측면에서도 우수하다.

3. 작품 설명
3.1. 주요 동작 및 특징

58 ict 자동화소화전 (1)

· 소화기의 수명연장을 위해 1달 주기로 한번씩 자동으로 소화기를 회전 시킨다
· 화재경보기가 감지할 만큼의 큰 불이 나면 소화기 터너와 화재경보기가 상호 블루투스 통신으로 화재를 인지하고 소화기의 위치를 식별시켜줌과 동시에 Telematics기술을 활용하여 가까운 소방기관에 자동으로 신고한다.
· 화재 시 소화기 거치대의 부저, 네오픽셀이 켜져 소화기의 위치를 쉽게 파악할 수 있어서 더 큰 화재로 번지는 것을 막아줄 수 있다.
· 벽걸이형 거치대로 제작하여 장소에 영향을 받지 않고 어디든지 설치가 가능하다.
· 화재경보기와 소화기 거치대가 서로 블루투스 기술을 활용 상호 통신하여 소화기의 위치를 빠르게 식별할 수 있어 빠른 진압이 가능하다.
· 자동회전 기능으로 소화기 분말을 섞어줘 소화기의 수명을 크게 연장시킬 수 있다.
· 화재가 발생하면 자동신고, 수동신고 기능으로 가까운 소방기관에 빠른 신고가 가능해 빠른 진압이 가능하다.

3.2. 전체 시스템 구성
알고리즘

58 ict 자동화소화전 (4)

3.3. 개발 환경
· 개발언어 : C++(아두이노), C#(어플 개발)
· 회로도 소스 개발 Tool : 아두이노
· 어플 개발 Tool : Unity

4. 단계별 제작 과정
4.1. 아이템 기획 및 기획서 작성

4.2. 개발자 소스코딩, 기구제작자 모델링

58 ict 자동화소화전 (2)

4.3. 개발자 회로제작, 기구제작자 모델 조립

58 ict 자동화소화전 (3)

4.4. 디자이너 모델 디자인

58 ict 자동화소화전 (4)

4.5. 소화기 거치대 회로도

58 ict 자동화소화전 (5)

4.6. 소화기 거치대 소스코드

#include <Stepper.h> //스텝모터 라이브러리
#include <SoftwareSerial.h> //블루투스 라이브러리
#include <Adafruit_NeoPixel.h> //네오픽셀 라이브러리 시작
#ifdef __AVR__ //네오픽셀 라이브러리 시작
#include <avr/power.h>
#endif //네오픽셀 라이브러리 끝

#define PIN 6 //네오픽셀 핀번호
#define NUMPIXELS 60 //사용할 네오픽셀 수
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//네오픽셀을 위한 객체 선언

const int stepsPerRevolution = 8; //스텝모터 스텝수
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); //스텝모터 객체선언

SoftwareSerial phoneSerial(4, 5); //핸드폰 Master 블루투스의 Tx. Rx핀을 4번 5번핀으로 설정
SoftwareSerial alarmSerial(2, 3); //화재경보기 Slave 블루투스의 Tx, Rx핀을 2번 3번핀으로 설정

int sirenPin = 13; //부저 핀번호
int buttonPin = 7; //버튼 핀번호
int buttonData; //버튼 데이터
bool motorTrigger = false; //화재, 진압 trigger
char serialData; //통신데이터
int oneTimeFlag = 0;
int oddEvenFlag = 0;

void setup()
{

pinMode(buttonPin, INPUT);
pinMode(sirenPin, OUTPUT);

// 네오픽셀 라이브러리 사용 시작
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
strip.begin();
strip.show();

myStepper.setSpeed(60);

Serial.begin(9600); // 시리얼 통신의 속도를 9600으로 설정
alarmSerial.begin(9600); //거치대 블루투스만 연결
phoneSerial.begin(9600);

}
void loop () {

motorEvenOdd(); //모터회전함수
buttonValue(); //수동신고 함수

//화재, 진압 통신
alarmSerial.listen();
if (alarmSerial.available()) {
serialData = alarmSerial.read();
Serial.write(serialData);
fireAlarmBT(); //블루투스 통신 함수
}

}
void alarmData() { //블루투스 데이터 값 받기
serialData = alarmSerial.read();
Serial.write(serialData);
fireAlarmBT();
}

void fireAlarmBT() { //화재,진압 통신
if (serialData == ‘F’) { //화재시
fireWork();
}
if (serialData == ‘E’) { //진압시
exWrok();
}
oneTimeFlag = 1;
}

void fireWork() { //화재시 행동
motorTrigger = true;
fire();
buzzerOn();
oneTimeFlag = 1;
}
void exWrok() { //진압시 행동
motorTrigger = true;
extinguish();
motorTrigger = false;
oneTimeFlag = 0;
}

void buttonValue() { //수동신고 함수
buttonData = digitalRead(buttonPin);
if (buttonData == HIGH) { //수동신고
delay(500);
motorTrigger = true;
selfFire();
buzzerOn();
}
}
void buzzerOn() { //부저, 네오픽셀 On
theaterChase(strip.Color(0, 255, 0), 0); //네오픽셀, 부저
}
void buzzerOff() { //부저, 네오픽셀 Off
noTone(sirenPin);
}

void theaterChase(uint32_t c, uint8_t wait) { //부저,네오픽셀 On 함수
for (int j = 0; j < 30; j++) {
tone(sirenPin, 262);
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int q = 0; q < 3; q++) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int i = 0; i < strip.numPixels(); i = i + 3) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
strip.setPixelColor(i + q, c); //turn every third pixel on

strip.show();
}
}
}
}

void theaterChase_(uint32_t c, uint8_t wait) { //부저,네오픽셀 Off 함수
for (int q = 0; q < 3; q++) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int i = 0; i < strip.numPixels(); i = i + 3) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
strip.setPixelColor(i + q, 0);
}
strip.show();
}
}

void fire() { //화재함수
phoneSerial.listen();
char data = “화재가 발생하였습니다.”;
phoneSerial.write(data);
}

void selfFire() { //수동 신고 화재
alarmSerial.listen();
char data = ‘f’;
alarmSerial.write(data);
phoneSerial.listen();
char data_ = “화재가 발생하였습니다.”;
phoneSerial.write(data_);
}

void extinguish() { //진압함수
phoneSerial.listen();
char data = “화재가 진압되었습니다.”;
phoneSerial.write(data);
theaterChase_(strip.Color(0, 0, 0), 0); //네오픽셀 끔
buzzerOff();
oneTimeFlag = 0;
}

void motorEvenOdd() { //모터회전
for (int i = 0; i <= 10; i++) {
if(oddEvenFlag == 1)break;
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
oddEvenFlag = 1;
break;
}
myStepper.step(stepsPerRevolution);
}
for (int i = 0; i <= 10; i++) {
if(oddEvenFlag == 1)break;
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
oddEvenFlag = 1;
break;
}
myStepper.step(-stepsPerRevolution);
}
oddEvenFlag = 0;
Serial.println(“bluetooth Ready”);
}

4.7. 화재경보기 회로도

58 ict 자동화소화전 (6)

4.8. 화재경보기 소스코드

#include <SoftwareSerial.h> //블루투스 라이브러리

SoftwareSerial alarmSerial(2, 3); //블루투스의 Tx, Rx핀을 2번 3번핀으로 설정
char serialData; //블루투스 통신 변수
int temSensor = A0; //온도센서 핀번호
int sirenPin = 4; //부저 핀번호

void setup() {
// 시리얼 통신의 속도를 9600으로 설정
Serial.begin(9600);
alarmSerial.begin(9600);
pinMode(temSensor, INPUT);
}

void loop() {

double temValue = 0; //센서 데이터 값 초기화

while (1) //온도가 올라갈 때까지 기다림
{
int readVal = analogRead(temSensor);
double temValue = Thermistor(readVal);
delay(500);

if (temValue >= 50.0) { //큰 화재 발생
break;
}
alarmSerial.listen();
if (alarmSerial.available()) {
Serial.write(alarmSerial.read());
byte serialData = alarmSerial.read();
if (serialData == 255) //수동신고
{
selfFire();
}
}
}
fire();

while (1)
{
int readVal = analogRead(temSensor);
double temValue = Thermistor(readVal);
delay(500);

if (temValue <= 20) { //진압신호 올때까지 기다림
break;
}
}
extinguish();

}

void selfFire() { //수동신고
buzzerOn();
delay(8000);
extinguish();
}

void fire() { //화재 함수
for(int i=0; i < 50; i++){
char data = ‘F’;
alarmSerial.write(data);
}
buzzerOn();
}

void extinguish() { //진압 함수
for(int i =0; i < 50; i++){
char data = ‘E’;
alarmSerial.write(data);
}
buzzerOff();
}

void buzzerOn() { //부저 On
tone(sirenPin, 262);
}

void buzzerOff() { //부저 Off
noTone(sirenPin);
}

double Thermistor(int RawADC) //온도센서 섭씨 변환
{
double temValue;
temValue = log(10000.0 * ((1024.0 / RawADC – 1)));
temValue = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * temValue * temValue )) * temValue );
temValue = temValue – 273.15; // convert from Kelvin to Celsius
return temValue;
}

 

 

 

 

 

[58호]낙상사고자를 살리는 마지막 사이렌, Life Bell

58 ict 라이프벨 (6)

58 ict 라이프벨 (1)

 

2019 ICT 융합 프로젝트 공모전 참가상

낙상사고자를 살리는 마지막 사이렌, Life Bell

글 | 한동대학교 반병우

1. 심사평
칩센 이미 상용화를 준비하고 있는 제품에 대하여 평가를 하는 것이 맞는것인지 모르겠습니다. 개발자께서 이미 사전 조사를 하여 알고 계시겠으나, 금번 개발 작품과 같이 낙상 사고 대비를 위한 제품을 포함하여 Silver care 관련한 수많은 제품들이 준비되고 기획되고 있습니다. 요양병원등과 같은 B2B의 형태도 중요하지만, 지역 기관등을 통하여 선제적인 보급과 스마트폰 뿐이 아닌 여타 기관에서 관리중인 시스템과 연계하는 부분도 검토가 필요하지 않을까 합니다.
뉴티씨 실제로 삶에서 노인들이 낙상하는 경우나 도움이 필요한데 즉시 도움을 주지 않을 경우 사고가 커져 심지어는 사망에 이르게 되는데, 이런 경우에 자동으로 낙상사고를 알려서 즉시 도움을 받을 수 있도록 하는 장치입니다. 매우 실질적인 제품이기에, 상품화하여 모든 노인분들이 착용하면 좋겠습니다.
위드로봇 낙상의 패턴을 분석하는 것이 가장 어려운 부분인데, 이 부분의 추가 연구가 필요합니다.
펌테크 실생활에 사용이 될 수 있는 실용성, 아이디어, 창의성이 돋보이는 작품으로 생각됩니다. 전체 하드웨어 시스템 구성은 비교적 심플한 구성인 반면에 낙상사고를 실질적으로 대비하기에 손색이 없을 정도로 잘 기획된 작품이라고 생각됩니다 다만 작품의 동작 영상을 볼 수 없어 출품작의 최종 완성도를 정확히 판단할 수가 없었습니다.

2. 작품 개요
내가 중학교 때 할머니가 낙상 사고로 돌아가셨다. 더 안타까운 점은 바로 옆방에 내가 있었음에도 대처를 하지 못했다는 점이다. 그리고 이런 슬픈 일이 나의 일만이 아니라는 것을 알게 되었다. 낙상 사고는 우리나라 사고사망원인 2위로 실제로 많은 사람들의 목숨을 위협하고 있다. 하지만 현재 그 어떤 회사도 이를 막을 만한 제품을 만들어 내지 못하고 있다. 이러한 사회적 문제점을 해결하고자 이번 ‘Life Bell’을만 들게 되었다. 낙상 사고를 막기 위해 우리 사회엔 지팡이 등 넘어지지 않기 위한 도구가 이미 존재한다. 하지만 이러한 도구들도 낙상 사고를 막지 못하고 있다. 그래서 우리는 이미 넘어진 후 생존을 위한 도구를 생각하게 되었고, 이를 만들어 보급함으로써 실제로 정말 많은 사람의 생명을 구하고 싶다.

58 ict 라이프벨 (2)

2.1. 아이디어 필요성
고령자의 안전사고는 매년 점점 더 증가하고 있다. 여기서 우리가 눈여겨 볼 점은 그 중 절반 정도(47.4%)가 낙상사고였다는 것이다. 이러한 낙상사고에는 4분이라는 골든 타임이 존재하지만 사고를 당한 노인분들이 이 상황에서 스스로 대처하시거나 주변사람들에게 도움을 청하는 것은 쉽지 않은 현실이다. 그 결과 노인들의 낙상 사고 사망률은 타 연령대의 10배에 달한다. 더 나아가 이미 우리 사회엔 지팡이와 같이 넘어지지 않기 위한 도구가 존재하지만, 이런 도구들도 낙상 사고를 막지 못하고 있다. 그래서 우린 이미 사고가 발생 한 후 생존을 위한 도구를 생각하게 되었다.

2.2. 아이디어 목표
· 정확한 낙상 감지
· 낙상 감지후 신속한 대처 절차

3. 주요 동작 및 특징
3.1. ‘Life Bell’의 기본 동작 및 역할

58 ict 라이프벨 (3)

착용자의 몸의 기울기를 측정하는 기울기 센서, 착용자의 속도 변화량을 감지하는 가속도 센서를 통해 낙상이 감지 되었을 시 어느정도 시간이 지날 때 까지(현재 15초로 지정) 대처가 되지 않았을 경우 기기 자체에서 1차적으로 사이렌을 울린다. 그리고 시간이 더 지날 때까지도 대처가 되지 않을 시엔 보호자에게 현재 위치와 함께 낙상 감지 문자가 보내진다, 그리고 사고 발생 후 30초가 지날 때 까지도 대처 되지 않았을 시 119에 자동 문자 신고가 접수된다.

3.2. 기존 유사 사례 및 차별화 포인트
가. 유사사례

58 ict 라이프벨 (5)

· 기존에 우리와 유사한 제품으론 바이탈밴드와 낙상 폰이 있다. 하지만 두 기기 모두 팔의 궤적으로 낙상을 감지한다. ▶ 어깨가 굳어 팔의 움직임이 자유롭지 못한 노인분들의 낙상은 감지하지 못한다.
· 낙상폰은 40만원 이상, 바이탈밴드는 50만원 이상의 고가로 책정되어 있고 사용법이 너무 어렵다. ▶ 실직적으로 사용하기가 번거롭고 어렵다. 그리고 가격으로 인해 구매하기가 부담스럽다
· 기기 형태가 제한 ▶ 기기 형태가 제한된 웨어러블 디바이스의 가장 큰 특징은 점점 더 사용빈도가 낮아진다는 점이다.

나. 차별점

58 ict 라이프벨 (4)

· 우리가 만든 기기, Life Bell은 몸의 중심축의 기울기 변화를 통해 낙상을 감지한다. ▶ 정말 낙상 여부 감지가 필요한 노인분들의 낙상을 감지할 수 있다.
· 낙상 감지 기능에 집중하여 가격을 크게 낮추었다.
· 기술력을 바탕으로 노인분들이 일상생활에서 사용하는 지팡이, 휠체어, 보행 도구, 자전거, 모자 신발 등에 적용하여 사용할 수 있어서 사용빈도가 줄지 않는다. 그 외 안전사고가 일어날 수 있는 수많은 곳들에 적용할 수 있다.

3.3. 정확한 낙상 감지 방법

58 ict 라이프벨 (6)

그림에서 볼 수 있듯이 앉았을 때와 누웠을 때와는 다르게 넘어졌을 때 기울기의 변화 값이 3배이상 크게 감지되었다. 이 구별 방법을 통해서 낙상을 정확하게 감지 할 수 있었다.

4. 전체 시스템

‘Life Bell’은 크게 감지부, 관제부, 전력 공급부로 이루어져 있다.

58 ict 라이프벨 (7)

4.1. 구성품

58 ict 라이프벨 (8)

58 ict 라이프벨 (9)

4.2. 구성요소
· 감지부 : mpu6050 기울기센서와 가속도 센서를 통해 이상 움직임을 감지한다. 기울기 센서는 착용자의 몸의 중심축의 기울기 변화를 측정하고, 가속도 센서는 착용자의 몸의 속도 변화를 감지한다. 이 2가지 변수로 낙상을 정확하게 감지한다.
· 관제부 : 사이렌과 통신부로 이루어져 있고, 이곳에서는 위급한 상황이 유지될 시 사이렌을 울리고, 블루투스 통신을 어플리케이션을 통해 문자 기능과 GPS기능을 활성화시켜 보호자과 119에 현재 상황과 위치를 알린다.
· 전력 공급부 : 감지부와 관제부가 역할을 잘 할 수 있도록 전력을 공급하여 준다.

4.3. 개발환경

58 ict 라이프벨 (10)

‘Life Bell’의 기기는 아두이노 나노를 기반으로 PCB를 제작하였으며, 모든 명령어 및 코드는 C언어로 코딩되어 있다. 또한 ‘Life Bell’ 어플리케이션은 자바 이클립스로 코딩을 하여 제작을 하였다.

5. 로드맵

58 ict 라이프벨 (11)

우리는 기술의 유효성, 실효성, 시장성을 인정받아 특허를 등록하였고, 이 기술을 바탕으로 프로토타입을 개발하였다. 그리고 현재는 한동대학교 IDEA 랩실에 지원을 받아 제품의 소형화 단계에 있다. 그리고 제품의 소형화 후 병원, 요양원 등 시설과 B2B마케팅을 통해 시장에진입할 것이고, 그 후엔 보험사, 일인 이용 수단 회사들과 콜라보레이션 마케팅을 통해 시장을 더더욱 확대해 나갈 것이다.

6. 기타

58 ict 라이프벨 (12)

6.1. 기기 소스코드

라이브러리 선언 및 함수 정의
// 라이브러리 선언
#include <Wire.h> // I2C통신 설정 – 가속도 측정하기 위함
#include “MPU6050.h” // 가속도 라이브러리 선언(가속도 측정 관련 라이브러리)
#include <SoftwareSerial.h> // 소프트 시리얼 라이브러리 선언(블루투스 통신하기 위함)

// 핀 번호 설정
#define BUZZER 7 // 부저 핀 번호
#define RESET 4 // 가속도센서(mpu6050) RESET 핀 번호
int TxPin = 5; // 블루투스 통신 TX단자
int RxPin = 6; // 블루투스 통신 RX단자
SoftwareSerial BTSerial(TxPin, RxPin);

// (중요)(중요)
int NOMAL_ANGLE = 20; // 정상기울기 범위, 기울기가 ‘NOMAL_ANGLE’ 안에 들어 올 경우 정상처리
long CRASH_VALUE = 700; // 충돌 값(충돌 판단하는 값, 가속도 변화량 값)

// 구동 변수
long ac_x, ac_y, ac_z, gy_x, gy_y, gy_z ; //acc, gyro data (acc, gyro 계산 수식)
double angle1 = 0, deg ; // angle, deg data (각도계산)
double angle2 = 0;
double dgy_x ;
long mapping_value = 1000;
long normal_x,normal_y,normal_z, deltha_x[3],deltha_y[3],deltha_z[3], deltha, angle_1[3], angle_2[3] ;
long event_value = 1000;

// 처리 변수
const int delay_main = 1; // 전체 시스템 구동하는 데, 걸리는 시간 (즉 구동 시간)이다. (ex) 1000 = 1000ms = 1s = 1초
const int sum_count = 4;
long delay_config = 6000; // 이벤트 발생 후 딜레이
boolean ACCESS_ACCEL = false;
long TIEMR_BLESEND = 0;
bool WARN_STATE = false;
long TIMER_WARN_STATE = 0;
bool buzzer_state2 = true;

// 함수 선언
int ACTION_config();
void value_init();

통신 설정
void setup() {

// 시리얼통신 & 소프트시리얼 통신 설정
Serial.begin(115200); BTSerial.begin(9600);

// 핀모드 및 초기 설정
pinMode(BUZZER, OUTPUT);pinMode(RESET, OUTPUT); // 출력으로 사용
tone(BUZZER, 1000, 100); delay(200); tone(BUZZER, 1000, 100); // 부저 울리기
digitalWrite(RESET, LOW); // RESET 초기화

// 가속도 센서 설정
delay(100);
mpu6050_init(); // 가속도 센서 초기 설정
ACCESS_ACCEL = ACCEL_ACCESS(); // 가속도 센서 값 맞게 나오는지 확인하기
}

블루투스 통신
void loop() {

// 1. 정해진 시간마다 블루투스 통신으로 ‘a’값 보내기 (부팅 되었는지 확인하기 위해)
if(TIEMR_BLESEND < millis()){
BTSerial.print(“a”); // 블루투스 데이터 보내기
TIEMR_BLESEND = millis() + 10000; // 10초 간격으로 데이터 보내기
}

// 2. 블루투스 데이터 감지하기
if (BTSerial.available()){ // 블루투스 데이터를 감지했을 경우 안에 while문이 동작함
int timeout = 50;
String response = “”; long int time = millis();
while( (time+timeout) > millis()) { // 50ms동안 문자열 세는 방식
while(BTSerial.available()) { // 블루투스 통신이 끝날 때 까지
char c = BTSerial.read(); // c에 읽어 response에 저장
response+=c; }}

String DATA = response; // 컨트롤 데이터에 읽은 데이터 넣기
Serial.println( “DATA : “ + DATA); // 컨트롤 데이터 출력

if(DATA.substring(0,2) == “HI”){ // 블루투스 데이터가 “HI”인가? 그럼 ‘a’데이터 보내기
BTSerial.print(“a”);
}
}

[비상모드] 비상모드에서 정상상태로 돌아가는지 확인하기
if(WARN_STATE){

// 0.5초마다 확인 하기
if(TIMER_WARN_STATE < millis()) { TIMER_WARN_STATE = millis() + 100;

// 0.5초 마다 부저 키고 끄기 (띠띠띠 소리 내기)
if(buzzer_state2) { tone(BUZZER, 1000); buzzer_state2 = false; } else { noTone(BUZZER); buzzer_state2 = true;}

// 각도 측정하기
value_init(); // 변수 초기화
accel_calculate(); // 가속도 측정 -> 각도계산
angle1 = abs(angle1); // 각도 변수에 저장
angle2 = abs(angle2); // 각도 변수에 저장

// Serial.print( “ ANGLE1 : “ + String(angle1)); Serial.println( “ ANGLE2 : “ + String(angle2));

if ( (angle1 < NOMAL_ANGLE ) && (angle2 < NOMAL_ANGLE ) ){ // 정상 상태에 돌아왔을 경우 (각도가 안정상태일 경우)

noTone(BUZZER); // 부저 끄기
WARN_STATE = false; // 비상모드 끄기
BTSerial.print(“x”); // 블루투스 데이터 ‘x’보내기

가속도 변화량(충격량) 감지하기
value_init();
//첫번째 센싱
for (int i=0; i < sum_count; i++){ accel_calculate();
deltha_x[1] = deltha_x[1]+(normal_x); deltha_y[1] = deltha_y[1]+(normal_y); deltha_z[1] = deltha_z[1]+(normal_z); delay(5);}
deltha_x[1] = int(deltha_x[1]/sum_count); deltha_y[1] = int(deltha_y[1]/sum_count); deltha_z[1] = int(deltha_z[1]/sum_count);

//두번째 센싱
for (int i=0; i < sum_count; i++){ accel_calculate();
deltha_x[2] = deltha_x[2]+(normal_x); deltha_y[2] = deltha_y[2]+(normal_y); deltha_z[2] = deltha_z[2]+(normal_z); delay(5);}
deltha_x[2] = int(deltha_x[2]/sum_count); deltha_y[2] = int(deltha_y[2]/sum_count); deltha_z[2] = int(deltha_z[2]/sum_count); //3축 변화량 비교가속도 변화량 측정하기
deltha_x[0] = abs(deltha_x[1]-deltha_x[2]); deltha_y[0] = abs(deltha_y[1]-deltha_y[2]); deltha_z[0] = abs(deltha_z[1]-deltha_z[2]);
deltha = deltha_x[0] + deltha_y[0] + deltha_z[0];

가속도 변화량 비교를 통한 낙상 감지
if(deltha > CRASH_VALUE){ // 충격이 감지 되었을 경우 내부 함수 동작하기
ACTION_config(); // 기울기를 통해 비상모드인지 판단함
}

< 비상모드 시 사이렌 알람과 블루투스를 통해 이뤄지는 통신 부분>
// 비상모드인지 판단하는 함수
int ACTION_config(){

tone(BUZZER, 1000,1000); // 부저 키기
delay(3000); // 3초간 대기
long TIMER1 = (long) millis() + 12000; // 12초간 대기하는 구간
long TIMER_buzzer = 0; bool buzzer_state = true;
int WARN = 0;
// 시작 Flow chart
// 충격감지(가속도변화감지) -> 3초간 대기 -> 12초간 기울기 감지

// 비상모드 인가? 정상모드 인가? 판단하기
while( (TIMER1 > millis())&&(WARN == 0)){

// 부저 울리기 : 띠띠띠
// if(TIMER_buzzer < millis()) { TIMER_buzzer = millis() + 500;
// if(buzzer_state) { tone(BUZZER, 1000); buzzer_state = false; } else { noTone(BUZZER); buzzer_state = true;}
// }

// 각도 측정하기
value_init(); accel_calculate();
angle1 = abs(angle1);
angle2 = abs(angle2);

// 정해진 각도 내에 들어가는지 확인하기 (12초 내의 정해진 각도에 들어 갈 경우 정상임)
if ( (angle1 < NOMAL_ANGLE ) && (angle2 < NOMAL_ANGLE ) ){
// tone(BUZZER, 1000, 100); delay(200); tone(BUZZER, 1000, 100);
noTone(BUZZER); WARN = 1; // WARN = 1이면 while에 나갈 수 있음
}

Serial.print( “ ANGLE1 : “ + String(angle1)); Serial.println( “ ANGLE2 : “ + String(angle2));
delay(100);
}
//—————————————//

// 정상 일 경우 return 시키기
if(WARN == 1) { return 0; }

// 비상모드 일 경우 부저 6초간 울리고 블루투스 데이터 보내기
TIMER1 = (long) millis() + 6000;
while( TIMER1 > millis() ){
tone(BUZZER, 1000); delay(100); noTone(BUZZER); delay(100);
}
noTone(BUZZER);
BTSerial.print(“w”); // ‘w’ 블루투스데이터 보내기

가속도 연산 및 각도 계산 함수
void accel_calculate() {

ac_x = 0; ac_y = 0; ac_z = 0;

Wire.beginTransmission(mpu_add) ; // 번지수 찾기
Wire.write(0x3B) ; // 가속도 데이터 보내달라고 컨트롤 신호 보내기
Wire.endTransmission(false) ; // 기달리고,
Wire.requestFrom(mpu_add, 6, true) ; // 데이터를 받아 처리

// Data SHIFT
ac_x = Wire.read() << 8 | Wire.read() ;
ac_y = Wire.read() << 8 | Wire.read() ;
ac_z = Wire.read() << 8 | Wire.read() ;

// Serial.println( “ X : “ + String(ac_x) + “ Y : “ + String(ac_y) + “ Z : “ + String(ac_z) );
if(ACCESS_ACCEL) { } else { return; }

//맵핑화 시킨 것 – 즉 10000으로 맵핑시킴
normal_x = map(int(ac_x), -16384, 16384, 0, mapping_value);
normal_y = map(int(ac_y), -16384, 16384, 0, mapping_value);
normal_z = map(int(ac_z), -16384, 16384, 0, mapping_value);

float accel_xz, accel_yz;
const float RADIANS_TO_DEGREES = 180/3.14159;

// 각도1 계산하기
accel_yz = sqrt(pow(ac_x, 2) + pow(ac_y, 2));
angle1 = atan(-ac_z / accel_yz)*RADIANS_TO_DEGREES;

// 각도2 계산하기
accel_xz = sqrt(pow(ac_z, 2) + pow(ac_y, 2));

에러를 줄이기 위한 변수 초기화
void value_init(){
normal_x = 0; normal_x = 0; normal_x = 0;
for (int i=0; i < 3; i++){ deltha_x[i]=0; deltha_y[i]=0; deltha_z[i] = 0; angle1 = 0;angle2 = 0; }

 

 

[58호]Battleship 2인용 게임기

58 ict 배틀쉽 (5)

58 ict 배틀쉽 (15)

2019 ICT 융합 프로젝트 공모전 참가상

Battleship 2인용 게임기

글 | 국민대학교 오재홍, 이강민

1. 심사평
칩센 보드게임을 디지털화하였다는 것에서 재미있는 발상이라 생각합니다. 하드웨어 구성에 있어서 게임기 조작부는 기성 조이스틱 등을 사용하여 조금 더 심플한 방법을 추구하고, Display 부분에 dot/character 보다 더 유려한 형태의 구성으로 했다면 재미있어 보이지 않았을까 합니다. 모듈 문제로 적용하지 못한 블루투스 기능 또한 아쉬움으로 남습니다.
뉴티씨 한때 유행하던 8비트 임베디드 게임기를 상상하게 만든 작품이었습니다. 실제로 블루투스를 넣어서 서로 통신하여 게임할 수 있도록 된 점도 잘된 점이라고 생각합니다. 다만, 스마트폰을 LCD 표현용으로 사용하고 스마트폰과 연결하여 게임기로 쓸 수 있도록 하였다면, 보조장치로 더 좋지 않을까 생각합니다.
위드로봇 보드 게임을 임베디드 시스템으로 구현한 부분이 재미있는 작품입니다.
펌테크 과거 오락실 게임을 연상시키는 흥미로운 작품이라고 생각합니다. 단순해 보이지만 프로그래밍 과정을 통해 게임 구성에 관한 Algorithm 구현, GLCD를 통한 상태 표시 등은 기술적 구현이 쉽지는 않았을 것으로 예상됩니다. 비록 2대의 게임기기 상호 간 무선통신을 통한 구현을 최종 완성시키지 못했지만 유선상의 구현만으로도 충분히 가치가 있는 작품이라고 생각합니다.

2. 작품 개요
· 2대의 ATmega128을 이용한 유선 통신 기능 구현
· 기존의 종이나 장난감으로 하는 보드게임을 디지털화하여 시중에서 판매되는 게임기와 비슷한 외형의 디지털 게임기 제작

3. 작품 설명

58 ict 배틀쉽 (1)

이 작품은 battleship 보드게임 원리에 착안해 만들었다. 기존의 battleship 보드게임은 10×10의 보드에서 이루어지고, 우선 각자 자신의 보드에 각각 크기가 5,4,3,3,2인 다섯 개의 배(종류는 4종류, 각각 Aircraft(크기 5), Battleship(크기 4), Cruiser(크기 3), Destroyer(크기 2))를 가로 혹은 세로로 겹치지 않게 배열한다. 그리고 서로 돌아가며 상대의 배의 위치를 추측한다. 한 번씩 돌아가며 상대의 배가 있을 걸로 예상되는 위치(게임 보드 위의 한 점)를 지목한 뒤, 그 결과를 듣고 다시 그 결과를 바탕으로 추측하여 먼저 상대의 배가 있는 위치를 모두 맞춘 쪽이 승리하는 게임이다. 이 작품은 기존 battleship 보드게임과 달리 상대방의 5칸 크기의 배를 파괴하거나 5칸 크기의 배가 아닌 배를 3척 파괴하는 것이 승리조건이다.

58 ict 배틀쉽 (2)
차이점은 이 작품에서는 크기가 5,4,3,2인 배가 있고 한 칸 크기의 함정이 있다는 것이다. 이 함정은 배와 겹치지 않게 배열하고 상대방이 함정을 공격했을 때 배를 공격했다고 착각하게 만드는 역할을 하여 배의 모양을 쉽게 예측하지 못하게 만들었다는 것이다. 마지막으로 스캔 기능이 추가되었다. 자신이 공격에 성공한 배가 어떤 배인지 알기 위한 기회가 3번이 주어진다. 자신의 공격 턴에 지정한 좌표에 스캔 버튼을 누르면 배의 종류를 알려준다.
이러한 게임 규칙의 변화, 아이템 사용 효과 추가, 아날로그 게임의 디지털화를 통해서 기존 battleship 보드게임에서 보다 더 재미의 요소를 추가하였다.

3.1. 주요 동작 및 특징
가. 스위치 동작

58 ict 배틀쉽 (1)
(1) 리셋 스위치
(2) 상하좌우 스위치
(3) 포격/확인 스위치
(4) 회전/스캔 스위치

나. 게임 진행 순서

58 ict 배틀쉽 (3)

① 게임기 상단에 부착된 스위치를 이용해 각자의 배 배치를 완료한다.

58 ict 배틀쉽 (4)

② 배 배치가 완료된 후 한 사람씩 공격을 하게 되는데 상대방의 배 위치를 맞췄을 때는 X표시가 되며 한 번 더 차례를 진행하고 공격에 실패했을 때는 *표시가 되며 상대방의 턴으로 넘어간다. 특정 알파벳 배의 모양을 완전히 파괴하게 되면 화면 하단에 있는 알파벳 현황판 숫자가 달라진다.

58 ict 배틀쉽 (2)

③ 게임기 스위치 좌측 상단에 LED는 자신의 턴일 때는 초록색, 상대방의 턴일 때는 빨간색에 불이 들어온다.

58 ict 배틀쉽 (3)

④ 공격 시 파란색 버튼을 이용하여 스캔 기능을 사용함으로써 상대방 특정 위치의 배 종류를 알 수 있다. 스캔 기능은 각 플레이어에게 3번의 사용 기회가 주어진다.

58 ict 배틀쉽 (5)

 

 

58 ict 배틀쉽 (6)

 

⑤ 게임 진행 중 승리조건이 달성되면 승리 문구가 표시되고 흰색 버튼을 눌러 새로운 게임을 시작할 수 있다.

3.2. 전체 시스템 구성
가. 스위치 구성

58 ict 배틀쉽 (7) 58 ict 배틀쉽 (8)

한 대의 게임기 안에 있는 7개 스위치는 모두 풀업 저항 회로로 구성되어 있고 스위치를 누를 때 연결된 포트의 HIGH 신호를 LOW 신호로 바꾸어 입력 신호를 변경한다. 스위치는 모두 폴링(Polling)방식으로 동작되며 RESET 단자에 연결된 스위치를 제외한 나머지는 모두 PORTD에 연결하였다.

나. 사운드

58 ict 배틀쉽 (9)

게임의 효과음은 전기 신호를 소리로 변환시켜 주는 부저(Buzzer)를 통해서 제작하였다.
부저에는 내부에 전자석과 진동을 일으키는 판으로 이루어져 있으며, 전자석이 진동판을 아주 빠르게 흔들어 소리를 발생 시키는 원리를 가지고 있어 타이머/카운터를 이용하여 주파수를 정해주어 소리를 발생시켰다.
하나의 효과음은 여러 가지 주파수의 배열로 만들었고 타이머/카운터 레지스터를 조절하는 함수의 인자로 사용하였다.

다. 통신 방법

58 ict 배틀쉽 (10)

게임기의 통신은 USART(Universal Synchronous and Asynchronous Receive and Transmitter) 통신 방식을 사용한다. USART 통신을 하기 위해서 2대의 ATmega128 Tx/Rx 포트를 서로 교차하여 선을 연결하고 양쪽 ATmega128 모두 송수신 속도, 전송 문자의 데이터 비트수 등 데이터를 송수신 하는데 필요한 레지스터들을 동일하게 설정한다.
정보를 보낼 때 UDR0에 데이터를 넣어 인터럽트를 발생시키고 그 데이터를 받을 때는 미리 선언한 flag 값만 변경시켜 인터럽트를 통해 실시간으로 정보를 주고받는다.

라. 배터리

58 ict 배틀쉽 (4)

게임기의 GLCD 백라이트와 부저에 전원을 공급하기 위해서 약 5V의 전압이 필요하다. 따라서 게임기의 하단부에 AA배터리 소켓을 4개 부착하였고 1.5V AA건전지 4개를 직렬 연결하여 총 6V의 전압을 공급할 수 있도록 설계하였다.

마. 게임 알고리즘

58 ict 배틀쉽 (11)

3.3. 개발 환경(개발 언어, Tool, 사용 시스템 등)

58 ict 배틀쉽 (12)

4. 단계별 제작 과정
4.1. 코드 제작

58 ict 배틀쉽 (13)

① Visual Studio와 Code Vision AVR 모두 C언어를 기반으로 한 플랫폼이기 때문에 먼저 Visual Studio로 게임 알고리즘을 제작한 후 Code Vision AVR에 부합하는 코드로 변환하여 GLCD에 영상을 띄웠다.

58 ict 배틀쉽 (5)

② ATmega128간의 USART 유선통신의 데이터 송수신을 간단한 스위치 동작으로 확인하였다.

4.2. 하드웨어 제작

58 ict 배틀쉽 (6)

① 스위치와 리드선을 글루건으로 고정시키고 스티로폼에 스위치만 보이게 하여 실제 게임기 스위치 같은 외형을 제작하였다.

58 ict 배틀쉽 (14)

② 아크릴판으로 틀을 제작하고 게임기의 윗면에 GLCD와 스위치를 아랫면에는 ATmega128, 부저, 브레드보드를 위치시켰다.

58 ict 배틀쉽 (7)

③ 2대의 게임기를 붙여 게임기 하단에 배터리를 넣으면 게임이 작동하도록 제작하였다.

5. 기타
5.1. 소스코드
가. 배 배치 알고리즘

void print_ship(int x, int y, int ship_length, char ship_name)
{
if(turn==0)
for (i = 0; i < ship_length; i++)
board_char[y][x+i] = ship_name;

else
{
for (i = 0; i < ship_length; i++)
board_char[y+i][x] = ship_name;
}
}

print_ship 함수는 x,y 좌표, 배의 길이, 배 이름을 인수로 받아 전역변수 turn이 0이면
배의 이름을 board_char 배열에 가로로 넣고 turn이 1이면 board_char 배열에 세로로 넣는다.

void MapDraw(void)
{
for(i = 0; i < 10; i++)
{
for(j = 0; j <10; j++)
{
GLCD_TextGoTo(i,j);
GLCD_WriteChar(board_char[j][i]);
}
}
}

MapDraw 함수는 board_char 배열에 저장된 데이터를 GLCD에 찍어주는 역할을 한다.

switch(PIND)
{
case 0xfd: // 아래로 움직이는 키를 눌렀을 때 (PORTD1)
if (turn == 0 && player_y != 9)
{
player_x+=0; player_y+=1;
_delay_ms(3000);
}
if (turn == 1)
{
if(board_char[player_y + ship_length][9] == ‘.’){
player_x+=0; player_y+=1;
_delay_ms(3000);
}
}

배를 이동하기 코드의 일부를 발췌한 부분이다.
turn이 0이면 배가 가로로 되어있는 상태이고 1이면 세로로 되어있는 상태이기 때문에 turn이 0이고 y좌표가 (x,9) 가 아닌 경우에 한 칸 내려갈 수 있고,
turn이 1이고 y좌표와 배의 길이를 더한 좌표에 있는 문자가. 맵의 기본 모양이라면 한 칸 내려갈 수 있기 때문에 y좌표에 1을 더해주었다. GLCD의 좌표는 첫 번째 줄의 y좌표는 0이고 아래로 내려갈수록 +1씩 된다.

void enter_ship(int x, int y, int ship_length, char ship_name)
{
if (turn == 0)
for (i = 0; i<ship_length; i++)
{
grid[y][x + i] = ship_name;
}
else
for (i = 0; i<ship_length; i++)
{
grid[y + i][x] = ship_name;
}
placement_cnt++;
enter_cnt++;
}

enter_ship 함수는 turn의 값을 통해 배의 방향을 판단하고 반복문을 이용해 grid 배열에 배치할 배의 이름을 넣어주는 함수이다.

void erase_ship(int x, int y, int ship_length)
{
if (turn == 0)
for (i = 0; i < ship_length; i++)
board_char[y][x + i] = grid[y][x + i];

else
for (i = 0; i < ship_length; i++)
board_char[y + i][x] = grid[y + i][x];
}

erase_ship 함수는 x,y 좌표, 배의 길이를 인수로 받아 board_char 배열에 grid 배열을 넣어준다. 이 함수는 좌표값을 이동시켰을 때 이전에 print_ship 함수로 board_char 배열에 넣어주어 Mapdraw 함수로 GLCD에 배열을 표현했을 때 잔상이 남는 것을 지워주는 역할을 한다. board_char 배열에 넣어주는 grid 함수는 배를 배치했을 때 배열 안에 값이 저장된다.

while(1)
{
print_ship
-> MapDraw
-> swich case 문을 이용하여 버튼 눌렀을 때 좌표 이동 및 배 배치
-> erase_ship
}

나. 부저 사운드 함수

float start3[]= {329.6, 329.6, 329.6, 293.7, 329.6, 0, 329.6, 329.6 ,329.6, 293.7, 392.0, 349.2, 329.6,-1}; // start 사운드
float end_win[] = {261.6, 329.6, 392.0, 523.3, -1}; // 승리 사운드
float end_lose[] = {277.2, 261.6, 246.9, 223.1,-1}; // 패배 사운드
float fire[]= {261.6, -1}; // 포격 성공 사운드
float wrecked[] = {130.8, 123.5, -1}; // 침몰사운드
float miss[] = {392.0 ,-1}; // miss 사운드
float scan2[] = {440.0, -1}; // scan 사운드
void Buzzer(float arr[])
{
int i = 0;
DDRB |=(1<<DDB4); //5번 핀으로 소리 출력
TCCR0 = 0x1D;
TCCR1A = 0×00;
TCCR1B = 0×04;
TCNT0 = 0;
TCNT1 = 65536 – 55000;

while(arr[i] != -1)
{
OCR0 = (int)(8000000/(arr[i]*256));
while((TIFR & 0×04) == 0);
TIFR |= 0×04;
TCNT1 = 61250;
//=====================
OCR0 = 0;
while((TIFR & 0×04) == 0);
TIFR |= 0×04;
TCNT1 = 55000;
i++;
}
TCCR0 = 0;
}

타이머/카운터 레지스터를 설정하고 while문의 인자에는 arr[i] 배열의 인자(주파수)를 하나씩 실행 시키는데 -1이 나오면 효과음이 끝나도록 설정 하였고 하나의 효과음이 모두 나온 후에 다음 동작(화면이 바뀌거나 스위치를 작동하는 행위)이 실행된다.
빠른 게임 진행을 위해서 게임 시작, 게임 종료를 나타내는 효과음 이외의 배열(arr[i])의 길이를 짧게 설정하였다.

다. 통신 방법

void Init_interrupt_usart(void) // 인터럽트 레지스터 설정
{
UCSR0A = 0×00;
UCSR0C = 0×06;
UCSR0B = 0xd8; // 1101 1000

UBRR0H = 0×00;
UBRR0L = 0×07; // 115200bps
SREG|=0×80;
}
ISR(USART0_TX_vect) // led 제어, 끝나는거 제어
{
tx_done=0;
}

ISR(USART0_RX_vect)
{
data = UDR0;

if(data==1) ////////////////////////
led_turn=1;
if(data==0) ////////////////////////
led_turn=0;

if(data==Game_set)
{
end_flag=1;
loss_cnt++;
}
if(data == re_game)
re_game_flag2=1;

if(data == C_zero)
C_zero_flag=1;

if(data == B_zero)
B_zero_flag=1;

if(data == S_zero)
S_zero_flag=1;

if(data == M_zero)
M_zero_flag=1;

if(data == D_zero)
D_zero_flag=1;
}

인터럽트 ISR(USART0_TX_vect)은 메인문에서 UDR0 값을 넣어줬을 때 tx_done=0 으로 만들면서 ISR을 빠져나가게 되면서 while(tx_done);을 다음 코드로 진행할 수 있게 구성하였다.
인터럽트 ISR(USART0_TX_vect)에서 정보는 최소화 하였고 보내는데 필요한 정보들은 flag 변수를 이용하여 주로 처리하였다.
인터럽트 ISR(USART0_RX_vect)은 UDR0 값을 받아 변수 data에 저장 후 필요한 flag를 1로 set 하는 용도로 쓰였다.

5.2. 아쉬운 점
블루투스 페어링(pairing) 오류

58 ict 배틀쉽 (8)

기존 작품 설계 방향은 무선통신을 이용한 2인용 게임기를 만드는 것 이 목표였기 때문에 아두이노를 이용하여 블루투스를 페어링 하려 했지만 블루투스 모듈 문제로 페어링이 되지 않아 유선통신을 하게 되었다. 그림은 블루투스 모듈인 hc-05와 hc-06을 페어링 하고 있는 모습이다.

휴대하기에는 큰 부피
기존에 보유하고 있던 큰 크기의 브레드보드를 기준으로 회로를 설계하고 게임기 외형을 제작하였기 때문에 휴대하기에는 큰 부피로 작품이 제작되었다.

시간제한 기능 미사용
타이머 인터럽트를 사용해서 사용자가 공격하는데 30초의 시간제한을 두려 하였지만 여러 개의 인터럽트를 동시에 사용하여 충돌이 생겨 타이머가 제대로 작동하지 않았다.
아래 내용은 타이머 인터럽트만을 사용하여 GLCD에 30초 타이머 기능을 구현한 코드와 코드의 설명이다.

ISR(TIMER0_COMP_vect) // 타이머 ISR (30초 카운트)
{
total_count++;
if ( total_count == 1000 ) // total_cound는 1ms
{
if(++sec_first>9){ s=0; // 1초 단위
if(++sec_second>2){ s1=0; //10초 단위
}
}
//sec_first와 sec_second는 전역변수
GLCD_TextGoTo(2,1); GLCD_WriteChar(sec_first+’0’); // GLCD에 1초 단위 표기
GLCD_TextGoTo(1,1); GLCD_WriteChar(sec_second+’0’); // GLCD에 10초단위 표기
_delay_ms(1);

total_count = 0;
}
}

void Init_Timer(void) // 타이머/카운터0 레지스터 설정을 통한 타이머 Init
{
TCCR0 |= (1<<CS02); // 프리스케일러로 64를 선택
TCCR0 |= (1<<WGM01); // CTC 모드
TCNT0 = 0; // 카운터 초기화
OCR0 = 249; // TOP 정의
TIMSK |= (1<<OCIE0); // 타이머/카운터0 Compare Match 인터럽트 활성화
sei(); // 전역 인터럽트 활성화
total_count = 0; // total_count 초기화
}

void Quit_Timer(void) // Timer 레지스터 설정을 통한 Timer Quit
{
TIMSK = 0×00; // 타이머/카운터의 interrupt를 비활성화
sec_first = 0; // sec_first를 초기화
sec_second = 0; // sec_second를 초기화
total_count = 0; // total_count를 초기화
}

타이머 기능: Init_Timer에서 타이머/카운터0의 레지스터 설정을 통해 1ms마다 total_count가 1씩 증가하는 타이머를 만들었다. 각 레지스터의 설정은 다음과 같다. Init_Timer함수의 주석을 통해서 설명되어 있다.
Init_Timer를 통해서 타이머/카운터0이 활성화 되면 TCNT가 OCR과 같아지는 순간 타이머0 ISR(TIMER0_COMP_vect)로 진입하여total_count가 1ms마다 증가하며, total_count가 1000이 되는 순간 sec_first를 1씩 증가시킨다. sec_fisrt가 10이 되는순간 sec_first는 0으로 초기화되고, sec_second가 1씩 증가한다. sec_second가 3이되는 순간 sec_second는 0으로 초기화 된다.
코드를 통해, 위 내용을 확인할 수 있으며, sec_first와 sec_second는 각각 1초 단위 10초 단위를 의미한다.
종합 의견 : 완성된 작품에서 무선통신과 타이머 기능을 추가하고 작은 크기의 브레드보드를 사용하여 외형을 제작한다면 보다 편리하고 직관적인 게임기의 기능을 갖추게 될 것이다.

5.3. 참고문헌
· 뉴티씨 (newtc) : http://www.newtc.co.kr/dpshop/bbs/board.php?bo_table=m41&wr_id=745&page=5
· 인터럽트 레지스터 설정 : https://webnautes.tistory.com/984
· USART 통신 : https://blog.naver.com/xisaturn/220750649418
· 그림 1,2 battleship 보드게임 예시 : https://en.wikipedia.org/wiki/Battleship_(game)
· 그림 3. ATmega128 data sheet : http://www.siphec.com/item/AVR-ATmega128-ATmega1281-ATmega2561.html
· 그림 6. 주파수와 피에조 부저의 음계 : https://kocoafab.cc/tutorial/view/626
· 그림 7. ATmega USART Tx/Rx 연결 회로도 : https://blog.naver.com/iintuition_/220587315291

 

 

 

 

[58호]2019 한국산업대전

58 hot 한국산업대전 (1)

58 hot 한국산업대전 (1)

2019 한국산업대전

한국기계전 KOMAF / 제조 IT서비스전 MACHINESOFT

 

글 | 박진아 기자 jin@ntrex.co.kr

 

5회째를 맞이한 이번 한국산업대전은 42년의 역사를 보유한 한국기계전(KOMAF)과 제조 IT서비스전 머신소프트(MachineSoft) 2019를 함께 개최한 국내 최대 규모의 산업 융합 박람회로 지난 10월, 3일에 걸쳐 일산 킨텍스에서 열렸다. 산업통상자원부가 주최하고 한국기계산업진흥회가 주관하는 이번 전시회에는 국내 주요 기업뿐만 아니라 미국, 독일, 중국 등 전세계 27개국, 752개사가 참여하였고, 공작, 건설기계, 발전기자재등 전통적 기계류와 AI, 5G 등 IT 서비스 기술 등 1,400여 품목이 전시되었다.

58 hot 한국산업대전 (1)

두산 로보틱스에서는 다섯 대의 협동 로봇이 작업자와 함께 산업용 수소 드론을 조립하는 모습을 시연하며 실제 산업현장에 적용되고 있는 공정을 선보였다. 점차 발전되는 기술에 따라 산업용 로봇은 사람의 손처럼 민감한 작업도 맡아서 진행해야 하기 때문에 두산 로보틱스에서는 이 부분에 특화된 프리미엄 협동 로봇 제작에 집중하였다. 그 결과 협동 로봇 시리즈는 민감한 힘도 쉽게 감지할 수 있는 조인트토크센서가 부착돼 섬세한 작업이 가능해졌으며, 그 외에도 다양한 기능을 추가하여 성능 및 생산 효율성을 극대화하였다.
이런 협동 로봇을 알아보자면 M0609은 제한된 공간에서 고속으로 반복적인 작업을 수행하도록 최적화되어 설계되었고, M1509는 작업자를 지원하기 위해 무거운 물체를 다루는데 효과적이며, M1013은 모든 응용 분야에 적합한 표준모델 M1013과 여러 작업 또는 장거리 작업에 이상적인 M0617 협동 로봇으로 제작되어 사용자의 필요한 환경에 맞게 활용할 수 있다.

58 hot 한국산업대전 (2)

국내 소형 정밀 Motor 산업의 선두주자 인아오리엔탈모터에서는 소형화 전동 그리퍼 EH Series를 선보였다. EH Series는 Rack-pinion기구에 AZ Series를 조합한 전동그리퍼 시리즈로 사람의 손가락처럼 섬세하게 잡는 기술을 실현한 제품이다. AZ 시리즈를 탑재하였기 때문에 운전 전류 1% 단위로 설정하여 잡는 물건에 맞춰 파지력을 다양하게 컨트롤할 수 있다. 워크물의 크기에 맞춰 파지력의 파지 시간, 속도를 자유 자재로 설정할 수 있고, 반송물에 충격을 주지 않아 부서지기 쉬운 유리나 스프링 등 안전하고 확실하게 잡을 수 있는 특징이 있다.
핑거 최소 이동량이 0.02mm이므로 워크의 크기에 맞게 방향과 위치를 정렬할 수 있으며 핑거의 작동 범위를 드라이버의 출력 신호 (TLC 출력, AREA 출력)에 의해 확인함으로써 작업의 크기와 유무의 판정을 할 수 있다. 다면 설치를 지원하도록 설계되어 로봇 암등에 설치가 적합하고, 크기가 91 × 46 × 48.5mm에 무게는 380g로 소형화 장치 다양한 분야에서 사용이 기대되어지는 제품이다.

58 hot 한국산업대전 (3)

많은 관람객의 발걸음을 멈추게 한곳은 3D 측정 기술 및 3D 엔지니어링 서비스 분야 전문기업 Creaform 부스였다. 고정밀 산업용 3D 스캐너를 선보이며, 직접 다양한 물체를 스캐닝 하는 모습을 시연하였기 때문이다. Creaform이 선보인 제품으로 첫 번째는 사진 속 1번 제품인 전문가용 휴대용 3D 스캐너이다. 이 제품은 복잡한 표면을 신속하게 측정하고, 측정물의 색상 정보와 함께 스캔 데이터를 3D 모델링 소프트웨어에서 활용할 수 있다. 해상도 0.100mm 복잡한 형상에 대한 고해상도 스캐닝 기능을 탑재하였고, 1.25kg에 작은 여행 가방에 들어가는 크기로 휴대성이 높아 측정 환경에 영향을 받지 않고 어디서든 측정이 가능하다. 또한, 빠른 셋업 기능으로 2분 이내 스캐닝 준비가 완료되며 측정 속도가 최대 1,500,000 measurements/s 99개 화이트라이트 스캐닝 라인이 있다.
2번째 제품은 쉽고 빠르게 정확한 3D 측정을 원하는 제조, 엔지니어링 전문가, 품질 관리 전문가의 요구 사항을 반영하여 이번에 새롭게 개발된 HANDYSCAN 3D 산업용 고정밀 스캐너이다. 공간 정확도는 최대 0.025mm로 세밀한 측정을 위해 고정밀 제품으로 설계되었으며, 0.94kg으로 기존 제품보다 가볍고, 어디서나 자유롭게 측정이 가능하다. 11개의 크로스 레이저 라인의 넓은 스캐닝 영역을 측정할 수 있는 특징을 갖는다.
3번째는 가장 유연한 휴대용 3D 측정 솔루션인 광학 CMM 3D 스캐너: METRASCAN 3D로 모든 유형의 재료 스캔하며, 흑색, 다색 및 광택 표면도 거뜬히 처리가 가능하다. 이 제품은 0.064mm의 용적 정확도를 갖고 있어, 0.2 ~ 10m 크기 부품을 정확하게 측정할 수 있고, 측정 중 언제든지 부품 및 시스템 이동이 가능한 점이 가장 큰 특징이다.

58 hot 한국산업대전 (4)

용접 자동화 시스템 전문 기업 베스트에프에이에서는 피로니우스의 MIG/MAG 용접기 TPS/i 사용하는 모습을 관람객 앞에서 선보였다. 베스트에프에이는 오스트리아 용접기 전문 회사인 프로니우스(Fronius)와 협업하는 국내 유일의 파트너사이기도 하다.
이날 선보인 제품은 TPS/i로 기존의 TPS 시리즈와는 달리 하나의 하드웨어 플랫폼에서 소프트웨어의 업그레이드만으로 다양한 용접 프로세스를 사용할 수 있다. 가장 큰 특징으로는 용접 시작과 종료까지의 용접 현상을 리얼타임으로 감시 및 제어하며 용접 속도 및 CTWD 변화에도 즉각적으로 반응하여 일정한 용입 깊이 및 비드형상을 유지할 수 있다. 또한, 320, 400, 500 및 600A 전원 범주에서 사용할 수 있으며, 사용자가 편리하게 용접기를 조작할 수 있도록 30개의 언어가 지원되고, 파라미터 설정 및 터치가 가능한 LCD 디스플레이가 함께 탑재되어있다. 자동차 및 부품 공급 산업, 파이프라인 및 압력 용기, 구조물 건설 분야에 사용하기에 적합한 제품이다.

58 hot 한국산업대전 (5)

차세대 로봇 자동화를 선도하는 인아텍에서는 스마트 자율 주행 로봇 MiR 제품들을 선보였다. MiR(Mobile Industrial Robots)은 공장, 병원 등 물류 이송 현장 어디에서든 적용할 수 있는 협업 자율 주행 로봇이다. 먼저 MiR100 및 MiR 200은 내부 운송 및 물류를 빠르게 자동화하는 안전하고 비용 효율적인 모바일 로봇이다. 최대 200kg까지 자동으로 운송할 수 있으며 보이는 이미지처럼 상부 모듈을 변경할 수 있어 다양한 작업에 맞춰 로봇을 설정할 수 있다.
MiR500은 산업 전반에서 팔레트와 무거운 화물 운송을 자동화할 수 있도록 설계되어 있다. 리프팅 기능으로 팔레트 이송 작업에 최적화돼 있어 최대 500Kg 중량물 및 팔레트를 이송할 수 있으며 시간당 7.2Km를 운행할 수 있다. 360도 시야를 확보한 최신 레이저 스캐닝 기술을 갖추고 있으며 3D 카메라는 바닥에서 0~3.5m 떨어진 범위를 인식할 수 있어 이동 시 사람, 장애물 등을 감지해 운전할 수 있기 때문에 근무자들이 안전하게 작업할 수 있다.
이 외에도 1,000Kg 중량물을 운반할 수 있는 MiR1000과 카트를 자동으로 픽업, 하역하며 광범위한 견인 작업이 가능하게 만들어주는 MiR Hooks 제품들이 있으며 선보인 제품들은 스마트폰, 태블릿, PC 등 스마트 기기를 통해 MiR 웹 인터페이스로 손쉽게 제어가 가능한 특징을 갖는다.
이번 한국산업대전 머신소프트부분에서는 KT와 퀄컴이 5G+ Stadium 특별관을 마련하고, 국내 8개의 중소기업들과 함께 다양한 5G 스마트팩토리 및 IoT 협력 사례를 선보였다. 퀄컴과 함께 협력한 기업 중 하나인 블루버드는 기업/산업용 loT RFID, 모바일 및 태블릿, 모바일 핀테크 기기를 생산하고 직접 공급하는 세계적인 기업이다.

58 hot 한국산업대전 (6)

블루버드에서는 산업용 모바일, RFID 리더, 산업용 태블릿 제품을 선보였다. 사진 속 가운데 위치한 EF501R 제품이 실외 및 거친 산업 환경에서 사용할 수 있는 블루 버드의 가장 견고한 5인치 터치 모바일 컴퓨터이다. 대용량의 사용자 교체 가능 배터리를 사용하여 가장 긴 작업 시간을 제공하며 핫 스왑 모드를 통해 재부팅하지 않고도 배터리를 교체할 수 있는 특징을 갖고 있다.
실내 및 외부에서 가장 빠른 Wi-Fi 및 4G LTE를 지원하여 안정적인 무선 연결이 가능하며 고급 스캔 기술을 통해 1D 및 2D 바코드뿐만 아니라 더럽고 손상된 바코드를 빠르고 정확하게 캡처할 수 있어 대형 저장, 물류, 제조, 경찰 및 응급 서비스를 갖춘 유통 시장과 같은 다양한 산업에 유용하게 사용된다.
맨 왼쪽 첫번째 제품인 RFR900은 태그 인식 속도와 정확도 모두에서 뛰어난 판독 성능을 제공하며 고속 판독 기능과 초당 6미터까지 확장 된 판독 거리로 초당 900개 이상의 태그를 판독 할 수 있다. 또한 RFR900은 배치 모드에서 4만 개가 넘는 RFID 태그를 저장할 수 있습니다. 5.5인치 풀 HD 멀티 터치 디스플레이 및 매우 얇고 가벼운 권총 손잡이로 설계되어 소매, 제조 및 유통에서 사용하기 이상적인 RFID 제품이다.

58 hot 한국산업대전 (7)

특별관에서는 스마트 비전 및 최적화된 Platform을 통해 다양한 제품으로 인공지능 기반의 영상 인식 솔루션을 제공하는eyedea(아이디어)도 만나 볼 수 있었다. 아이디어에서는 ERVS(Eyedea Robot Vision System)인 스마트팩토리 분야에 특화된 로봇 영상인식 기술을 탑재한 Edge Device를 선보였다. 엣지디바이스는 중앙집중적인 서버/클라우드에 데이터를 전송하고 명령을 전달받는 게 아닌, 서비스를 제공하고 있는 사용자 근접 종단(Edge)에서 바로바로 데이터를 분석하고 처리하여 지연 없이 즉각적으로 서비스를 제공할 수 있는 장치로 독립된 시스템의 처리 속도를 극대화 시켜준다.
또한, 디바이스에서 대부분의 영상처리를 진행하므로 전체 시스템의 부하를 최소화 시켜주며, 기존 시스템 인프라 기반에 디바이스를 장착함으로써 손쉽게 시스템 업그레이드가 가능한 특징이 있다. 기존 기업들이 다양한 고객사의 Needs에 맞는 Customizing Service를 제공하기에는 기술적 한계가 있어 다품종 소량 시스템을 구축하기에는 도입 및 유지 비용 등 막대한 투자가 불가피하였으나, 아이디어는 모듈 형태의 솔루션 공급으로 시스템 구축에 따른 비용 부담이 없어 스마트팩토리 분야에서 특히 비용부문의 강점이 두드러졌다.

58 hot 한국산업대전 (8)

미국 최대의 CNC 머시닝 센터 제조업체 하스오토메이션에서는 금형 및 공구, 다이, 기타 고정밀 부품 가공용으로 고객 맞춤형 컨피규레이션이 가능한 VM시리즈를 소개하였다. Haas VM Series 기계는 금형 제작, 공구 및 금형 작업 및 기타 고정밀 산업에 필요한 정확성, 강성 및 열 안정성을 제공하는 고성능 VMC으로. 각 기계에는 넉넉한 작업 큐브, 다중 고정 테이블 및 12,000rpm 인라인 다이렉트 드라이브 스핀들이 있다. 표준 12,000rpm 스핀들은 저속 토르크 또는 고속 파워의 저하없는 고rpm을 제공하고, 소형 공구를 장착하여 더 나은 표면 이송을 위해 15,000rpm 인라인 스핀들과 30,000rpm 30테이퍼 스핀들도 제공된다.
이외에도 전면 전망, 측면 장착 툴 체인저, 프로그래밍 가능 냉각수 노즐, 자동 에어건 등을 갖춘 Haas 고속 제어 기능을 탑재하였다.
또한, 제공되는 컨트롤러는 공작 기계 산업에서 가장 사용자 친화적인 CNC 컨트롤러로 간단한 사용자 인터페이스가 제공되어 직관적인 탐색 기능을 통해 빠른 조작이 가능하다.

58 hot 한국산업대전 (2)

 

58 hot 한국산업대전 (9)

산업용 센서, 컨트롤러 전문기업으로 잘 알려진 오토닉스는 각종 센서류를 비롯하여 내년출시 예정인 세이프티 제품 및 변위센서등의 고기능 신제품을 선보여 많은 관람객들로 붐볐다. 이번에 선보인 신제품 중 세이프티 도어락 장치는 보호물 또는 출입구의 위치를 감시하는 장치로 보호물이 개방될 때 전원을 차단하고 사람의 접근을 통제하며, 장비 시동을 중단할 수 있다. 이 제품은 기존에 사용되어왔던 외국산 제품이 아닌 국산 제품이기에 가성비가 좋으며, 기존 점등의 가시성, 스위치 키를 뺄 때 힘이 많이 들어가거나, 너무 쉽게 빠지는 문제점을 개선하여 개발되었다.

변위센서는 대상물의 물리 변화량을 다양한 소자로 검지하여 그 변화량을 거리로 환산함으로써 센서에서 대상물의 거리와 높이를 계측하는 제품이다. 레이저를 쓰는 변위센서는 높은 직진성을 지니면서 스팟 자체가 포토센서에 비해 작고, CMOS 센서를 써서 정확하게 어떤 위치에 레이저가 맺히는지 반사되기 때문에 정밀한 측정이 가능하다. 두 가지 제품 모두 정확한 스펙이나 자료는 내년에 배포될 예정이라 하니 국산화된 두가지 제품군이 어떻게 출시될지 기대된다.

58 hot 한국산업대전 (10)

산업 분야에서 매뉴얼 리프팅 작업용 핸들링 기술을 제공하는 슈말츠에서는 진공 리프터 및 크레인 시스템을 소개하며 관람객들 앞에서 직접 시현을 보이고 있다. 진공 리프터는 진공기술을 이용하여 작업물을 흡착, 이송해주는 진공 흡착이송장치로 압축된 공기로 흡착하여 에어밸런스, 에어 바란스라고도 불린다. 손가락을 사용하여 상하 조작 버튼을 조정하고, 한 손으로는 이송 방향을 살짝 밀어 움직이기 때문에 사용이 쉽고, 직관적으로 제품을 작동 시킬 수 있다.
알루미늄 구성 부품으로 제작된 크레인 시스템과 완벽하게 조합된 크레인 진공 리프터를 제공하며 리프트는 최대 300kg 중량의 상품을 쉽고 빠르게 옮길 수 있다. 이렇듯 자동화 설비에 추가하여 공정개선과 함께 스마트 물류를 실현할 수 있으며, 진공을 사용하여 화물을 들어 올리거나 내리기 때문에 무거운 화물을 옮기는 작업에서 비롯되는 부상을 사전에 예방할 수 있다.

최대 규모로 진행된 이번 전시회에는 6만여명의 관람객이 다녀가며 성황리에 막을 내렸다고 전해진다. 큰 규모에 맞게 전시회장을 다 둘러보기란 매우 힘들었으나, 한국기계전과 머신 소프트 2019가 함께 개최되어 IT 기술과 제조 트렌드를 한 번에 확인할 수 있는 좋은 기회였다. 단순히 제품 정보를 얻는것이 아닌 실제로 어떻게 작동을 하고 어떻게 활용할 수 있는지를 직접 시연하고, 설명해주는 부스들이 유독 눈에 많이 띄어 끝까지 집중해서 둘러볼 수 있었다. 또한, 대다수의 업체들이 스마트 기계류를 선보이며 스마트 팩토리에 대한 업계의 관심과 스마트화가 국내 기계분야에서는 어느 수준까지 도달했는지 살펴볼 수 있었다. 내년 한국산업대전에서는 어떤 혁신적인 제품들이 미래산업의 모습을 바꿀지 기대하며 이번 관람기를 마친다. DM

[58호]세이프티 볼라드

[58호]세이프티 볼라드

58 ict 세이브티볼라드 (1)

2019 ICT 융합 프로젝트 공모전 참가상

세이프티 볼라드

글 | 경북대학교 김도훈, 박선우, 박은빈

1. 심사평
칩센 횡단보도등에서 발생하는 사고소식을 접할때마다 늘 생각이 들던 시스템이고, 간혹 주차장 입출입구 등에 유사한 시스템이 적용되어 있는 것을 본적이 있는듯 하다. 하지만 여러가지 현실적인 문제로 인하여 아직까지도 적용이 되지 않는게 아닐까 하는 막연한 추측을 하고 있다. Mechanic적인 요소를 적용한 것이 매우 흥미로우며, 시제품의 완성도도 생각보다는 높게 평가할수 있을듯 하다. 앞서 설명한것과 같이 실제 시스템을 적용하기 위한 현실적인 문제에 대하여 조금 더 고민하여 개선된 제품이 나온다면 아파트 단지등과 같은 변수고려가 적은 환경에 있어 적용가능할 것으로 보인다.
뉴티씨 법적으로 근거가 있는 아이디어이며, 또한, 많은 특허들도 등록되어 있습니다. 실용화가 가능한 것으로, 이미 국내 및 일본 등에서 실용화가 되어 있는 곳도 있는것으로 알고 있습니다. 장소에 따라서는 사고를 막기위하여 매우 중요한 시설로 사용될 수 있다고 생각됩니다. 학생으로 스스로 이런 생각을 해내었다는 점에서 박수를 보냅니다.
위드로봇 아이디어가 독보이는 작품입니다. 실용성 측면을 좀 더 고민하면 더욱 좋은 작품이 될 것 같습니다.
펌테크 작품의 하우징 구성은 상당히 깔끔하고 훌륭하게 구성이 되었으나, 작품의 구성 측면에서는 너무 단순하고 심플한 느낌을 받았습니다. 작품전 출전이라는 것을 감안한다면 현재의 작품에 아디디어를 좀 더 반영한 형태로 출품이 되었다면 좋지 않았을까 생각합니다.

2. 작품 동기 및 개요
2.1. 동기
[랩해서남줄랩]이라는 TV프로그램의 주제 중 ‘나는 장애를 극복하지 않았다.’라는 편을 보았습니다. 이 프로그램에서는 지체장애인분들이 일상생활에서 많은 불편함을 겪고 있고, 이것을 해결하기위해 직접 나서는 모습을 담고 있었습니다. 특히 차가 들어오는 것을 막기 위해 설치를 해둔 볼라드 때문에 휠체어가 지나가지 못하거나, 걸린다는 것을 알게 되었습니다. 이런 불편사항을 보안하기 위해 ‘자동으로 움직이는 볼라드는 어떨까?‘라는 생각을 하게 되었고 주로 횡단보도에 설치되어있는 볼라드에 적용해보기로 했습니다.
볼라드가 올라오고 내려오는 과정을 토의하면서 주의할 점을 파악해 나갔습니다. 무턱대고 볼라드가 땅에서 올라오면 횡단보도에 서있던 보행자가 다칠 위험이 클 것이라고 생각했습니다. 그래서 볼라드를 윈기둥 형태가 아닌 ‘π’자 형태로 만들기로 했습니다. 세이프티 볼라드의 윗부분은 일반 보행자들에게 잘 보이는 색상으로 구성하였고, 지체장애인 분들도 볼라드의 위치를 알도록 들어갔을 때도 약간 볼록한 형태로 구상을 했습니다.
또한, 이 볼라드는 지체장애인분들 뿐만 아니라 보호구역에서도 유용하게 사용될 수 있을 것이라고 판단했습니다. 어린이 보호구역에 세이프티 볼라드가 설치된다면 아이들에게 신호체계를 보다 정확하게 알려 줄 수 있을 것이라고 생각합니다. 더불어 빨간불일 때 횡단보도에서 무단횡단을 하는 사람들이 줄어들어 보다 나은 교통질서를 제공할 것입니다. 결과적으로 안전사고를 예방하는데 큰 도움이 되는 시스템이라고 자부합니다.

2.2. 개요
이 세이프티 볼라드는 신호에 따라 올라가고 내려가는 시스템을 가지고 있다. 이것은 장애인분들의 이동권을 보장 해 줄 수 있을 뿐만 아니라 일반인들의 무단횡단을 줄여 안전사고를 예방할 수 있다. 또한 어린이 보호구역에 설치하여 초록어머니를 대신하는 횡단보도 지킴이가 될 것이다.

3. 작품 설명
3.1. 구상도

58 ict 세이브티볼라드 (2)

 

58 ict 세이브티볼라드 (3)

차량이 지나다니지 않아도 신호등이 빨간불이 되면 볼라드에 신호를 주어 땅에서 올라와 보행자가 지나가지 못하도록 길을 막습니다. 마찬가지로 신호등이 파란불이 되면 볼라드에 신호를 주어 땅으로 들어가서 보행자가 길을 다닐 수 있도록 합니다.

3.2. 결과물 사양

58 ict 세이브티볼라드 (4)

4. 제작과정
4.1. 단계별 제작과정

58 ict 세이브티볼라드 (1)

도로의 안, 즉 땅 속을 나타낼 틀을 제작합니다. 이 때 볼라드가 만들어질 위치에 모터와 볼라드를 설치할 지지대를 만들어 줍니다.

58 ict 세이브티볼라드 (2)

볼라드 지지대를 만들어 올라가고 내려갈 수 있도록 기존의 지지대에 설치해 줍니다. 이는 모터에 부착된 톱니바퀴가 회전을 하면 아래, 위로 움직여주는 역할을 합니다.

58 ict 세이브티볼라드 (3)

모터를 볼라드와 연결된 부분에 연결시켜 주어 모터가 돌아가면 볼라드가 올라가고 내려가도록 설정해줍니다.

58 ict 세이브티볼라드 (4)

시스템 상단에 도로를 구현해 줍니다. 분홍색부분은 인도 부분이며 검은색부분은 차도로 횡단보도만 나타냈습니다. 빨간색 LED와 초록색LED를 연결한 신호등을 설치해 줍니다.
볼라드를 설치할 구멍을 뚫어 볼라드가 내려가고 올라가도록 합니다.

58 ict 세이브티볼라드 (5)

빨간불 일 때는 볼라드가 올라오도록 모터가 정방향 회전을 합니다.

58 ict 세이브티볼라드 (6)

초록불 일 때는 볼라드가 내려가도록 모터가 후방향 회전을 합니다.

4.2. 주요 동작 및 특징
전체적인 동작 내용은 신호등과 횡단보도를 표현하고 신호등 신호에 맞게 볼라드를 위아래로 움직여 주는 것이다. 이를 위해 아두이노 보드와 모터 쉴드를 이용해 모터의 동작과 LED 깜박임을 제어하도록 구성하였다. 먼저 신호등 빨간불에서 초록불로 바뀌는 경우에 LED-green에 전압을 인가하고 LED-red의 전압을 차단하는 동시에 두 모터에 동작명령을 주어 횡단보도 양측 볼라드가 같이 내려가도록 설계하였다. 초록불 시간이 거의 다 끝나갈 때 즈음 LED-green이 깜박이도록 명령을 주어 신호가 거의 끝나간다는 것을 표현하였다. 이후 시간이 다 되면 LED-green의 불이 꺼짐과 동시에 LED-red의 불이 켜지면서 볼라드가 올라오도록 설계하였다.
상하로 움직일 수 있는 볼라드로 인해 볼라드의 주 기능인 차량 통제의 역할을 수행할 수 있는 동시에 볼라드로 인해 발생했던 보행자의 통행 불편함을 해소할 수 있게 되었다.
또한 제작 과정에서 볼라드가 내려갈 때와 올라갈 때의 모터 구동 시간을 다르게 설정하여 중력으로 인한 모터의 부하로 발생하는 볼라드의 높이 오차를 해결하였다.

4.3. 전체 시스템 구성

#include <AFMotor.h>

AF_DCMotor motor1(3); // M3에 연결
AF_DCMotor motor2(2); // M2에 연결

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println(“Motor test!”);

// turn on motor
motor1.setSpeed(0); // 모터 회전속도 설정
motor2.setSpeed(0);
motor1.run(RELEASE);
motor2.run(RELEASE);

// analog input pin을 output으로 초기화
pinMode(A0, OUTPUT); // RED
pinMode(A5, OUTPUT); // GREEN
}

void loop() {
uint8_t i;

delay(1000);

Serial.print(“tick”);

// 정방향 회전
motor1.run(FORWARD);
motor2.run(FORWARD);
digitalWrite(A0, LOW); // RED off
digitalWrite(A5, HIGH); // GREEN on

// 모터 구동 시작
for (i=0; i<60; i++) {
motor1.setSpeed(180);
motor2.setSpeed(180);
delay(10);
}

// 모터 정지
motor1.run(RELEASE);
motor2.run(RELEASE);
delay(5000);

Serial.print(“tock”);

// 초록불 점멸
for (i=0; i<5; i++) {
digitalWrite(A5, LOW);
delay(200);
digitalWrite(A5, HIGH);
delay(200);
}

Serial.print(“tech”);

// 역방향 회전
motor1.run(BACKWARD);
motor2.run(BACKWARD);
digitalWrite(A0, HIGH); // RED on
digitalWrite(A5, LOW); // GREEN off

// 모터 구동 시작
for (i=0; i<80; i++) {
motor1.setSpeed(200);
motor2.setSpeed(200);
delay(10);
}

// 모터 정지
motor1.run(RELEASE);
motor2.run(RELEASE);
delay(7000);
}

위는 스마트 볼라드의 모형을 구동시키기 위한 소스 코드이다. 상하로 왕복운동을 하는 구조는 과학상자로 만들었으며, 이에 필요한 두 개의 모터를 제어하기 위한 장치로 아두이노(UNO R3 ATmega328)와 아두이노 모터 쉴드(Adafruit L293D Motor Shield)를 선택하였다. 아두이노의 코드는 C++을 기반으로 만들어졌다. 따라서 코드의 문법은 모두 C++과 동일하다. 아두이노에서 모터쉴드를 제어하기 위한 헤더파일(AFMotor.h)이 제공되고 있으므로 이를 활용하였다. 아두이노의 코드는 크게 두 부분으로 구분된다. LED, 모터 등의 객체를 생성하고 객체들의 초기 설정을 해주는 부분인 void setup() 함수와 무한 반복되며 하드웨어의 실질적인 동작을 기술하는 부분인 void loop() 함수로 이루어진다. 먼저, 가장 첫 부분은 다음과 같다.

#include <AFMotor.h>

AF_DCMotor motor1(3); // M3에 연결
AF_DCMotor motor2(2); // M2에 연결

#include <AFMotor.h>는 Adafruit L293D Motor Shield를 활용하기 위한 라이브러리를 추가하는 부분이다. 미리 만들어져있는 헤더파일을 통해 모터 객체를 쉽게 생성하고, 다양한 메소드를 편리하게 사용할 수 있게 된다. 아래의 두 줄은 AFMotor 라이브러리에 정의되어있는 AF_DCMotor 클래스를 사용해 두 개의 모터를 제어하기 위해 각각 motor1, motor2 라는 모터 객체를 생성한다. 이때 생성자의 매개변수로 각각 3, 2를 넘겨주었는데, 이는 모터 쉴드의 4개의 모터 연결 포트 중 motor1은 3번 포트에, motor2는 2번 포트에 연결하겠다는 의미이다.

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println(“Motor test!”);

// turn on motor
motor1.setSpeed(0); // 모터 회전속도 설정
motor2.setSpeed(0);
motor1.run(RELEASE);
motor2.run(RELEASE);

// analog input pin을 output으로 초기화
pinMode(A0, OUTPUT); // RED
pinMode(A5, OUTPUT); // GREEN
}

Serial.begin(speed)는 아두이노가 시리얼 통신을 사용하게 만드는 메소드이다. Serial은 시리얼 통신과 관련된 메소드들이 포함되어있는 정적(static) 클래스이다. 메소드의 인자로 넘겨주는 speed 초당 몇 비트의 속도로 통신을 할지 설정하는 값이다. 이는 컴퓨터 쪽의 시리얼 통신 속도와 일치하여야 시리얼 모니터에 정상적으로 출력이 된다. 다음은 모터와 LED를 초기화하는 부분이다. setup() 함수 이전에 생성한 두 개의 모터 객체의 속도와 현재 구동 상태를 각각 0과 RELEASE 상태로 초깃값을 설정해 준다. 아두이노 보드에는 12개의 출력 핀과 6개의 아날로그 인풋 포트가 있다. 그런데 Adafruit L293D Motor Shield는 2번, 13번 핀을 제외하고는 모두 사용하는 방식으로 아두이노 보드에 장착된다. 따라서 모터를 구동시키는 것 외에 신호등을 구현하기 위한 두 개의 LED의 출력을 제어하기 위해서는 아날로그 인풋 포트를 디지털 아웃풋 핀으로 사용할 필요가 있었다. 그 설정을 해주는 부분이 pinMode() 함수이다.

void loop() {
uint8_t i;

delay(1000);

loop() 함수는 setup() 함수가 실행된 후 프로그램이 종료될 때까지 함수 내부의 내용이 무한 반복되며 실행된다. 먼저 uint8_t i; 는 loop() 함수 내부의 반복문에서 계속 사용할 지역변수 i를 선언하는 코드이다. 자료형 uint8_t 는 <stdint.h>에 정의되어있는 자료형으로, 8비트의 부호가 없는 정수형의 자료형을 나타낸다. 즉, 정수 0에서부터 255까지 표현할 수 있다. 아두이노 UNO R3 ATmega328는 8-bit의 프로세서를 가지고 있어 8비트 보다 큰 자료를 한 번에 처리하지 못하므로 해당 자료형을 사용한다. delay() 함수는 의미 그대로 코드를 실행하는데 시간을 지연시키는 역할을 한다. 함수의 인자로 전달받는 시간의 단위는 ms(밀리세컨드) 이므로 위의 예처럼 1000 을 넘기면 1000ms 즉 1초를 지연시킨다. 이 delay() 함수를 통해 신호등의 빨간불, 초록불이 켜지는 시간과 모터를 동작시키는 반복문의 시간을 제어할 수 있다.

Serial.print(“tick”);

// 정방향 회전
motor1.run(FORWARD);
motor2.run(FORWARD);
digitalWrite(A0, LOW); // RED off
digitalWrite(A5, HIGH); // GREEN on

// 모터 구동 시작
for (i=0; i<60; i++) {
motor1.setSpeed(180);
motor2.setSpeed(180);
delay(10);
}

// 모터 정지
motor1.run(RELEASE);
motor2.run(RELEASE);
delay(5000); Serial.print(“tick”);

// 정방향 회전
motor1.run(FORWARD);
motor2.run(FORWARD);
digitalWrite(A0, LOW); // RED off
digitalWrite(A5, HIGH); // GREEN on

// 모터 구동 시작
for (i=0; i<60; i++) {
motor1.setSpeed(180);
motor2.setSpeed(180);
delay(10);
}

// 모터 정지
motor1.run(RELEASE);
motor2.run(RELEASE);
delay(5000);

Serial.print(“tick”) 메소드는 아두이노 개발환경의 시리얼 모니터에 “tick”이라는 문자열을 출력한다. 이를 통해 loop() 함수 내부에서 해당 메소드까지 소프트웨어적으로 문제없이 실행되고 있음을 확인하기 위한 목적으로 활용한다. 초록불이 되고 모터가 정방향으로 구동되기 시작할 때 “tick”을, 초록불이 깜빡거리기 시작할 때 “tock”을, 빨간불이 되고 모터가 역방향으로 구동되기 시작할 때 “tock”을 출력하도록 하였다.
motor1.run(FORWARD); 는 모터를 회전시키기 위하여 모터 객체(motor1, motor2) 의 상태를 정지(RELEASE)에서 정방향 회전(FORWARD)로 변경시켜 주는 부분이다. digitalWrite(pin, value); 함수는 HIGH 또는 LOW 값을 디지털 핀에 출력하는 함수이다. setup() 함수에서 아날로그 입력 단자 A0, A5를 pinMode() 함수를 통해 디지털 출력 핀으로 설정해 주었기 때문에 A0, A5 단자에 대해서 HIGH, LOW의 값을 출력할 수 있다. A0 단자에는 빨간색의 LED를 연결하고, A5 단자에는 초록색의 LED를 연결할 것이므로, 빨간색 신호등은 끈 상태로, 초록색 신호등은 켜진 상태로 만들기 위해 digitalWrite() 함수의 value 인자를 각각 LOW, HIGH로 설정하였다.
초록불이 켜지고 난 다음은 올라가 있던 스마트 볼라드가 땅으로 내려올 차례이다. AF_DCMotor클래스의 메소드인 .setSpeed(speed) 메소드는 모터의 속력을 설정한다. speed 인자의 값으로 0에서 255까지의 값을 받을 수 있으며, 0은 꺼진 상태를, 255는 최대 속력을 나타낸다. 우리가 설정한 speed 값인 180은 어떤 정확한 수치를 나타내는 것이 아니다. DC 모터의 응답이 일반적으로 선형적이지 않으므로, 실제 RPM이 설정된 값인 180에 비례하게 나타나지는 않는다. 다양한 값으로 구동을 시켜본 결과 볼라드 구조물의 무게와 부하를 이겨내기 위한 적절한 속도를 구한 것이 180이다.
반복문의 한 루프에 10ms씩의 시간 지연이 들어가 있어 총 60번의 반복을 하므로 이론적으로는 총 0.6초가 걸리겠지만, 모터가 구동되는 시간으로 인해 시간이 조금 더 걸려 1초 내외로 동작을 마친다. 반복문의 실행을 마치고 나면 양쪽의 볼라드가 하강하여 땅으로 완전히 내려와 있는 상태가 된다. motor1.run(RELEASE); 메소드는 볼라드가 정지한 이후 두 개의 모터의 동작 상태를 정방향 구동 중에서 정지로 바꿔주는 부분이다. 또한, 초록불이 점멸하기 시작하기 전까지 5초 동안의 시간 지연을 준다.

Serial.print(“tock”);

// 초록불 점멸
for (i=0; i<5; i++) {
digitalWrite(A5, LOW);
delay(200);
digitalWrite(A5, HIGH);
delay(200);
}

초록불이 일정 시간이 지나 빨간불로 바뀌기 전 깜빡이는 기능을 수행하는 부분이다. 따라서 위에서 말한 대로 초록불이 점멸하기 전 Serial.print() 메소드를 통해 “tock”을 시리얼 모니터에 출력하여 프로그램이 정상 작동하고 있는지 확인한다. 초록색 LED가 연결된 A5 포트의 출력을 LOW, HIGH로 0.2초의 시간 지연을 두고 번갈아 가면서 5번 바꾼다. 다시 말해서, 초록불이 다섯 번 깜빡이고 끝난다.

Serial.print(“tech”);

// 역방향 회전
motor1.run(BACKWARD);
motor2.run(BACKWARD);
digitalWrite(A0, HIGH); // RED on
digitalWrite(A5, LOW); // GREEN off

// 모터 구동 시작
for (i=0; i<80; i++) {
motor1.setSpeed(200);
motor2.setSpeed(200);
delay(10);
}

// 모터 정지
motor1.run(RELEASE);
motor2.run(RELEASE);
delay(7000);

초록불이 깜빡거리기를 끝내고 빨간불로 바뀌면서 모터가 작동하여 볼라드가 올라가는 동작을 시키는 부분이다. 초록불이 되고 볼라드가 내려가는 동작을 하는 loop() 함수의 첫 번째 블록과 거의 같은 코드 구성을 하고 있다. 하지만 세세한 설정은 정반대이다. 모터가 구동되는 방향이 반대여야 하므로 이전에 FORWARD로 설정하였던 값을 BACKWARD로 바꾸고, 초록불과 빨간불의 켜지고 꺼짐도 반대로 바뀌었다. 모터 구동 부분의 반복문의 경우 반복 횟수가 위의 블록과 같지 않다. 같은 구조로 코드를 작성하여 실행시켜 보았을 때, 볼라드 구조물의 무게로 인해 볼라드가 내려가는 길이에 비해 올라가는 길이가 적었다. 따라서 반복문의 횟수를 더 크게 설정하여 올라가고 내려오는 길이가 거의 같도록 조절하였다. 또한, 모터의 상태를 정지(RELEASE)로 변경한 후 주는 시간 지연이 더 긴 것은 초록불과는 다르게 깜빡거리는 시간을 고려하지 않았기 때문이다.

4.4. 기대효과 및 예상되는 장애요인과 해결방안
스마트 볼라드가 실제로 도입된다면 필요에 따라 볼라드를 설치 및 제거함으로써 차량 통제가 필요한 곳에 널리 쓰일 수 있을 것이다. 예를 들어 주차장에서의 차량 통제나 인도의 불법 주정차 예방에도 사용될 수 있고, 큰 행사로 인해 넓은 지역의 대규모 차량 통제가 필요한 경우 손쉽게 스마트 볼라드를 이용하여 차량 진입을 막을 수 있다.
또한 스마트 볼라드는 횡단보도에서 지하철의 스크린 도어와 비슷한 역할을 해줄 수 있기 때문에 무단횡단 예방의 효과가 있고, 횡단보도에서의 교통사고 발생 위험을 상당히 낮출 수 있을 것으로 기대된다.
특히, 어린이 보호 구역이나 보행 약자가 많은 지역에서 스마트 볼라드가 빛을 발할 수 있는데 사람 없이도 24시간 교통 약자의 보행을 보호해줄 수 있어 교통 상황을 관리해주는 교통 경찰이나 경비원, 녹색 어머니회의 역할을 대신할 수 있다.
스마트 볼라드를 제작하는 과정에서 여러 좋은 아이디어가 나왔지만 직접 제작하는 데까지는 이르지 못하였다. 예를 들어 볼라드에 LED를 설치하여 야간에 어두운 길을 밝혀 주는 역할을 할 수도 있고, 센서를 부착해 사람을 인식하여 차가 없으면 신호가 바뀌고 자동으로 내려가게 하는 기능과 시간대 별로 보행자와 차량의 통행량 정보를 측정해 교통 정보도 수집할 수 있도록 할수 있을것이다. 그리고 볼라드가 움직이기 전에 음성안내를 해주어 보행자에게 미리 알려주는 기능도 추가되면 좋을 것 같다.
스마트 볼라드에서 예상되는 장애요인으로는 갑자기 움직이는 볼라드로 인한 보행자 피해와 볼라드의 설치 및 유지 관리 문제가 있다.
하지만 이런 문제는 향후 발전 방향에서 언급한 것처럼 볼라드가 움직이기 전에 LED점멸이나 음성 안내 메시지를 통해 보행자가 볼라드의 움직임을 미리 예측할 수 있도록 한다면 보행자가 볼라드의 움직임을 인지하지 못해 생기는 사고를 예방할 수 있을 것이다. 또한 스마트 볼라드는 땅 밑에 장치를 설치하여 볼라드가 올라오는 방식이므로 설치가 비교적 쉬운 편이고 외부 충격으로 인한 파손이 있다 하더라도 볼라드 기둥만 교체해 주면 되기 때문에 수리하기도 편리할 것이다. 또한 컴퓨터로 볼라드를 제어할 수 있기 때문에 볼라드 관리도 간편할 것으로 예상된다.

5. 참고
· 아두이노 코드 및 구동방법: https://youtu.be/V-MXQN3CjEE https://www.youtube.com/watch?v=D5JX2N-7zWo