User Tools

Site Tools


getting_started_with_arduino

Table of Contents

Getting Started With Arduino 번역

오픈소스 전자 프로토타입용 플렛폼

마시모 밴지 - 아두이노의 공동 창시자

서문

몇 년 전 나는 아주 흥미로운 과제를 맡은 적이 있다. 그것은 디자이너들에게 그들이 디자인하는 물체의 양방향성 프로토타입을 스스로 만들 수 있도록 아주 기본적인 전자 지식을 가르치는 것이었다.

무의식 적으로 내가 학교에서 전자에 대해 배웠던 방법을 사용해 가르치기 시작했는데 이 방법이 전혀 기대했던 대로 되지 않고 있음을 알게 되었고, 나 역시 실습이 전혀 없는 채로 교실에 앉아 쏟아지는 이론을 듣고만 있는 것이 끔찍하게 지루했다는 것이 기억나기 시작했다.

실제로 나는, 학교에서 전자를 배우기 전부터 매우 특별한 방법인 이론은 매우 부족하지만 손으로 터득한 많은 경험으로 이미 전자 기술에 대해 알고 있었다.

내가 전자지식을 얻게 된 진짜 과정들을 생각해 보니 다음과 같았다.

  • 입수할 수 있는 전자 장치들을 분해한다.
  • 천천히 각 부품들에 대해 배운다.
  • 더 깊게 생각해 보기 시작하여, 내부 연결점들을 바꿔 보고 장치에 어떤 변화가 있는지 살펴본다. 대부분 부품이 터지거나 연기가 피어났다.
  • 전자 잡지들에서 파는 키트를 만들어 본다.
  • 헤집어 논 장치들과 수정한 키트들, 잡지에서 찾은 회로도를 조합하여 새로운 일을 하도록 만들어 본다.

어린 시절, 나는 물건들이 어떻게 작동하는지 알아내는 일에 심취해 있었기 때문에, 물건들을 분해하곤 했다. 이 열정이 자라나 사용하지 않는 가전기기들을 그 대상으로 삼게 되었고, 사람들은 모든 종류의 장치들을 분해하라고 내게 가져다주었었다. 당시 나의 프로젝트들 중 가장 큰 규모의 것은 식기세척기와 보험 사무실에서 버려진 커다란 프린터와 전자 카드, 마그네틱 카드 리더가 딸린 초기 컴퓨터였는데 이를 완전히 분해하는 것은 매우 흥미롭고 도전적이었다.

이런 해부 실습을 꽤 많이 한 뒤에, 나는 어떤 전자 부품들이 있고 대략 어떤 역할을 하는지 알 수 있게 되었다. 이런 지식의 배경에는 아버지께서 1970년대 초부터 사 두어 집안에 가득했던 오래된 전자잡지들이 있었다. 거의 대부분은 이해할 수 없었지만, 나는 그 기사들과 회로도들을 몇 시간씩 읽곤 했다.

기사를 읽고 또 읽는 과정들은 회도들을 분해하면서 얻은 지식들을 합쳐져, 느리지만 효과적인 순환 과정이 되었다.

아버지께서 내게 십대들을 대상으로 한 전자 학습 키트를 선물해 주신 어느 크리스마스에 비약적인 도약이 이루어졌다. 키트의 각 부품들은 플라스틱의 네모난 껍데기가 씌워져 있었고, 각 부품들은 자석을 사용해 딱각하는 소리를 내며 서로 연결되었다. 각 부품의 윗면에는 회로 기호가 표시되어 있었다. 이 장난감에 대해서 조금 더 알고 있었던 것은, 이 장난감의 독일 디자인의 한 획이라는 것으로, 왜냐하면 1960년대에 디터 람스1)가 이 장난감을 디자인했기 때문이다.

이 새 도구를 사용해 나는 빠르게 회로를 만들고, 어떤 일이 일어나는지 확인해 볼 수 있었다. 이 프로토타입을 만드는 주기는 점점 더 짧아졌다.

그 다음으로는 라디오, 앰프, 끔찍한 노이즈나 괜찮은 소리가 나는 회로들, 강우 센서, 조그만 로봇들을 만들었었다.

나는 특별히 계획을 세우지 않고 아이디어로 부터 시작해서 완전히 기대 밖의 결과를 얻어내는 일을 설명하기 위해 단어를 오랫 동안 찾아왔고, 마침내 “팅커(tinker)“이라는 단어를 찾게 되었다. 많은 다른 분야에서도 새로운 길을 개척하는 사람을 묘사하는 데 이 단어를 사용한다는 것을 알게 되었다. 예를 들면 프랑스에서 “누벨바그”의 탄생을 이끌었던 사람들은 “팅커러”2)로 불린다. 내가 팅커링에 대해 찾은 가장 좋은 정의는 샌프란시스코의 박람회장에서 열린 박람회에서 알게 된 것이다.

팅커링은 어떻게 해야 하는지 정확히 모르는 상태에서 직관, 상상, 호기심 등을 따라 일을 시도할 때 일어난다. 팅커링을 할 때 따라야할 교범 같은 것은 없다. 즉 실패란 없으며, 옳고 그름 나뉘지도 않는다. 이는 어떻게 작동하는지와 다시 작동하게 하는 방법을 알아내는 것에 관한 것이다.

기묘한 발명품, 기계들, 크게 어긋나 있는 물체들이 조화롭게 동작하는 것. 이런 것들이 팅커링이다.

팅커링은, 가장 기본적으로는 놀이, 탐구와 결혼하는 과정이다.

www.exploratorium.edu/tinkering

어릴 적 경험에 비추어, 나는 원하는 회로를 만들기 위해서는 기본적인 부품들부터 시작해 얼마나 많은 경험이 필요한지를 알게 되었다.

다른 도약점은 1982년 여름에 부모님과 함께 런던에 가서 과학박물관을 관람하느라 오랜 시간을 보내던 시점에 찾아왔다. 당시 박물관은 컴퓨터 관을 새롭게 열었는데, 가이드를 따라 다니면서 기본적인 이산수학과 프로그래밍의 기초에 대해 배울 수 있었다.

그곳에서, 많은 어플리케이션에서 엔지니어들은 더 이상 기본 부품들로부터 회로를 만들지 않고, 마이크로프로세서를 사용해 다량의 정보처리를 구현한다는 것을 알게 되었다. 소프트웨어는 많은 시간이 필요한 전자 디자인을 대체하여, 팅커링 주기를 더 짧게 만들 수 있게 해 준다.

그곳에서 돌아와서는 돈을 모으기 시작했는데, 왜냐하면 컴퓨터를 구입해서 프로그래밍 하는 방법을 배우고 싶었기 때문이다.

그 후로 내게 가장 중요한 프로젝트는 새로 산 ZX-81 컴퓨터를 사용해 용접기를 제어하는 것이었다. 아주 흥미로운 프로젝트처럼 들리진 않겠지만, 필요한 곳이 있었고 막 프로그래밍하는 방법을 배운 터라 대단한 도전이기도 했다. 이 시점에서 복잡한 회로를 수정하는 것보다 몇 줄의 코드를 작성하는 게 시간이 덜 든다는 사실이 명확해 졌다.

이십여 년이지나, 나는 이런 경험들 때문에, 학교에서 배운 수학 수업을 전혀 기억 못하는 사람들에게도 내가 어린 시절부터 지녀온 것과 같은 열정과 팅커링 하는 능력을 가르칠 수 있게 되었다고 생각한다.

- 마시모

감사의 글

이 책을 루이자(Luisa)와 알렉산드라(Alexandra)에게 바친다.

우선 아두이노 팀의 파트너 David Cuartielles, David Mellis, Gianluca Martino, Tom Igoe에게 감사를 전한다. 여러분과 함께 일한다는 것은 환상적인 일이다.

그녀 자신은 모르겠지만 Barbara Ghella의 정확한 조언이 없었다면 아두이노와 이 책은 없었을 지도 모른다.

Bill Verplank는 내게 피지컬 컴퓨팅과 더 많은 것들을 가르쳐 주었다.

내게 기회를 준 Gillian Crampton-Smith과 그녀에게 배운 모든 것들에 감사한다.

Wiring 플랫폼을 만든 Hernando Barragan에게 감사를 전한다.

Brian Jepson는 훌륭한 편집자로 전 과정에서 열정적인 도움을 주었다.

Nancy Kotary, Brian Scott, Terry Bronson, Patti Schiendelman 는 내가 작성한 글들은 책으로 마무리 해 주었다.

더 많은 사람들에게 감사를 전하고 싶지만, 브라이언이 공간이 부족하다고 하는 관계로 여러 이유에서 감사들 드리는 사람들의 이름을 나열한다.

Adam Somlai-Fisher, Ailadi Cortelletti, Alberto Pezzotti, Alessandro Germinasi, Alessandro Masserdotti, Andrea Piccolo, Anna Capellini, Casey Reas, Chris Anderson, Claudio Moderini, Clementina Coppini, Concetta Capecchi, Csaba Waldhauser, Dario Buzzini, Dario Molinari, Dario Parravicini, Donata Piccolo, Edoardo Brambilla, Elisa Canducci, Fabio Violante, Fabio Zanola, Fabrizio Pignoloni, Flavio Mauri, Francesca Mocellin, Francesco Monico, Giorgio Olivero, Giovanna Gardi, Giovanni Battistini, Heather Martin, Jennifer Bove, Laura Dellamotta, Lorenzo Parravicini, Luca Rocco, Marco Baioni, Marco Eynard, Maria Teresa Longoni, Massimiliano Bolondi, Matteo Rivolta, Matthias Richter, Maurizio Pirola, Michael Thorpe, Natalia Jordan, Ombretta Banzi, Oreste Banzi, Oscar Zoggia, Pietro Dore, Prof Salvioni, Raffaella Ferrara, Renzo Giusti, Sandi Athanas, Sara Carpentieri, Sigrid Wiederhecker, Stefano Mirti, Ubi De Feo, Veronika Bucko.

1/도입

아두이노는 간단한 입/출력(I/O) 보드와 프로세싱(www.processing.org) 언어에 사용된 개발 환경으로 구성된 오픈소스 피지컬 컴퓨팅 플랫폼이다. 아두이노를 사용해 독립형 인터엑티브 장치를 개발할 수도 있고 여러분의 컴퓨터(플래시, 프로세싱, VVVV, Max/MSP)와 연동할 수도 있다. 보드는 직접 조립하거나, 조립된 상태로 구입할 수 있다. 오픈 소스인 IDE(통합 개발 환경) 은 다음 링크에서 자유롭게 다운로드 할 수 있다. www.arduino.cc

다음과 같은 특징들이 아두이노를 다른 플랫폼과 구별해 준다.

  • 멀티 플랫폼 환경이다 : 윈도, 매킨토시, 리눅스에서 실행 가능 하다.
  • 아티스트와 디자이너들이 사용하기 쉬운 개발환경인, 프로세싱 프로그래밍 IDE에 기반을 두었다.
  • 시리얼 케이블이 아닌 USB 케이블을 통해 프로그램 할 수 있다. 최근의 컴퓨터에는 시리얼 포트가 없는 경우가 종종 있기 때문에, 이 특징은 유용하다.
  • 하드웨어와 소프트웨어 모드 오픈소스로 여러분이 원한다면 회로도를 다운로드 받고, 따로 모든 부품들을 구입하여 여러분만의 아두이노를 만들 수 있다. 아두이노의 창시자들에게 어떠한 대가도 지불할 필요 없다.
  • 하드웨어가 저렴하다. USB 보드는 대략 3~4만 원 정도이며 보드 상에 터버리거나 한 부품들을 교체하는 비용도 5천 원 정도를 넘지 않는다. 여러분도 실수에 대한 이정도의 대가는 지불할 수 있을 것이다.
  • 활발한 사용자 커뮤니티가 존재한다. 고로 문재가 생기면 도와줄 사람이 많다.
  • 아두이노 프로젝트는 교육 환경으로 개발되었기 때문에, 막 시작했지만 빨리 작동하는 결과를 얻고 싶어 하는 사람들에게 최적이다.

이 책은 초보자들이 아두이노 플랫폼을 어떻게 사용하는지를 배우고, 아두이노의 철학을 적용하여 얻는 장점들을 이해하는 것을 돕도록 구성되었다.

대상 독자

이 책은 “원래의” 아두이노 사용자들인, 디자이너와 아티스트들을 위해 쓰였다. 그런고로, 엔지니어들이라면 아마도 참을 수 없는 방법으로 설명을 하고 있다. 사실, 엔지니어 중 한 명은 저자가 쓴 도입 장의 초고를 “허접 데기”라고 불렀다. 그 말이 정확히 맞다. 사실 대부분의 엔지니어들은 그들이 하는 일을 보통 사람은 말할 것도 없고, 다른 엔지니어에게도 설명하지 못한다. 그럼 이제부터 이 허접한 것들을 깊이 파고들어 보자.

참고: 아두이노는 헤르난도 베르간(Hernando Barragan)이 이탈리아 이브레아 IDII에서 저자와 케이시 리스(Casey Reas)하에서 공부하며 작성한 와이어링(Wiring) 플랫폼을 기반으로 한 논문을 바탕으로 만들어졌다.

아두이노가 대중화 되어감에 따라 경험자들, 취미가들, 각 분야의 해커들이 아두이노를 사용해 아름답거나 기괴한 물건들을 만들어 내는 것을 보게 되었다. 나는 여러분 모두가 스스로 자신을 아티스트이며 디자이너라고 여길 권리가 있다는 것을 깨달았다. 따라서 이 책은 바로 당신을 위한 책이기도 하다.

아두이노는 인터렉션 디자인(Interaction Design: 상호 작용하는 디자인)을 가르치기 위해 태어났다. 이런 디자인을 하기 위해서는 반드시 프로토타입을 만드는 과정을 거치게 된다. 인터렉션 디자인에 대한 정의는 많지만 내가 좋아하는 것은 다음 것이다:

인터렉션 디자인은, 모든 종류의 주고받는 경험에 대한 디자인이다.

오늘날 인터렉션 디자인은 우리(사람)와 물체들 간 의미 있는 경험을 만드는 것이라 여겨진다. 이는 우리와 기술 간의 아름다운-그리고 아마도 논란이 될 수도 있는-경험의 창조를 살펴보기 위한 좋은 방법이다. 인터렉션 디자인은 계속 완성도를 높여가는 프로토 타입을 사용한 쌍방향 과정을 통한 디자인 방법이 좋다. 이러한 접근방법-이는 또한 일부 “전통적인” 디자인의 한 부분이다-은 기술을 사용한 프로토타입, 특히 전자기술을 사용한 프로토타입을 만드는 것을 포함하게 확장될 수 있다.

특히 아두이노를 사용한 인터렉션 디자인은 피지컬 컴퓨팅(또는 피지컬 인터렉션 디자인)으로 구분된다.

피지컬 컴퓨팅이란?

피지컬 컴퓨팅에서는 디자이너나 아티스트들이 새로운 물체의 프로토타입을 만드는데 전자지식을 사용한다.

여기에는 마이크로컴퓨터(칩 안에 들어있는 작은 컴퓨터)안에 들어있는 소프트웨어를 실행해 동작을 구현한 센서와 엑튜레이터를 통해 사람과 소통하는 인터렉티브 물체의 디자인도 포함되어 있다.

과거에는 전자지식을 사용하기 위해서는 처음부터 끝까지 엔지니어를 상대해야만 했고, 회로를 만드는 일은 한 번에 하나의 작은 부품을 만드는 것을 의미했었다: 이런 문제점들 때문에 창조적인 사람들은 중간 부분을 직접 가지고 놀 수 없었다. 대부분의 도구들은 엔지니어들만 사용할 수 있었고 전문 지식이 필요했다. 최근에 들어서, 마이크로컨트롤러들이 점점 더 싸지고 사용하기 쉬워졌기 때문에, 더 좋은 도구들을 만들 수 있게 되었다.

아두이노를 통해 우리가 만든 진전은 이러한 도구들을 무경험자들에게 한걸음 더 가깝게 해 주었기 때문에, 2~3일 정도의 워크숍만으로도 사람들이 이것저것을 만들기 시작할 수 있게 해 준다.

아두이노를 사용하면, 디자이너나 아티스트도 전자와 센서들에 대한 기초 지식들을 얻을 수 있고, 아주 적은 노력만으로 프로토타입들을 만들기 시작할 수 있다.

2/아두이노 방식

아두이노의 철학은 말로 설명하는 것 보다는 디자인을 직접 만드는 것에 기반을 두고 있다. 이것은 더 나은 프로토타입을 만들기 위한 더 빠르고 강력한 방법을 찾아 온 결과이다. 우리는 여러 프로토타이핑 기술들과 손을 사용해 생각하는 방법들을 거쳐 왔다.

종래의 엔지니어링은 A로 부터 B를 얻는 고정된 과정을 기반을 두고 있는데 반해, 아두이노 방식에는 그 과정에서 길을 잃고 C를 찾아낼 수도 있다는 즐거움이 있다.

이는 우리가 찾아낸 팅커링 방법으로-목표가 정하지 않은 채로 놀다가 기대하지 않았던 것들을 찾는 것이다. 또한, 더 나은 프로토타입을 만들기 위한 방법을 찾는 과정에서 우리는 소프트웨어와 하드웨어의 중간단계를 수정할 수 있게 해 주는 몇몇 소프트웨어 패키지들을 선택했다.

이 뒤에 올 몇 섹션들 에서는 아두이노 방식에 영감을 준 몇몇 철학과, 이벤트, 개척자들을 소개한다.

프로토타이핑

프로토타입을 만드는 것은 아두이노 방식의 심장이다. 우리는 다른 물체들은 물론 사람, 네트워크들과 상호 작동하는 물건을 만든다. 우리는 최대한 싸게 프로토타입을 만들기 위한 간단하고 빠른 방법을 찾기 위해 노력해 왔다.

전자를 처음 시작하는 많은 사람들은 우선, 아무것도 없는 상태에서 시작해 모든 것들을 만드는 방법을 배워야 한다고 생각한다. 이는 에너지의 낭비다: 여러분이 정말로 원하는 것은 매우 단시간 안에 무엇인가가 동작하는 것을 확인하는 것으로, 그럼으로써 여러분 스스로가 다음 단계로 넘어갈 동기가 부여되거나, 더 나아가 누군가가 여러분에게 그 일을 계속하라고 많은 돈을 주도록 동기를 부여할 수도 있다.

이미 만들어진 장치들을 해킹해서 커다란 회사의 좋은 엔지니어들이 열심히 노력한 결과를 이용할 수 있는데, 왜 시간과 깊은 기술 지식을 요하는, 처음부터 모두 만들어 내기 위해 시간과 에너지를 낭비하는가?

우리가 본받아야할 사람을 한명 소개하자면 제임스 다이슨을 꼽을 수 있다. 그는 원하는 대로 동작하는 만족스러운 진공청소기를 만들기 위해 5127개의 프로토타입을 만들었었다. (www.international.dyson.com/jd/1947.asp).

팅커링

우리는 이것이 기술과 놀기 위한 필수 과정이라고 믿는다. 목표를 확실히 정하지 않은 채로도-하드웨어와 소프트웨어의 다른 가능성을 찾아보는 것이다. 우리는 팅커링이 기술을 사용해 놀기 위해 꼭 필요한 과정이라고 믿는다. 때로는 확실한 목표를 정하지 않은 채로-하드웨어와 소프트웨어의 다른 가능성을 찾아보는 것이다.

이미 존재하는 기술을 재사용하는 것은 최고의 팅커링 방법이다. 싸구려 장난감 또는 오래되어 사용하지 않는 기계들을 구해서 무언가 새로운 것을 하도록 만드는 것은, 훌륭한 결과를 얻기 위한 최고의 방법 중 하나이다.

이어붙이기

모듈 방식과, 간단한 장치들을 연결하여 복잡한 시스템을 만드는 능력은 언제나 저자를 매료시켰다. 로버트 무그(Rovert Moog)가 만든 아날로그 신디사이저는 이런 과정을 잘 보여준다. 음악가들을 각각의 모듈들을 케이블로 “이어붙이는”방법으로 수없이 많은 조합을 시도하여 소리들을 구성해 냈다. 이런 접근 방법은 신디사이저를, 셀 수없이 많은 노브들로 조합되는 것을 제외하면, 오래된 전화 교환기처럼 보이게 하지만, 이 장치는 소리로 팅커링 하기 위한 그리고, 혁신적인 음악을 위한 완벽한 플랫폼이다. 무그는 이것을 “목격과 발견의 중간” 과정이라고 설명했다. 처음에는 대부분의 음악가들이 이 수백가의 노브들이 무엇인지 알 수 없겠지만, 계속 시도해 보는 과정에서, 중관에 멈추는 과정 없이 그들만의 스타일을 정제해 낼 수 있을 것이라고 확신한다.

창의적인 작업을 위해서는 진행 과정 중 끼어드는 것들을 줄여야 한다. 과정이 더 매끄럽게 진행될수록 더 많은 팅커링이 일어난다.

이런 기술들은 소프트웨어 세상에도 반영되어 그 결과 Max, PureData, VVVV같은 “비주얼 프로그래밍” 환경이 되었다. 이런 도구들에서는 제공되는 각기 다른 기능들이 “상자”로 보이며, 사용자들이 이 박스들을 “선으로 이어 붙여서” 연결할 수 있다.

이런 환경들은 사용자들이 보통의 개발 주기인, “프로그램을 치고, 컴파일하고, 망할 에러!, 에러를 고치고, 다시 컴파일, 실행”하는 과정에서 일반적으로 겪게 되는 일정한 방해 없이도 프로그래밍을 하는 경험을 준다. 여러분이 좀 더 시작 지향적이라면 이들 환경을 시도해 볼 것을 권장한다.

서킷 밴딩

서킷 밴딩(Circuit bending)은 가장 흥미로운 팅커링 형태 중 하나이다. 이것은 기타 이펙트 페달 같은 음악 장비, 어린이 장난감들, 작은 신디사이저 등의 낮은 전압이나 배터리로 작동하는 전자 장치의 회로를 위해 창조적으로 쇼트 시켜서 새로운 악기나, 소리 생성기를 만드는 일이다. 이 과정의 근원에는 “우연이 얻게 되는 예술”이 있다. 서킷 밴딩은 1996년에, 리드 가자라(Reed Ghazala)가 우연히 그의 책상 서랍에 있던 금속 물체로 장난감 앰프를 쇼트 시키자 평소와 다른 소리가 흘러나온 것부터 시작되었다. 필자는 좋아하는 것은 서킷 밴딩을 하는 사람들이 이론적으로는 자기가 무엇을 하는지 이해할 필요가 없이도 팅커링를 통해 가장 엉뚱발랄한 장치들을 만드는 능력이다

Sniffin'glue

아두이노의 방식의 여기에 있는 스니핑글루 팬진3)과 다소 닮았다: 펑크 영역에서는 세 가지 기타 코드만 안다면 밴드를 시작할 수 있다. 한 분야의 전문가 여러분에게 당신은 절대 전문가가 되지 못할 거라고 말하지 못하게 하라. 그들의 말을 무시하고 그들을 깜작 놀라게 하자.

키보드 해킹

컴퓨터 키보드는 60년이 넘도록 컴퓨터와 소통하기 위한 주요 수단으로 쓰이고 있다. MIT 미디어랩의 대장(학장)인 알렉스 펜트렌드 다음과 같이 언급한 적이 있다. “이런 표현이 껄끄러울 수도 있지만, 소변기가 컴퓨터 보다 더 똑똑하다. 컴퓨터는 주변 환경에서 고립되어 있기 때문이다.”4)

팅커러 라면, 우리는 키를 주변 환경을 감지할 수 있는 물체로 교체하여 상호 소통하는 새로운 방법을 소프트웨어로 구현할 수 있다. 컴퓨터 키보드를 떼어내어 아주 간단한 (그리고 싼) 장치로 되살리자. 키보드의 주요 부품은 작은 보드이다. 보드는 일반적으로 냄새가 나는 녹색이나 갈색의 회로로, 각각의 키들의 접점들을 가지고 있는 두개의 플라스틱판으로 연결되는 두 세트의 접점들이 있다. 이 회로를 제거하여 전선을 사용해 두 접점을 연결해 보면, 컴퓨터 화면에 글자가 나타나는 것을 볼 수 있을 것이다. 밖으로 나가 동작-감지기를 구입하여 이를 여러분의 키보드에 연결하면, 컴퓨터 앞으로 누군가가 지나갈 때 마다 키가 입력되는 것을 볼 수 있을 것이다. 이 장치를 여러분이 좋아하는 소프트웨어에 연결하면, 이제 여러분은 소변기만큼 똑똑한 컴퓨터를 만들게 되는 것이다. 키보드 해킹에 대해 배우는 것은 프로토타이핑과 피지컬 컴퓨팅의 중요한 빌딩 블록이다.

우리는 고물이 좋아

요즘 사람들은 구형 프린터, 컴퓨터, 희한한 사무기기, 기술 장비, 군용 물품 같은 수많은 과학 기술들을 버린다. 특히 젊고 가난한 해커들과 갓 입문한 초심자에게 유용한 이 넘치는 과학 기술을 위한 커다란 시장은 항상 있어왔다. 이런 시장은 우리가 아두이노를 개발한 곳인 이탈리아 이브레아에서도 분명히 있었다. 이 도시는 올리베티(옮긴이 주: Olivetti 이탈리아의 컴퓨터 회사)사의 본사가 있던 곳이다. 이 회사는 1960년대부터 컴퓨터를 만들어 왔다. 1990년대 중반에 들어 그들은 고물상에 모든 종류의 것들을 버렸다. 그 곳에는 컴퓨터 부품들, 전자 부품들 및 모든 종류의 이상한 장치들이 가득 있었다. 우리는 수없이 많은 시간을 그곳에서 보냈고, 아주 적은 돈으로 모든 종류의 기묘한 장치들을 구입하여, 우리의 목적에 맞게 해킹하였다. 여러분이 커다란 스피커 천개를 매우 적은 돈으로 구입할 수 있다면, 여러분도 머릿속에도 결국 어떤 아이디어가 떠오르게 될 것이다. 아무것도 없는 상태에서 만들기 시작하기에 앞서 쌓아놓은 고물들을 사용해 보자.

장난감 해킹

앞서 언급된 서킷 벤딩에서 증명한 것처럼 장난감들은 해킹하고 재사용하기 위한 값싼 기술들의 보고이다. 요즘에는 중국에서 만든 첨단 기술의 매우 값 싼 장난감이 넘쳐나기 때문에, 갑자기 떠오른 아이디어를 소리 나는 고양이 인형들과 광선검 장난감들을 조합해 만들어 볼 수도 있다.

저자는 학생들에게 기술은 무섭거나 접근하기 어려운 것이 아니라는 것을 이해시키기 위해 이 방법을 몇 년간 사용해 왔다. 저자가 참고하는 책자 중 가장 마음에 드는 것은 (Usman Haque)과 (Adam Somlai-Fischer)의 “낮은 기술의 센서와 엑츄에이터(Low Tech Sensors and Actuators)” (lowtech.propositions.org.uk)이다. 이 책은 장난감 해킹 기술을 완벽하게 설명하고 있으며, 저자도 이 책을 계속 사용하고 있다.

협력

사용자간 협력은 아두이노 세상의 중요한 정책 중 하나이다. www.arduino.cc 에 위치한 포럼을 통해 전 세계 각 분야의 사람들이 서로 도우며 아두이노 플랫폼을 배우고 있다. 아두이노 팀은 방문하는 모든 도시에서 지역 사용자 모임을 만들도록 도움으로서, 사람들이 서로 협력하도록 독려하고 있다. 또한, “놀이터(Playground)“라는 위키(www.arduino.cc/playground)를 구성해 두어 사용자들이 그들이 발견한 것을 이곳에 문서화 할 수 있다. 사람들이 얼마나 많은 지식들을 모든 사람들이 사용할 수 있게 웹상에 올리는지 놀랍다. 저자는 이러한 공유와 서로 돕는 문화를 아두이노에 관련한 것들 중 가장 자랑스럽게 생각한다.

3/아두이노 플랫폼

아두이노는 두개의 주요 부분으로 구성되어 있다: 여러분이 물건을 만들 때 기반으로 작업을 하게 될 아두이노 보드와, 여러분의 컴퓨터에서 실행되는 소프트웨어인 아두이노 IDE가 그것이다. 아두이노 IDE를 사용해 아두이노 보드에 올릴(upload) 스케치(작은 컴퓨터 프로그램)를 만들 수 있다. 스케치는 보드가 무슨 일을 할 지 알려주게 된다.

그리 오래지 않은 과거만 해도, 하드웨어 작업을 한다는 것은 레지스터, 커패시터, 인덕터, 트랜지스터 같은 이상한 이름을 가진 부품들을 수백 개 사용해서 아무것도 없는 상태에서 부터 회로를 만들어 내야 함을 의미했었다.

하나의 특정 작업(application)을 위해서 모든 회로는 전선으로 연결 되어 있었고, 수정을 하려면 전선을 자르고, 접점을 납땜하는 등의 일이 필요했다.

디지털 기술과 마이크로세서의 등장으로, 예전에는 배선을 통해 구현했던 기능들을, 소프트웨어 프로그램들을 사용해 구현할 수 있게 되었다.

소프트웨어는 하드웨어에 비해 수정하기가 더 쉽다. 몇 번의 키 입력으로 신속하게 장치의 논리 구조를 바꿀 수 있고, 저항 몇 개를 땜질할 정도의 시간이면 두 세 버전의 소프트웨어를 시험해 볼 수 있다.

아두이도 하드웨어

아두이노 보드는 작은 마이크로컨트롤러 보드이다. 마이크로컨트롤러 보드란, 작은 칩(마이크로 컨트롤러)안에 컴퓨터 전체를 구현한 부품을 포함하는 자극 회로 기판(보드)이다. 이 컴퓨터는 저자가 이 책을 쓰는데 사용하고 있는 맥북에 비해 적어도 천 배는 더 저 성능이다. 하지만 훨씬 싸며 재미있는 장치들을 만드는데 매우 유용하다. 아두이노 보드를 보면, 28개의 “다리”가 달린 검은색 칩을 볼 수 있다-이 칩이 ATmega3285)로 여러분의 보드의 심장이다.

우리(아두이노 팀)는 이 마이크로컨트롤러가 잘 동작하고, 여러분의 컴퓨터와 통신하기 위해 필요한 모든 부품들을 아두이노 보드에 준비해 두었다. 보드는 여러 가지 버전이 존재하는데, 이 책에서 우리가 사용할 것은 Arduino Duemilanove로, 가장 간단하게 사용할 수 있으며, 배우기에 최적인 보드이다. 하지만 이 책의 학습 과정들은 바로 전 버전인 Arduino Diecimila 보드와 더 오래된 Arduino NG 같은 이전 버전의 보드들에도 적용된다. 그림 3-1에서 Arudino Duemilanove를 볼 수 있다. 그림 3-2는 오래 된 Arduino NG 보드이다.

이들 그림들은 아두이노 보드를 확인할 수 있다. 처음에는, 이 모든 커넥터들이 약간 혼란스러울 수도 있다. 보드를 구성하고 있는 모든 부분들에 대한 설명이 여기 있다:

  • 14개의 디지털 입/출력 핀(핀 0~13)
    • 이 핀들은 입력 또는 출력으로 사용할 수 있으며, IDE를 사용해 만든 스케치를 통해 어떻게 사용할 지 결정하게 된다.
  • 6개의 아날로그 입력 핀 (핀 0~5)
    • 이 핀들은 오직 아날로그 입력으로만 쓰이며 아날로그 값(예, 센서를 통해 읽은 전압 값)을 받아 0~1023사이의 숫자로 변환하게 된다.
  • 6개의 아날로그 출력 핀 (핀 3,5,6,9,10,11)
    • 디지털 핀들 중 6개는 사실, IDE를 사용해 작성한 스케치를 통해 아날로그 출력으로 재 프로그램 할 수 있다.

보드는 여러분의 컴퓨터의 USB포트나, 거의 모든 종류의 USB 충전기 또는 AC어댑터(9 볼트 권장, 2.1mm 원형 팁, 중앙이 양극)로 부터 전원을 공급받을 수 있다. 만약 전원 소켓에 전원을 꽂지 않으면 USB에서 전원을 사용하게 되지만, 보드에 전원을 꽂자마자 바로 외장 전원을 자동으로 사용하게 된다.

참고: 만약 여러분이 오래된 아두이노인 아두이노-NG또는 아두이노 Diecimilla를 사용한다면, (보드에 PWR_SEL이라고 적힌) 점퍼 스위치를 사용해 외장 전원(EXT)과 USB전원 중 어떤 전원을 사용할 지 선택해야 한다. 이 점퍼는 AC어댑터 플러그와 USB 포트 사이에 위치해 있다.

그림 3-1. Arduino Duemilanove
그림 3-2. Arduino NG

소프트웨어 (IDE)

IDE(Integrated Development Environment: 통합 개발 환경)은 여러분의 컴퓨터에서 돌아가는 특별한 프로그램으로, 이 프로그램을 사용해 프로세싱(www.processing.org) 언어에 기반을 둔 간단한 프로그래밍 언어로 아두이노 보드에서 사용할 스케치를 작성할 수 있다.

여러분이 보드에 스케치 올리기 버튼을 누르면 마법 같은 일이 일어난다. 여러분이 작성했던 코드는 C 언어(보통 초보자들이 사용하기에는 꽤 어려운 언어)로 번역되어, avr-gcc 컴파일러에 전달된다. 컴파일러는 오픈 소스 소프트웨어 중 중요한 부분으로 프로그래밍 언어를 마이크로컨트롤러가 이해할 수 있도록 마지막 변환 작업을 수행한다. 이 마지막 단계는 정말 중요한데, 왜냐하면 이 부분이 아두이노가 마이크로컨트롤러를 프로그래밍 하는 복잡한 작업을 최대한 숨김으로서 여러분의 삶을 단순하게 해 주는 부분이기 때문이다.

아두이노의 프로그래밍 작업 사이클은 기본적으로 다음과 같다:

  • 아두이노 보드를 여러분의 컴퓨터의 USB 포트에 꽂는다.
  • 보드에 생명을 불어 넣을 스케치를 작성한다.
  • USB 연결을 통해 보드에 스케치를 올리고, 보드가 재 시작하기까지 몇 초 종안 기다린다.
  • 여러분이 작성한 스케치를 보드가 실행한다.

참고: 이 글을 쓰는 시점에서 리눅스에 아두이노를 설치하는 것은 다소 복잡하다. 리눅스에서의 설치 전 과정은, 다음 링크에 위치한 설명을 참고하기 바란다. www.arduino.cc/playground/Learning/Linux

컴퓨터에 아두이노 설치하기

아두이노 보드를 프로그램 하기 위해서는 우선, 반드시 다음 주소에서 개발 환경 (IDE)을 다운로드 받아야 한다. www.arduino.cc/en/Main/Software 여러분이 사용하고 있는 오퍼레이팅 시스템에 맞는 버전을 선택하라.

파일을 다운로드 한 후 더블-클릭하여 압축을 푼다. 이제 arduino-[버전] 형식의 폴더가 생성될 것이다. 예를 들어 글을 쓰고 있는 시점의 최신 버전을 다운 받았다면 arduino-0017라는 폴더가 만들어진다. 이 폴더를 드래그 하여 여러분이 아무 곳이나 여러분이 원하는 곳, 바탕화면이나 (맥 에서는) /Application 폴더, (윈도 에서는) C:\Program Files 폴더 같은 곳에 두도록 한다. 이제 아두이노 IDE를 실행하고 싶으면 방금 옮겨 둔 아두이노 폴더를 열어서 아두이노 아이콘을 더블클릭하면 된다. 아직 아두이노를 시작하지 마라. 먼저 해야 할 일이 한 가지 더 있다.

참고: 아두이노 IDE를 실행하는데 문제가 있다면, 7장 문제해결을 참조하라.

이제 여러분의 컴퓨터와 아두이노 보드가 USB 포트를 사용해 대화 하도록 하기 위해 반드시 드라이버를 설치해야 한다.

드라이버 설치: 매킨토시

arduino-0017안의 Drivers 폴더를 찾아, FTDIUSBSerialDriver_x_x_x.dmg(x_x_x 대신 드라이버의 버전 넘버가 있을 것이다. 예. FTDIUSBSerialDriver_v2_2_9_Intel.dmg)라는 파일을 찾아라. .dmg 파일을 더블클릭하여 마운트 한다.

참고: 맥북, 맥북 에어, 맥북 프로, 인텔기반 맥 미니 혹은 i맥과 같은 인텔 기반의 맥을 사용 중이라면, 반드시 FTDIUSBSerial-Driver_v2_2_9_Intel.dmg 처럼 드라이버의 이름에 “Intel”이 포함되어 있는 것을 설치하라. 인텔 기반의 맥북을 사용하지 않는다면 이름에 “Intel”이 빠진 드라이버를 설치한다.

다음으로, FTDIUSBSerialDriver 패키지를 더블클릭하여 소프트웨어를 설치한다. 인스톨러에서 제공하는 지시들을 따르며, 물어본다면 관리자 암호를 입력한다. 설치과정의 끝에서, 드라이버가 잘 로드 되었는지 확실히 하기 위해 여러분의 컴퓨터를 재시작(restart) 한다. 이제 아두이노 보드를 여러분의 컴퓨터에 연결한다. PWR LED에 불이 들어올 것이며 “L”이라고 표시된 노란 LED가 깜박이기 시작할 것이다. 그렇지 않다면 7장 문제해결을 참조하라.

드라이버 설치: 윈도

아두이노 보드를 컴퓨터에 연결한다. 새 하드웨어 검색 마법사 창이 뜨고, 윈도는 드라이버를 먼저 윈도 업데이트 사이트에서 찾으려 할 것이다.

윈도 XP의 경우 여러분에게 윈도 업데이트(Windows Update)를 검사할지 물어본다. 윈도 업데이트를 사용하지 않기를 원한다면 “아니요, 지금 연결 안함” 옵션을 선택하고 다음 버튼을 클릭한다.

다음 화면에서 “목록 또는 특정 위치에서 설치”를 선택하고 다음으로 진행한다.

“검색할 때 다음 위치 포함”이라고 적힌 체크박스를 선택하고, 찾아보기를 클릭해 여러분이 아두이노를 설치한 폴더를 찾은 뒤, drivers\FTDI USB Drivers 폴더를 선택한다. 확인을 선택하고, 다음 버튼을 누른다.

윈도 비스타의 경우 우선 윈도 업데이트(Windows Update)를 찾는 시도를 한다. 검색에 실패하면, Drivers\FTDI USB Drivers 폴더를 검사하도록 해 주어야 한다. 이 과정을 두 번 해야 하는데, 왜냐하면, 컴퓨터가 우선 저 수준 드라이버를 설치한 후, 아두이노 보드를 컴퓨터에게 시리얼 포트처럼 보이게 하기 위한 코드들을 설치하기 때문이다.

드라이버가 설치되었으면, 이제 아두이노 IDE를 실행시켜 아두이노를 사용할 수 있다.

다음으로, 어떤 시리얼 포트가 아두이노에게 할당되어 있는지 찾아야 한다. 추후 아두이노를 프로그램 할 때 이 정보가 필요하다. 이 정보를 얻는 방법은 다음 섹션에서 확인할 수 있다.

포트 지정: 매킨토시

아두이노 IDE의 Tools 메뉴에서 “Serial Port”를 선택한 후 /dev/cu.usbserial- 로 시작하는 포트 이름을 선택한다. 이 포트 이름을 사용해 여러분의 컴퓨터는 아두이노를 사용하게 된다. 그림 3-3 에서 포트 리스트를 볼 수 있다.

그림 3-3. 아두이노 IDE의 시리얼 포트 리스트

포트 지정: 윈도

윈도에서는 이 과정이 -적어도 처음에는- 조금 더 복잡하다. 시작 메뉴를 클릭한 후 컴퓨터(비스타) 또는 내 컴퓨터(XP)에서 오른쪽 클릭한 후, 속성 선택하여 시스템 등록 정보 창을 연다. 윈도 XP에서는 하드웨어 탭을 클릭하고 장치 관리자를 선택한다. 비스타에서는 장치 관리자(창의 왼쪽에 있는 작업 목록에서 찾을 수 있다)를 클릭한다. “포트 (COM & LPT)” 밑에서 아두이노 장치를 찾는다. 아두이노는 USB 시리얼 포트 (USB Serial Port)로 보이며, 그림 3-4 에서 보이는 바와 같이 COM3 같은 이름일 것이다.

그림 3-4. 윈도 장치 관리자에서 확인할 수 있는 모든 사용 가능한 시리얼 포트들

참고: 윈도가 설치된 컴퓨터 중 일부에서는 COM 포트 가 9보다 큰 포트번호를 가지고 있을 것이다. 이런 큰 번호의 포트들은 아두이노와 통신하는데 문제가 되기도 한다. 7장 문제해결 에서 이 문제에 대한 도움을 확인하자.

할당된 COM 포트를 알아낸 후에, 이 포트를 아두이노 IDE의 Tools > Serial Port 메뉴에서 선택한다. 이제 아두이노 개발 환경이 아두이노 보드와 대화할 수 있게 되었고, 보드를 프로그램 할 수 있다.

4/정말로 아두이노 시작하기

이제 여러분은 인터렉티브 장치를 만들고 프로그램 하는 방법을 배울 것이다.

인터렉티브 장치의 해부도

우리가 아두이노를 사용해 만드는 물건들은 “인터렉티브 장치”라는 아주 간단한 패턴을 따르게 된다. 인터렉티브 장치는 전자 회로로, 센서(실제 세계를 측정해 전자 신호로 변환해 주는 전자 부품)를 통해 주변 환경을 감지할 수 있다.

이러한 장치는 센서를 통해 받은 내용을 소프트웨어로 구현된 행동을 따라 처리한다. 그리고 엑츄에이터(acturator)라 불리는 전자 신호를 물리적 행동으로 바꾸는 장치를 통해 실제 세상과 교감한다.

그림 4-1. 인터렉티브 장치

센서와 엑츄에이터

전자 장치는 센서와 엑츄에이터를 통해 실제 세상과 교감한다. 마이크로컨트롤러는 아주 간단한 컴퓨터이기 때문에 오직 전기 신호(우리의 뇌신경들 사이에 오가는 전기 신호 같은 것)만을 처리할 수 있다. 마이크로컨트롤러가 빛이나, 온도, 물체의 양등을 감지하기 위해서는 이들을 전기신호로 변환해주는 무엇인가가 필요하다. 예를 들면, 우리의 몸에서는 눈을 통해 빛을 뇌가 받아들일 수 있는 신호로 변환하게 된다. 전자의 세상에서는 수광센서(LDR 또는 감광저항)를 사용해 센서의 표면에 비춰진 빛의 양을 측정해 마이크로컨트롤러가 이해할 수 있는 신호로 변환한다.

센서로 부터 읽어 온 후에는, 장치가 어떻게 반응할 지 결정하기 위한 정보가 필요하게 된다. 이 의사결정 과정은 마이크로컨트롤러를 통해 이루어지며, 엑튜레이터를 사용해 반응을 수행한다. 예를 들어, 우리의 몸에서는 뇌로부터 전기 신호를 받은 근육이 움직임(반응)을 만들어낸다. 전자의 세상에서는 빛이나 전기 모터를 사용해 이와 같은 세상으로의 반응을 만들어낸다.

다음 섹션에서 여러분은 어떻게 각기 다른 종류의 센서들을 읽고, 엑츄에이터를 제어하는 방법을 배우게 될 것이다.

LED 깜박이기

LED를 깜박이는 스케치는 여러분의 아두이노 보드가 잘 작동하고 제대로 설정되었는지 확인하기 위한 첫 번째 프로그램이다. 이 프로그램은 또한 마이크로컨트롤러를 프로그램 하는 방법을 배우기 위해 가장 먼저 해 보는 프로그래밍 실습이기도 하다. 발광다이오드(LED)는 작은 전자 부품으로 전구와 비슷하다고 볼 수 있다. 하지만 전구에 비해 더 효율적이며, 낮은 작동 전압을 사용한다.

아두이노 보드에는 하나의 LED가 기본 장착되어 있는데, “L”이라는 표시가 되어 있다. 또한 여러분이 그림 4-2에서 보이는 것처럼 LED를 추가할 수도 있다.

K는 캐소드(음극)로 짧은 다리 쪽이며, A는 애노드(양극)로 긴 다리 쪽이다.

LED를 연결하였으면, 아두이노에게 무엇을 할 지 알려주어야 한다. 코드가 이런 일을 하게 된다. 코드는 마이크로컨트롤러를 우리가 원하는 대로 동작하게 하기 위한 일련의 명령어 들이다.

그림 4-2. LED를 아두이노에 연결하기

여러분의 컴퓨터에서 아두이노 IDE를 복사해 둔 폴더를 열어, 아두이노 아이콘을 더블클릭해서 실행 한다. File > New 메뉴를 선택하면 스케치 폴더 이름을 선택하라는 질문이 나온다. 그 위치에 아두이노 스케치가 저장된다. Blink_LED 라는 이름으로 입력하고 OK를 누른다. 그리고 아래의 코드 (예제 01) 를 아두이노 스케치 편집기 (아두이노 IDE의 메인 윈도우)에 적자. 이 코드는 www.makezine.com/getstartedarduino 에서 다운로드 받을 수도 있다. 이제 그림 4-3.과 같은 모습일 것이다.

// 예제 01 : LED 깜박이기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED 13   // LED는 디지털 핀
                // 13번에 연결되어 있음
 
void setup()
{
  pinMode(LED, OUTPUT);    // 디지털 핀을
                           // 출력으로 설정
}
 
void loop()
{
  digitalWrite(LED, HIGH);   // LED를 켠다
  delay(1000);               // 1초 동안 대기
  digitalWrite(LED, LOW);    // LED를 끈다
  delay(1000);               // 1초 동안 대기
}
그림 4-3. 여러분의 첫 스케치를 불러온 아두이노 IDE 

IDE에 코드를 작성했으면 이제 틀린 곳이 없는지 확인해 볼 필요가 있다. “Verify” 버튼(그림 4-3 에 위치가 표시되어 있다)을 누르자. 틀린 곳이 없다면 “Done compiling” 이라는 문구가 아두이노 IDE의 하단에 나타난다. 이 문구는 아두이노 IDE가 여러분의 스케치를 보드 상에서 돌아가는 실행 프로그램(윈도의 .exe파일이나 맥의 .app와 유사하다가 볼 수 있다)으로 번역했음을 의미한다.

이제 그 프로그램을 보드에 올려(upload) 볼 수 있다. (그림 4-3에 표시된) Upload to I/O Board 버튼을 누르자. 강제로 현재 수행중인 동작을 멈추고, USB를 통해 들어오는 명령들을 수신하기 위해 보드가 리셋 된다. 아두이노 IDE가 보낸 현재의 스케치는 보드의 메모리에 저장된 후 동작하기 시작한다.

프로그램 창 하단의 검은 영역에 몇몇 문구들이 나타난 뒤, 모든 과정이 잘 마무리 되었다는 표시로, 그 바로 위쪽 영역에 “Done upload-ing”이라는 문구가 표시될 것이다. 보드 상에는 RX와 TX라 표시된 두개의 LED가 있다. 이 LED들은 한 바이트를 보내거나 받을 때 마다 깜박인다. 업로드 중에는 두 LED가 계속 깜박거린다.

만약에 그 LED들이 깜박거리지 않거나 “Done uploading” 문구 대신 오류 문구가 나온다면 여러분의 컴퓨터와 아두이노 간 커뮤니케이션에 문제가 있는 것이다. Tools > Serial Port 메뉴에서 시리얼 포트를 맞게 설정했는지 (3장 참고) 확인 확인해 보자. 또한 Tools > Board 메뉴에서 올바른 아두이노 모델을 선택했는지도 살펴보자.

여전히 문제가 남아있다면 7장 문제해결을 살펴보라.

일단 아두이노에 올라간 코드는 다른 스케치를 올리기 전 까지 유지된다. 여러분의 컴퓨터의 하드 드라이브 와 비슷하게, 보드가 리셋 되거나 꺼졌을 때도 스케치는 지워지지 않는다.

스케치가 제대로 올라갔다면, “L” 표시의 LED가 1초마다 꺼졌다 켜졌다 하는 것을 볼 수 있을 것이다. 지난 그림 4-2 처럼 LED를 추가로 설치했다면 그 LED도 같이 깜박인다.

여러분이 방금 작성해서 실행한 것을 “컴퓨터 프로그램” 또는, 아두이노 프로그램(IDE)에서 지칭하기로는 스케치라고 한다. 앞서 언급했듯이, 아두이노는 작은 컴퓨터로 여러분이 원하는 대로 프로그램 할 수 있다. 아두이노 IDE에서 프로그래밍 언어를 사용해 작성한 일련의 명령들은 아두이노 보드에서 실행 가능하도록 변환되어 실행된다. 차차 여러분에게 스케치를 이해하는 방법을 보여주도록 하겠다. 우선, 아두이노는 가장 위 부분에서 마지막 까지 차례로 코드를 실행한다. 해서 가장 위에 있는 첫 줄을 가장 먼저 읽고 차례로 아래로 내려가게 된다. 이는 흡사 퀵타임 플레이어나 윈도우 미디어 플레이어 같은 비디오 플레이어의 재생 위치가 좌에서 우로 이동하며 영화의 어디쯤을 보고 있는지 알려주는 동작과 비슷하다.

소금 좀 주세요

코드 중 중괄호( {, } )를 주목해 보자. 이는 여러 줄의 코드를 묶는데 사용되며, 특히 명령어들의 모음에 이름을 붙일 때 유용하다. 여러분이 식탁에서 누군가에게 “소금 좀 건네주세요.” 라고 말한다면, 여러분이 말한 몇 음절은 일련의 행동을 유발하게 된다. 우리는 사람이기 때문에 이런 전 과정이 자연스럽지만, 아두이노는 우리의 뇌처럼 강력하지 않기 때문에 모든 동작을 각각 용청해야 한다. 그렇기 때문에 많은 양의 명령들을 한데 묶기 위해서는 코드의 앞뒤에 {와 }를 사용한다.

위의 코드 상에서는 두개의 코드 블록들이 이러한 방법으로 정의되어 있는 것을 볼 수 있다. 각각의 블록 앞에는 다음과 같은 이상한 명령어가 존재한다.

    void setup()

이 줄은 코드 블록에 이름을 붙이기 위한 것이다. 아두이노에게 소금을 건네주는 방법을 알려 주기위한 명령어들을 작성하려면, 우선 void passTheSolt() 를 블록의 시작에 작성한다. 이제, 이 블록은 아두이노 코드 중 어디서나 호출할 수 있게 된다. 이러한 블록들을 함수라고 부른다. 이렇게 함수를 정의한 후 여러분의 코드 중 어디에서나 passTheSalt()를 작성(호출)하면, 아두이노는 블록 안의 코드로 건너와 명령들을 실행하게 된다.

아두이노는 멈추지 않는다

아두이노에서는 setup()과 loop() 라는 두 개의 함수가 꼭 존재해야 한다.

setup()에는 보드가 동작을 시작할 때 한번만 실행되길 원하는 코드들을 모두 두고, loop()에는 계속 반복되어 실행될 코드들을 둔다. 아두이노는 여러분의 컴퓨터처럼 여러 프로그램을 동시에 실행할 수 없기 때문에 프로그램이 그만 두지(quit) 않게 된다. 보드에 전원을 넣으면 코드가 실행되고, 멈추기 위해서는 그냥 전원을 끄면 된다.

진짜 팅커러들은 설명을 작성한다

아두이노는 //로 시작하는 줄들을 무시한다. 이런 줄들은 주석(설명문)으로, 여러분이 여러분 자신을 위해 프로그램에 작성하는 메모다. 후에, 이 주석을 보고 프로그램을 작성하면서 자신이 어떤 일들을 했는지 기억해 낼 수 있으며, 다른 사람들이 코드를 이해하는데 도움을 줄 수도 있다.

(저자가 항상 그러기 때문에 확신하건데) 코드 조각을 작성해서 보드에 올린 뒤 “좋아! 이제 다신 이 망할 코드를 볼 일 없을 거야!” 라고 말한 6개월 코드를 갱신하거나 버그를 수정해야 하는 일은 정말 자주 일어난다. 그 시점에서 주석을 전혀 작성하지 않은 프로그램을 열어 본다면, “세상에 이 잡다한 게 다 뭐지? 어디서부터 봐야 하나?”라는 생각이 들 것이다. 이제 여러분의 프로그램을 좀 더 읽기 쉽고, 유지보수가 편하게 만들기 위한 꼼수들을 살펴보자.

코드 한줄 한줄 살펴보기

일단, 여러분은 이런 종류의 설명이 불필요하다고 생각할 지도 모르겠다. 학창 시절 단테 신곡(모든 이탈리아 학생들에 이 작품과 약혼자들이라는 문학 작품은 필수 교과 과정이다. 아. 끔찍해라)을 배우는 것과 비슷하다고 생각할 것이다. 한 줄의 시 구절마다 백여 줄의 설명이라니! 하지만, 여러분 자신만의 프로그램을 작성해 나가야 하는 시점에서 이런 방식의 설명은 꽤 유용한다.

// 예제 01 : LED 깜박이기

주석은 간단한 메모를 남기기에 유용한다. 위의 제목 주석문은 이 프로그램이 첫 번째 예제이며, LED를 깜박이기 위한 것이라는 걸 상기시켜 준다.

#define LED 13    // LED 는 13번 핀에
                  // 연결되어 있음

#define 문은 여러분의 코드에서 자동으로 모두 찾아서 바꾸기 같은 것이다. 이 예는, 아두이노에게 LED라는 단어가 나타나면 모두 숫자 13으로 바꾸라는 것이다. 이 변환은 여러분이 Verify나 Upload to I/O Board 를 클릭하면 가장 먼저 수행된다(이 동작은 화면에 표시되지 않기 때문에 변환된 결과를 볼 수는 없다). 위 명령문은 깜박이는 LED를 아두이노의 13번 핀에 연결했다는 것을 명기한다.

void setup()

이 줄은 아두이노에게 따라 오는 코드 블록을 setup()이라 부를 것이라고 알려준다.

{

중괄호를 사용해 코드 블록이 시작 된다.

pinMode(LED, OUTPUT); // 디지털 핀을 
                      // 출력으로 설정

드디어, 정말 흥미로운 명령문이 나왔다. pinMode는 아두이노에게 특정 핀을 어떻게 설정할 것인지를 알려준다. 디지털 핀은 INPUT(입력)또는 OUTPUT(출력)으로 설정할 수 있다. 이 상황에서는 LED를 제어하기 위해 출력 핀이 필요하다. 해서, 핀 번호와 모드를 괄호 안에 작성했다. pinMode는 함수이며 괄호 안에 있는 단어(또는 숫자)들은 인자라 한다. 아두이노 언어에서 INPUT과 OUTPUT은 상수 이다. (변수처럼, 상수에도 값을 할당할 수 있다, 다만 상수 값들은 이미 정의되어 있고(predefine) 절대로 변경되지 않는다.)

}

이 닫는 중괄호는 setup() 함수의 끝을 알린다.

void loop()
{

loop()는 여러분의 인터렉티브 장치의 주 행동을 결정하는 곳이다. 이 함수는 보드를 끄기 전까지 계속 반복해서 수행된다.

digitalWrite(LED, HIGH);      // LED 켜기

주석문의 설명처럼 digitalWrite()로 OUTPUT으로 설정된 모든 핀을 켜거나 끌 수 있다. 첫 번째 인자(이 경우, LED)는 키고 끌 핀을 지정한다(LED가 13번 핀을 지칭하는 상수임을 되짚어 보면, 13번 핀이 작동하게 된다). 두 번째 인자로 해당 핀을 켜거나(HIGH) 끄는(LOW) 동작을 할 수 있다.

모든 출력 핀들을 여러분의 아파트 벽에 있는 것과 같은 -하지만 조그마한- 전원 소켓이라고 상상해 보자. 한국의 가정 전압은 220 V이고, 미국은 110 V이다. 아두이노에서는 더 낮은 5 V로 동작한다. 소프트웨어가 하드웨어로 변하는 마법이 여기서 일어난다. 여러분이 작성한 digitalWrite(LED, HIGH) 은 출력 핀을 5 V로 만들고, LED를 연결해 두었다면 빛이 켜진다. 코드 중 이 위치에서 소프트웨어로 행한 명령이 핀의 전기를 통해 실제 세상에 어떤 일이 일어나게 했다. 우리는 핀이 켜고 꺼진 것을 좀 더 인간이 보기 쉽게 바꾸어 봤다. LED가 우리가 사용한 엑츄레이터 이다.

delay(1000);        // 1초 대기

아두이노는 아주 기본적인 구조를 가지고 있다. 그러므로 어떤 일이 정확한 주기마다 일어나게 하고 싶다면, 아두이노에게 다음 동작을 수행하기 전에 조용히 기다리라고 말 해 주어야 한다. delay() 는 기본적으로 프로세서가 미리초 단위의 시간동안 아무 일도 하지 않고 대기하도록 한다. 미리초는 천분의 일초이다. 따라서 1000 미리초는 1초와 같다. 그러므로 1초 동안 LED가 켜진 상태로 유지된다.

digitalWrite(LED, LOW);        // LED 끄기

이 명령어는 이전에 켰던 LED를 끄게 한다. 어째서 HIGH와 LOW같은 단어를 사용할까? 사실, 이는 디지털 전자공학의 오래된 관습이다. HIGH는 핀이 켜짐을 의미하며, 아두이노의 경우 핀은 5 V로 설정된다. LOW 는 0 V가 된다. 마음속으로 이 인자들을 ON 과 OFF로 바꾸어 생각해도 된다.

delay(1000); // 1초 대기

다시 한 번 1초 동안 대기한다. LED가 1초 동안 꺼진 채로 유지된다.

}

이 닫힘 중괄호는 loop 함수의 끝을 나타낸다.

정리해보면, 이 프로그램은 다음과 같은 일을 한다.

  • 13번 핀을 출력으로 설정 (시작 시 단 한번만)
  • 반복을 시작
  • 13번 핀에 연결된 LED를 켬
  • 1초 대기
  • 13번 핀에 연결된 LED를 끔
  • 1초 대기
  • 반복 시작점으로 되돌아 감

너무 힘든 과정이 아니었기를 바란다. 뒤에 나올 예제들을 통해 프로그램을 어떻게 하는지 더 배우게 될 것이다.

다음 장으로 넘어가기 전에, 이 코드를 가지고 놀아 보기 바란다. 예를 들면 대기(delay)시간을 줄여보거나, 켜고 끌 때의 대기 시간을 다르게 하면 다른 패턴의 깜박임을 볼 수 있을 것이다. 특히, 켜고 끄는 대기 시간 중 하나를 아주 작게 만들어 보기 바란다. 그러다 보면 무언가 이상한 일이 벌어지는 시점이 있다. 이 “무언가”는 이 책의 후반부에서 펄스 폭 변조에 대해 배울 때 매우 유용하다.

앞으로 우리가 만들어 볼 것

나는 언제나 빛과 기술을 사용해 다양한 광원을 조절하는 능력이 매력적이라고 생각했다. 운 좋게도, 나는 빛을 제어해 사람들과 교감하는 흥미로운 프로젝트에 충분히 참여해 보았다. 아두이노는 정말로 이러한 일에 걸맞다. 이 책을 통해 우리는 아두이노를 어떻게 인터렉티브 장치를 만드는지 배우는 방법으로 사용하여, “인터렉티브 램프”를 디자인 해 보도록 하겠다.

다음 장에선, 엔지니어에겐 지루할 테지만, 신입 아두이노 프로그래머를 겁주지 않는 방법으로 전기의 기본에 대해 설명할 것이다.

전기는 무엇인가?

여러분의 집에 수도관이 있다면, 전기를 이해하는 것은 문제될 게 없다. 전기와 전자 회로가 어떻게 동작하는지 이해하기 위한 최고의 방법은 “물에 비유”하는 것이다. 그림 4-4에서 보이는 것과 같은 배터리로 동작하는 간단한 장치를 살펴보자

그림 4-4. 포터블 팬

팬을 떼고 보면, 작은 배터리와 몇 개의 전선들, 전기 모터로 구성되어 있으며, 모터로 가는 전선의 중간에 스위치가 있음을 알 수 있다. 새 배터리를 장착하고 스위치를 켜면 모터가 돌기 시작하며 시원한 바람이 나오게 된다. 어떻게 동작하는 것일까? 그럼, 다음과 같이 배터리를 펌프와 저수조, 스위치는 수도꼭지, 모터는 물레바퀴라고 상상해 보자. 수도꼭지를 열면 물이 펌프로 부터 흘러나와 물레바퀴가 돌아가게 된다.

이 간단한 수력 시스템을 그림 4-5에서 볼 수 있다. 여기서 중요한 두 가지 요소는 수압(은 펌프의 힘에 따라 달라진다)과 관을 따라 흐르는 물의 양(은 파이프의 두께와 흘러나오는 물이 부디쳐 물레바퀴에서 발생하는 저항력에 따라 달라진다) 이다.

그림 4-5. 수력 시스템

물레바퀴를 더 빨리 돌게 하려면 위쪽에 더 굵은 관을 사용 하고 펌프의 압축력을 증가시켜야 한다는 것을 쉽게 알아챌 수 있다. 더 큰 관을 사용할수록 흐르는 물의 양을 더 많아진다. 이렇게 큰 관을 사용하여 관이 더 많은 물을 흐르게 하지 못하게 하는 저항력을 효율적으로 줄일 수 있다. 이러한 방법으로는 어느 정도까지만 효과가 있고, 더 큰 관을 사용해도 물레바퀴의 속도가 더 이상 증가하지 않게 된다. 이는 수압이 충분하지 않기 때문으로 이제 부터는 속도를 높이기 위해 더 강력한 펌프 사용해야 한다. 이 방법으로 계속 속도를 높이다 수압이 너무 강해져서 물레바퀴가 수압을 견디지 못하고 부서져 버릴 것이다.

또 하나 주목해야 할 것은 물레바퀴가 회전을 함에 따라 회전축이 어느 정도 가열된다는 것이다. 아무리 물레바퀴를 잘 설치했다고 하더라도, 축과 축이 고정된 구멍 간에 존재하는 마찰력으로 부터 열을 발생한다. 이런 종류의 시스템에서는 투입된 모든 에너지가 모두 움직임으로 변환지 않는다는 것을 이해하는 것이 중요하다. 에너지 중 일부는 몇 몇 비효율성에 의해 잃어버리게 되고, 이렇게 잃어버린 에너지는 일반적으로 시스템의 몇 몇 부분들에서 열이 되어 나타난다.

그럼, 이 시스템에서 중요한 부분들이 무엇일까? 펌프로 부터 발생하는 압력, 관과 물레바퀴가 물의 흐름을 방해하는 저항력 그리고, 그리고 실제로 흐르는 물의 양(일 초에 몇 리터의 물이 흐르는 가로 표시할 수 있다)이 중요한 부분이다. 전기는 다소 물과 비슷하게 동작한다. 펌프의 역할을 하는 부분(배터리나, 전원 가정용 플러그 같은 전기가 발생하는 곳)은 충전된 전기를 전선으로 표현되는 관을 따라 내려(이를 전기가 물처럼 떨어져 내린다고 상상하자) 보낸다. 이런 에너지는 열을 만들어 내는 장치(할머니의 전기장판)를 비롯해, 빛 (침실의 수면등), 소리(오디오), 움직임(팬)등 여러 형태로 변형되게 된다.

배터리의 전압이 9 V 로 표시될 때, 이 전원 값을 이 작은 “펌프”(배터리)가 만들어 낼 수 있는 물의 압력 같은 것이라고 생각하자. 전압은 볼트 단위로 측정한다. 볼트라는 명칭은 전지를 처음 발명한 사람인 알레산드로 볼타의 이름에서 유래했다.

물의 압력의 역할을 하는 부분이 전기에 있는 것처럼 물이 흐르는 비율에 해당하는 부분 또한 존재한다. 전류가 바로 그것이다. 전류는 “암페어”(전가기의 선두자인 안드레 마리 앙페르의 이름에서 유래)단위로 측정할 수 있다. 전압과 전류의 상관관계는 물레바퀴의 동작하는 결과로 표현할 수 있다. 더 높은 전압 (수압) 은 물레바퀴를 더 빠르게 회전하게 하며, 더 많은 유량 (전류) 로 더 큰 물레바퀴를 돌릴 수 있다.

마지막으로, 연결된 길을 따라 흐를 수 있는 전류의 흐름을 방해 하는 저항력이 있다 -알아차렸겠지만- 바로 저항으로, 옴(독일의 물리학자인 게오르그 옴의 이름에서 유래) 단위로 측정 한다. 옴 선생님은 전기 분야에서 가장 중요한 법칙-또한, 여러분이 정말로 기억해야 하는 단 하나의-수식의 창시자이다. 그는 회로에서 전압, 전류, 저항 모두가 서로 연관이 있다는 사실과, 회로의 특정 부분에서, 전압이 정해져 있으면, 저항은 전류가 흘러갈 수 있는 양을 결정함을 입증했다.

생각해 보면 다음의 내용은 매우 직관 적이다. 9 V 인 건전지를 가져와 간단한 회로에 연결하자. 전류를 측정할 때, 더 큰 저항을 회로에 붙이면 더 적은 전류가 흐르게 된다. 물에 비유했던 것으로 돌아가 보면, 펌프의 압력이 변하지 않고, 관에 밸브(전기에서는 가변저항으로 표현할 수 있다)를 설치해 두면 따라 흐르는 물의 양은, 밸브를 잠글수록-물이 흐르지 못하게 저항력을 높일수록-물은 더 적게 흐르게 된다. 옴은 세 가지 수식으로 그의 법칙을 요약했다.

R (저항) = V (전압) / I (전류)
V = R * I
I = V / R

이 규칙은 반드시 기억하고 사용법을 배워야 한다. 왜냐하면, 여러분의 작업 대부분에서 이 식 만은 정말로 필요하기 때문이다.

푸쉬버튼을 사용해서 LED 제어하기

앞서 LED를 깜박이는 것은 쉬웠다. 하지만 만약 여러분이 책을 읽으려는데 독서등이 계속 깜박거린다면 참기 힘들 것이므로, 이 깜박임을 제어하는 방법을 배워야 한다. 앞서의 예제에서, LED가 우리가 사용한 엑츄레이터였고, 아두이노로 이를 제어하는데 사용했었다. 전체 구성에서 빠진 부분은 센서 이다.

여기서는 사용 가능한 가장 간단한 형태의 센서를 사용해 보겠다. 바로 푸쉬버튼 이다.

푸쉬버튼만을 떼 내어 살펴보면, 무척 단순하게 이루어진 장치라는 것을 알 수 있을 것이다. 두 금속 조각이 스프링에 의해서 떨어져 있고, 플라스틱으로 된 버튼을 누르면, 두 금속 조각이 서로 만나게 된다. 금속 조각들이 떨어져 있을 때는 푸쉬버튼에 전류가 흐르지 않게 된다.(마치 수도꼭지가 잠긴 것과 같다 볼 수 있다.) 버튼을 누르면 연결이 되게 된다.

스위치의 상태를 살펴보기 위해서는 새 아두이노의 명령어를 배워야 한다. digitalRead() 함수가 그것이다.

digitalRead() 는 특정 핀에 전압이 인가된 전압이 있는지를 검사하여, HIGH 또는 LOW 값을 반환해 준다. 지금까지 우리가 살펴본 다른 명령어 들은 정보를 알려주지 않았었다-그 함수들은 우리가 요청한 일을 수행하기만 했다. 하지만 이런 종류의 함수들은 다소 한계가 있는데, 왜냐하면, 세상으로 부터의 입력 없이는 어떻게 동작할지 아주 뻔한, 순차 명령만을 내일 수 있기 때문이다. digitalRead()를 사용하면, 우리는 아두이노에게 “질문을 하고” 받은 대답을 어딘가에 기억해 두었다가, 당장이나 차후에 의사결정을 하기위해 사용할 수 있다.

그림 4-6에 표시된 회로를 만들어 보자. 이를 만들기 위해서는 몇 가지 부품들을 입수해야 할 것이다. (이 부품들은 다른 프로젝트에서도 여러모로 쓸모 있는 부품들이다):

  • 브레드보드
    • 첨부 A에 브레드보드에 대한 설명을 볼 수 있다.
  • 점퍼 선 키트
  • 10K 옴 저항 하나
  • TACT 버튼
그림 4-6. 푸쉬버튼 연결

참고: 점퍼선을 구입하는 대신, 작은 실패처럼 둥글게 감긴 22 AWG(역자 주: 전선 두께의 단위)의 단선을 구입해 니퍼와 스트리퍼(전선의 피복을 벗겨내는 도구)를 사용해 자르고 벗겨내어 사용할 수도 있다.

이제, 푸쉬버튼을 사용해 LED를 제어하기 위해 사용할 코드를 살펴보자.

// 예제 02: 버튼이 눌려있는 동안 LED를 켜기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED 13   // LED가 사용하는 핀 번호
#define BUTTON 7 // 푸쉬버튼이 연결되어 있는
                 // 입력 핀 번호
int val = 0;     // val은 입력 핀의 상태를
                 // 저장하기 위해 사용됨
 
void setup() {
  pinMode(LED, OUTPUT);   // 아두이노에게 LED는 출력
  pinMode(BUTTON, INPUT); // BUTTON은 입력임을 알려줌
}
 
void loop(){
  val = digitalRead(BUTTON); // 입력 값을 읽어 저장
 
  // 입력이 HIGH (버튼이 눌림) 인지 검사
  if (val == HIGH) { 
    digitalWrite(LED, HIGH); // LED 켬
  } else {
    digitalWrite(LED, LOW);
  }
}

아두이노에서 File > New 메뉴를 선택하자(다른 스케치가 열려 있으면, 먼저 그 스케치를 저장할지를 물어본다). 아두이노가 여러분이 작성할 새 스케치의 폴더 명을 물어보면 PushButtonControl를 입력하자. 예제 02의 코드를 아두이노에 입력한다(또는, www.makezine.com/getstartedarduino 에서 다운로드 하여 아두이노 IDE로 붙여 넣기를 한다). 틀린 부분이 없다면 여러분이 버튼을 누를 때만 LED에 불이 들어온다.

코드가 어떻게 동작하는가?

위 예제를 통해 두 가지 새로운 개념이 소개 되었다. 작업한 결과를 반환하는 함수와 조건(if)문이다.

조건문은 프로그래밍 언어에서 가장 중요한 명령어라고 할 수도 있다. 왜냐하면, 컴퓨터에게(기억을 상기시켜 보면, 아두이노는 작은 컴퓨터이다) 의사 결정을 하게하는 명령어이기 때문이다. if 라는 키워드 뒤에는 괄호 안에 “질문”을 작성해야 한다. 그럼 올바른 “답”또는 질문의 결과가 참 일 때 바로 밑에 따르는 코드 블록이 실행된다. 조건에 맞지 않으면 else 뒤의 코드 블록이 실행된다. 조건문에서는 = 심벌 대신 == 를 사용했음을 주목하기 바란다. 전자는 변수에 값을 대입하는데 사용되지만 후자는 두개의 두 항목을 비교할 때 사용되며, 결과로 TRUE(참) 또는 FALSE(거짓)을 반환한다. 올바른 연산자를 쓰도록 주의하기 바란다. 왜냐하면, 조건문에 == 대신 = 을 사용하는 실수는 정말 범하기 쉽기 때문이다. 이 경우 여러분의 프로그램은 전혀 동장하지 않게 된다. 저자의 경우 25년가량 프로그래밍을 하고 있지만, 여전히 이 실수를 저지른다.

빛이 필요한 동안 계속 버튼을 손가락으로 누르고 있다는 것은 실용적이 못하다. 비록 이렇게 함으로써 램프를 켜 둔 채로 외출을 할 때 얼마나 많은 에너지가 낭비되는지 되돌아 볼 수 있긴 하겠지만 실용적인 램프를 위해 어떻게 버튼이 “붙어있게” 만드는지 찾아내야 한다.

한 가지 회로로 수천가지 동작

디지털(구형 전자기기에 대비해 프로그램 가능한 전자기기를 칭함)의 엄청난 장점이 이제 명확히 들어난다. 이제 동일한 이전 장에서 보여준 동일한 전자 회로를 사용해, 소프트웨어만 변경하여, “다양한” 종류의 동작을 구현하는 방법을 보여줄 것이다.

앞서 언급했듯이. 불을 켜기 위해 손가락으로 계속 누르고 있어야 한다는 건 그다지 실용적이지 못하다. 그러므로 “메모리”, 소프트웨어 메커니즘의 형태로 언제 버튼을 눌렀는지 기억하여, 버튼에서 손을 떼도 불이 계속 들어와 있도록 하도록 구현하여야 한다.

이 동작을 위해서 우리는 변수라 불리는 것을 사용할 것이다.(벌서 사용해 봤지만 아직 변수에 대해 설명하지는 않았다.) 변수는 아두이노에서 여러분의 데이터를 저장할 수 있는 곳인 메모리에 존재한다. 이는 접착식 메모지와 같은 것이라고 생각할 수 있다. 보통 메모지는, 한 장 뽑아서, “루이자 02 555 1212” 라고 쓴 뒤, 컴퓨터 모니터나 냉장고에 붙여둔다. 아두이노 언어에서도 이와 동일하게 간단하다. 여러분은 저장하고 싶은 데이터의 종류(예를 들면, 숫자인지 문구인지)를 결정하고, 이름을 붙인 뒤, 아무 때나 그곳에 데이터를 저장하거나 불러 올 수 있다. 예를 들면:

int val = 0;

int 는 이 변수를 정수(integer)를 저장하는데 사용할 것이라는 것이다. veal 은 변수의 이름이고, = 0 은 이 변수에 초기 값으로 0을 대입함을 의미한다.

변수라는 이름에서 알 수 있듯이, 변수는 코드 중 어디에서나 그 값이 바뀔 수 있다. 여러분의 코드에서 뒤에 다음과 같이 작성한다면;

val = 112;

이는 변수 val에 새로운 값, 112를 다시 대입한다는 것이다.

참고: 아두이노에서 모든 하나의 명령문 (#define) 을 제외한 모든 명령들이 세미콜론(;) 으로 끝난다는 것을 알아차렸는가? 이는 컴파일러(아두이노에서 스케치를 마이크로컨트롤러가 실행할 수 있는 프로그램으로 변경하는 부분)에게 현재 명령이 끝나고 새 명령이 시작함을 알려주기 위해서 사용된다. #define으로 시작되는 줄을 제외하면, 항상 세미콜론으로 마쳐야 함을 기억하자. 컴파일러가 #define을 처리(정의된 값으로 변경)하는 것은, 아두이노 실행파일로 변경하는 일을 수행하기 전이다.

다음의 프로그램에서 변수 val 은 핀의 상태를 읽는 digitalRead(); 의결과를 저장하기 위해서 사용된다. 아두이노가 입력 핀에서 얻은 값들은 변수에 남게 되며, 코드의 다른 줄에서 바꾸기 전까지 남아 있게 된다. 변수들은 램(RAM)이라 불리는 기억장치에 저장됨을 주의하자. 램은 속도가 꽤 빠르지만 보드에 전원을 끄면, 램에 저장된 데이터는 사라져 버린다(따라서, 보드의 전원이 다시 켜지면, 변수들은 각각의 초기 값으로 리셋 된다). 여러분의 프로그램은 자체는 플래시 메모리-핸드폰에서 전화번호가 저장되는 것과 같은 종류의 메모리-에 저장되기 때문에 보드의 전원이 꺼져도 사라지지 않고 남아있게 된다.

이제 LED가 켜져 있는지 꺼져 있는지를 기억하기 위한 새 변수를 사용해 볼 것이다. 예제 03A는 이 일을 완성하기 위한 첫 번째 시도다.

// 예제 03A: 버튼이 눌리면 LED를 켜고
// 다시 누를 때 까지 유지하기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED  13  // LED가 사용하는 핀 번호
#define BUTTON 7 // 푸쉬버튼이 연결되어 있는
                 // 입력 핀 번호
int val = 0;     // val은 입력 핀의 상태를
                 // 저장하기 위해 사용됨
int state = 0;   // 0 = LED 꺼짐, 1 = LED 켜짐
 
void setup() { 
  pinMode(LED, OUTPUT);   // 아두이노에게 LED는 출력
  pinMode(BUTTON, INPUT); // BUTTON은 입력임을 알려줌
} 
 
 
void loop() { 
  val = digitalRead(BUTTON); // 입력 값을 읽어 저장
 
  // 입력이 HIGH (버튼이 눌림)인지 와
  // 상태가 변했는지 검사
  if (val == HIGH) { 
    state = 1 - state; 
  } 
 
 
  if (state == 1) {      
    digitalWrite(LED, HIGH); // LED 켬
  } else { 
    digitalWrite(LED, LOW); 
  } 
} 

이제 이 코드를 테스트 해 보자. 동작을 하긴 하는데 이상한 점이 발견할 것이다. 빛이 너무 빠르게 꺼다 켰다를 반복해서 제대로 켜진 상태나, 꺼진 상태로 설정하기 힘들다.

그럼, 코드에서 흥미로운 부분을 살펴보자. state는 변수로 LED가 끄고 켜짐에 따라 0과 1을 저장한다. 버튼이 떼어진 상태에서, 우리는 이 변수를 0(LED 꺼짐) 으로 초기화하였다.

그 후에, 버튼의 현재 상태를 읽어, 만약 눌려있다면 (val == HIGH), state를 0 에서 1로 바꾸고, 떼어져 있다면 반대로 바꾼다. 이 동작을 위해 우리는 작은 트릭을 사용했다. state 값이 1과 0만 될 수 있으므로, 1 - 0 은 1 이고 1 - 1 은 0 이라는 아이디어에 기반을 둔 간단한 수학식이 그것이다.

state = 1 – state;

위 식은 수학에서는 말이 안 되는 이야기 일 수 있겠지만 프로그래밍에서는 맞는 식이다. 프로그래밍에서 기호 = 는 “내 뒤에 오는 결과를 내 앞의 변수 이름에 대입”하라는 의미이다. 이 경우, 1 - 이전 state 값이 새 state 값으로 대입된다.

프로그램의 뒷부분에서, LED가 켜있는지 꺼져있는지 알아내기 위해 state를 사용하는 것을 볼 수 있다. 앞서 언급한 대로, 이 때문에 엉뚱한 결과가 발생한다.

엉뚱한 결과의 원인은 우리가 버튼을 읽은 방법 때문이다. 아두이노는 매우 빠른데; 내부 명령어를 1초에 16만 개씩 실행한다. 이는, 여러분이 버튼을 손가락으로 누르고 있는 동안, 아두이노는 버튼의 위치를 수천 번 읽고 state를 바꾸게 된다는 것이다. 그렇기 때문에 끄고 싶은데 켜지거나 그 반대의 경우처럼, 원하는 대로 동작하지 않게 된다. 망가진 시계도 하루에 두 번씩은 맞는 것처럼 이 프로그램은 가끔씩 제대로 동작하는 것처럼 보일 수도 있지만 대부분의 경우 잘못 동작한다.

어떻게 수정할 수 있을까? 우리는 버튼이 눌려진 바로 그 순간을 감지해 내야하며, 이때가 우리가 LED의 상태를 바꿔야 할 때 이다. 저자가 좋아하는 방법은 새로운 val 값을 읽기 전에 이전 값을 저장해 두는 것이다; 그러면, 현재 버터의 위치를 이전의 위치와 비교해 볼 수 있으므로,버튼이 LOW에서 HIGH로 변했을 때만 상태 값을 바꿀 수 있다.

예제 03B 에 그렇게 동작하는 코드를 포함해 봤다.

// 예제 03B: 버튼이 눌리면 LED를 켜기
// 다시 누를 때 까지 유지하기
// 개선된 방법 사용
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
 
#define LED  13   // LED가 사용하는 핀 번호
#define BUTTON 7  // 푸쉬버튼이 연결되어 있는
                  // 입력 핀 번호
int val = 0;      // val은 입력 핀의 상태를
                  // 저장하기 위해 사용됨
int old_val = 0;  // 이 변수는 변수 "val"의
                  // 이전 상태를 저장하기 위함
int state = 0;    // 0 = LED 꺼짐, 1 = LED 켜짐
 
void setup() { 
  pinMode(LED, OUTPUT);    // 아두이노에게 LED는 출력
  pinMode(BUTTON, INPUT);  // BUTTON은 입력임을 알려줌
} 
void loop(){ 
  val = digitalRead(BUTTON); // 입력 값을 읽어 저장
                             // 냠냠. 새 값이다.
 
  // 상태가 변했는지 검사
  if ((val == HIGH) && (old_val == LOW)){ 
    state = 1 - state; 
  } 
 
  old_val = val;  // val 값은 이제 오래됨. 저장해 둔다
 
  if (state == 1) {      
    digitalWrite(LED, HIGH); // LED 켬
  } else { 
    digitalWrite(LED, LOW); 
  } 
} 

테스트 해 보자. 이제 거의 다 되었다!

아마 여러분은 이 방법이 완전히 완벽하지 못하다는 것을 알아차렸을 수도 있다. 이는 스위치의 기계 구조에서 오는 문제점 때문이다. 푸쉬버튼은 아주 간단한 장치로, 두 금속 조각이 스프링에 의해 떨어진 상태이다. 여러분이 버튼을 누를 때, 두 조각은 서로 연결이 되어 전기가 흐를 수 있게 된다. 간단하고 잘 동작할 것처럼 보이지만 실제로는 이 연결이 그렇게 완벽하지 못하다. 특히 버튼을 완전히 누르지 않았을 때는 바운싱이라는 가짜 신호가 나타나게 된다.

푸쉬버턴이 바운싱할 때 아두이노는 반복적으로 켜지고 꺼지는 신호가 아주 빠르게 바뀌는 것처럼 보게 된다. 바운싱을 제거하기 위한 기술적인 방법이 많이 개발되어 있지만, 경험 상, 이정도의 간단한 코드에서는 대개, 변경을 감지할 때 10~50 미리초의 정도 대기하도록 추가하는 정도면 충분하다.

예제 03C가 최종 코드이다.

// 예제 03C: 버튼을 누르면 LED를 켬
// 다시 누를 때 까지 유지하기
// 간단한 바운싱 제거 포함
// 개선된 새 버전!!
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED  13   // LED가 사용하는 핀 번호
#define BUTTON 7  // 푸쉬버튼이 연결되어 있는
                  // 입력 핀 번호
int val = 0;      // val은 입력 핀의 상태를
                  // 저장하기 위해 사용됨
int old_val = 0;  // 이 변수는 변수 "val"의
                  // 이전 상태를 저장하기 위함
int state = 0;    // 0 = LED 꺼짐, 1 = LED 켜짐
 
void setup() { 
  pinMode(LED, OUTPUT);   // 아두이노에게 LED는 출력
  pinMode(BUTTON, INPUT); // BUTTON은 입력임을 알려줌
} 
 
void loop(){ 
  val = digitalRead(BUTTON); // 입력 값을 읽어 저장
                             // 냠냠. 새 값이다.
 
  // 상태가 변했는지 검사
  if ((val == HIGH) && (old_val == LOW)){ 
    state = 1 - state;
    delay(10);
  } 
 
  old_val = val; // val 값은 이제 오래됨. 저장해 둔다
 
  if (state == 1) {      
    digitalWrite(LED, HIGH); // LED 켬
  } else { 
    digitalWrite(LED, LOW); 
  } 
} 

5/Advanced Input and Output

앞선 장에서 여러분은 아두이노로 할 수 있는 가장 기본적인, 디지털 출력을 제어하고 디지털 입력을 읽는, 명령들을 배웠다. 아두이노 언어를 자연어에 비유해 보면 이제 두 글자 정도를 배운 것이다. 아두이노가 -영문으로- 다섯 글자의 단어라는 것을 고려해 보면, 아두이노 언어로 시를 쓰기 위해 어느 정도의 작업을 더 해야 할 지 가능해 볼 수 있을 것이다.

다른 종류의 On/Off 센서 사용해 보기

앞서 여러분은 어떻게 푸쉬버튼을 사용하는지 배웠다. 이외에도 같은 원리로 동작하는 기초적인 센서들이 많이 있다는 것을 알기 바란다.

스위치

푸쉬버튼과 같지만 손을 떼었을 때 자동으로 상태가 -이전으로- 변하지 않음

온도센서(Thermostats)

설정한 값만큼 온도가 오르면 열리는 스위치

자석 스위치 (reed 스위치)

자석을 가까이 대면 접점이 붙는 수위치; 창문이 열렸을 때 울리는 경보 장치에 사용됨

압력센서 (카펫 스위치)

작은 매트로 카펫이나, 현관매트 밑에 두어, 사람(또는 뚱뚱한 고양이)이 그 위에 서 있는지 감지하는 센서

기울기 스위치

두개의 접점과 작은 금속 구슬(또는 -사용하지 않기를 바라지만- 수은 한 방울)이 들어있는 작은 전자 부품. 이 스위치는 기울기(tilt) 센서로도 불린다. 그림 5-1은 일반적인 기울기 센서의 내부 모습으로, 센서가 똑바로 서 있으면 구슬이 두 접점을 연결해서, 푸쉬버튼을 누른 것처럼 동작한다. 센서를 기울이면, 구슬이 움직이고, 접점은 떨어지게 된다. 마치 푸쉬버튼을 뗀 것과 같다. 이 단순한 부품을 사용해서, 예를 들면, 움직임이나 흔들었을 때 반응하는 제스처 인터페이스를 구현할 수도 있다.

그림 5-1. 기울기 센서의 내부

여러분이 접할 수 있는 또 다른 센서는 적외선 센서(PIR 센서 또는 열선 감지기로 알려져 있다. 그림 5-2를 보자)로 경보 장치 등으로 사용된다. 이 작은 장치는 사람(또는 살아있는 것들)이 센서의 사정거리 안에서 움직일 때 작동한다. 이것은 움직임을 감지하는 간단한 방법이다.

그림 5-2. Typical PIR sensor

이제 여러분이 두 접점을 연결할 수 있는 장치들을 가능한대로 찾아서 경험해 보기 바란다. 이를테면 실내 온도 조절기(더 이상 사용하지 않는 오래된 걸 써 보자)를 사용하거나, 단지 접점들을 가까이 두고 물을 떨어뜨려 스위치로 사용할 수 있다.

예를 들어 4장의 마지막 예제와 PIR 센서를 사용하면, 사람이 근처에 있을 때 켜지는 램프를 만들어 볼 수 있다. 또는 기울기 스위치를 사용하여 기울였을 때 꺼지는 램프를 만들어 볼 수 있다.

PWM을 사용해 빛의 밝기를 조절하기

지금까지 여러분이 얻은 지식들을 사용하면, 단지 켜고/꺼지는 램프가 아닌 좀 더 우아한 인터렉티브 램프를 만들 수 있다. 지금까지 우리가 사용해 온 LED를 깜박이는 예제의 한 가지 단점이라면 단지 켜고 끌 수만 있다는 것이다. 고급형 인터렉티브 램프라면 밝기를 조절할 수 있어야 한다. 이 문제를 해결하기 위해, 우리는 TV나 영화가 가능하게 만든 (잔상효과 라는) 작은 트릭을 사용해 볼 것이다.

4장의 첫 번째 예제에서 귀뜸했던 것처럼, LED가 깜박이게 보이지 않는 시점까지 delay 함수의 숫자를 조절해 보면, LED가 본래의 50%의 밝기가 된다는 걸 확인해 볼 수 있다. 이제 4번 중 한번만 LED가 켜지도록 코드를 수정해 보자. 스케치를 실행하면 이제 대략 25%의 밝기가 됨을 볼 수 있다. 이것이 ,멋지게 말하면, 펄스 폭 변조(PWM)라 불리는 기술이다. LED를 충분히 빠르게 깜박거리면, 여러분의 눈은 LED가 깜박인다는 것을 인지하지 못하게 된다. 또한 켜져있는 시간과 꺼져 있는 시간의 비율을 조절하여 밝기를 조절할 수도 있다. 그림 5-3은 PWM의 동작 원리를 보여준다.

이 기술을 LED 뿐만 아니라 다른 장치들에도 적용된다. 예를 들면, 같은 방법으로 모터의 속도를 조절할 수도 있다.

계속 하다 보면, 코드 상에서 delay를 사용해서 LED를 깜박이게 하는 게 약간 불편하다고 느끼게 될 것이다. 왜냐하면, 이와 동시에 센서의 값을 읽거나 시리얼 포트로 데이터를 보내려고 하면 아두이노가 그 동작을 마칠 때 까지 기다려야 하기 때문에 LED의 깜박거림이 다시 보이게 되기 때문이다. 다행이도, 아두이노 보드에서 사용하는 프로세서는 다른 일을 하는 동안 매우 효율적으로 LED를 깜박이게 할 수 있는 하드웨어를 포함하고 있다. 이 하드웨어는 9, 10, 11번 핀에 구현되어 있으며 analogWirte()명령문을 사용하여 제어할 수 있다.

Figure 5-3. PWM in action

예를 들면, analogWrite(9, 128) 라고 작성한 것은 9번 핀에 연결된 LED의 밝기를 50%로 만들 것이다. 128이란 숫자는 어디서 온 걸까? analogWrite()에는 0에서 255사이의 숫자를 인자로 사용할 수 있다. 255가 완전히 켜진 상태고 0이 꺼진 상태이므로 128은 딱 중간이다.

참고: PWM을 세 채널 가지고 있다는 건 꽤 좋은 일이다. 왜냐하면 빨강, 파랑, 녹색 LED를 사서 조합하면, 원하는 색을 모두 만들어 볼 수 있기 때문이다.

그럼, 직접 사용해 보자. 그림 5-4에 보이는 회로를 만들어라. LED는 극성이 있음을 주의하자. 긴 핀(양극)이 오른쪽, 짧은 핀(음극)이 왼쪽에 와야 한다. 또한, 그림에서 보이는 것처럼 대부분의 LED는 음극 쪽에 평편한 면을 가지고 있다.

Figure 5-4. LED connected to PWM pin

이제, 아두이노에 새 스케치를 만들어 예제 04를 작성하자 (코드 예제들은 www.makezine.com/getstartedarduino 에서 다운로드 할 수도 있다):

// 예제 04: 애플 컴퓨터의 절전기능처럼
// LED를 서서히 켜고 끄기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED   9 // LED가 사용하는 핀 번호
int i = 0;      // 증가와 감소를 세기 위해 이 변수를 사용
 
void setup() { 
  pinMode(LED, OUTPUT); // 아두이노에게 LED는 출력
} 
 
void loop(){ 
 
  for (i = 0; i < 255; i++) { // 0에서 254까지 반복 (서서히 켜짐)
    analogWrite(LED, i);      // LED의 밝기 설정
 
    delay(10); // analogWrite의 반응이 즉각적이므로
               // 변화를 보기 위해서 10ms 만큼
               // 대기해야 함
  }
 
  for (i = 255; i > 0; i--) { // 255에서 1까지 반복 (서서히 꺼짐)
 
    analogWrite(LED, i); // LED의 밝기 설정
    delay(10);           // 10초간 대기
  }
 
} 

이제 여러분은 (아두이노로 구현하기는 너무 간단한 기능이라 낭비라 볼 수도 있겠지만) 랩톱 컴퓨터가 가진 멋진 기능의 복제품을 갖게 되었다. 이 지식을 사용하여 우리가 만든 램프를 개선해 보도록 하자.

이 브레드 보드에 버튼을 읽기 위해 사용했던 회로(4장 참조)를 추가하자. 여러분이, 다음 장을 넘겨보지 않고도, 회로를 만들 수 있는지 확인해 보도록 하자. 왜냐하면, 이제부터 여러분은 이곳에서 소개하는 기초적인 회로들을 점점 더 큰 프로젝트들을 만들기 위한 “블록(building block)” 이라는 사실에 대해 생각해 봐야 하기 때문이다. 앞 장을 엿봐야 한다 해도 걱정할 필요는 없다; 가장 중요한 것은 여러분이 회로가 어떻게 생겼는지 생각해 보기 위한 시간을 갖는다는 것이다.

이 회로를 만들기 위해서는, 방금(그림 5-4에 보인) 만들었던 회로와, 그림 4-6에 보인 푸쉬버튼 회로를 조합해야 한다. 원한다면, 공간이 충분하니 단순히 각각의 회로를 브레드 보드의 다른 부분에 만들어도 된다. 하지만, 브레드보드(부록 A 참조)의 장점 중 하나는 윗부분과 아랫부분에 한 쌍의 레일들을 사용할 수 있다는 것이다. 하나는 빨간색(양극)으로 표시되어 있고, 다른 하나는 파랑이나 검은색(그라운드)으로 표시되어 있다.

이 레일들은 전원과 그라운드를 필요한 곳으로 분배하기 위해 사용된다. 이 예제에서 여러분이 만들어야 하는 회로의 경우, 아두이노의 GND(그라운드)핀에 연결되어야 하는 부품이 두개(둘 다 저항)있다. 아두이노에는 GND핀이 두개 있기 때문에 단순히 두 그림들에 보이는 대로 두 회로들을 연결할 수도 있다; 두 회로를 모두 동시에 아두이노에 연결하면 된다. 혹은, 전선 하나를 브레드보드의 그라운드 레일에서 아두이노의 GND 핀들 중 하나에 연결하고, 그림 상 아두이노의 GND핀에 연결되어 있는 전선을 따서 브레드보드의 그라운드 레일에 연결할 수도 있다.

아직 이를 시도해볼 준비가 되어 있지 않더라고 걱정하지 말라. 일단 그림 4-6과 5-4에 보이는 대로 양쪽의 회로를 모두 연결하자. 브레드보드에서 그라운드와 양극을 위해 레일을 사용하는 예제를 6장에서 보게 될 것이다.

다음 예제로 돌아와서, 여러분에게 푸쉬버튼이 하나밖에 없다면 어떻게 램프의 밝기를 조절할 수 있을까? 우리는 또 다른 인터렉티브 디자인 테크닉인, 얼마나 오래 버튼이 눌렸는지 알아내는 방법을 사용할 것이다. 이를 위해서, 4장의 예제 03C를 서서히 켜지는(dimming) 기능을 추가하기 위해 업그레이드해야 한다. 이 아이디어는 버튼을 눌렀다 떼는 동작에 빛을 켜고 끄며, 계속 누르고 있으면 밝기를 변하게 하는 “인터페이스” 만들기 위한 것이다.

그럼, 스케치를 살펴보자.

// 예제 05: 버튼이 눌렸을 때 LED를 켬
// 다시 누를 때 까지 유지하기
// 간단한 바운싱 제거가 포함됨.
// 버튼을 누르고 있으면 밝기가 변한다.
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED 9     // LED가 사용하는 핀 번호
#define BUTTON 7  // 푸쉬버튼이 사용한 입력 핀
 
int val = 0;      // 입력 핀의 상태 저장
 
int old_val = 0;  // "val" 값의 이전 상태 저장
int state = 0;    // 0 = LED 꺼짐, 1 = LED 켜짐
 
int brightness = 128;        // 밝기 값 저장
unsigned long startTime = 0; // 버튼이 눌리기 시작한 시간
 
void setup() { 
  pinMode(LED, OUTPUT);   // 아두이노에게 LED는 출력
  pinMode(BUTTON, INPUT); // BUTTON은 입력임을 알려줌
} 
 
void loop() {
 
  val = digitalRead(BUTTON); // 입력 값을 읽어 저장
                             // 냠냠. 새 값이다.
 
  // 상태가 변했는지 검사
  if ((val == HIGH) && (old_val == LOW)) {
 
    state = 1 - state; // 상태를 끔에서 켬으로 또는
                       // 그 반대로 변경
 
    startTime = millis(); // millis() 는 아두이노의 시계 임
    // 이 함수는 보드가 재시작(reset)
    // 된 후 지난 시간을 미리초 단위로
    // 반환한다.
 
    // (이 줄은 마지막으로 버튼이 눌린
    // 시간을 기억한다)
    delay(10);
  }
 
 
  // 버튼이 계속 눌려 있는지 검사
  if ((val == HIGH) && (old_val == HIGH)) {
 
    // 버튼이 500ms 이상 눌려 있는지
    if (state == 1 && (millis() - startTime) > 500) {
 
      brightness++; // 밝기를 1 만큼 증가
      delay(10);    // 밝기가 너무 빨리 변하는 것을
                    // 방지하기 위해 대기
 
      if (brightness > 255) { // 255가 밝기의 최댓값
 
        brightness = 0; // 값이 255가 넘는 경우
                        // 0으로 초기화 함
      }
    }
  }
 
  old_val = val; // val 값은 이제 오래됨. 저장해 둔다
 
  if (state == 1) {
    analogWrite(LED, brightness); // 현재 밝기로
                                  // LED를 켬
  } else { 
    analogWrite(LED, 0); // LED를 끔
  } 
}

이제 이 코드를 시험해 보자. 여러분이 확인할 수 있는 것처럼, 우리의 인터렉티브 모델이 점점 구체화 되고 있다. 여러분이 버튼을 눌렀다가 즉시 뗀다면, 램프의 스위치를 키고 끌 수 있다. 버튼을 계속 누르고 있으면 밝기가 변한다. 원하는 밝기가 될 때 까지 누르고 있으면 된다.

이제 좀 더 흥미로운 센서를 사용하는 방법을 배워볼 것이다. 푸쉬버튼 대신 조광센서를 사용해 본다. 이제 흥미로운 실험을 해 보자. 그림 5-5에서 보이는 것 같은 조광센서(LDR)를 구입하자. 이 센서는 전자부품상점에서 5개 단위로 구할 수 있다.

그림 5-5. Light-dependent resistor (LDR)

어두운 곳에서 LDR(light-dependent resistor)의 저항 값은 꽤 크다. 센서에 빛을 조금 쬐이면, 저항 값은 빠르게 떨어져서 전기가 상당히 잘 흐르게 된다. 따라서 LDR은 일종의 광-반응 스위치이다.

예제 02(4장의 “푸쉬버튼으로 LED 제어하기” 참조)에서 선보였던 회로를 만들고, 예제 02의 코드를 아두이노에 올리자.

이제 브레드보드에 푸쉬버튼 대신 LDR을 꽂아 보자. 손으로 LDR을 가리면 LED가 꺼지는 것을 확인할 수 있을 것이다. LDR을 덮은 손을 떼면 불빛이 다시 들어온다. 방금 여러분은 여러분의 첫 번째 센서-구동형 LED를 만들어 냈다. 이것이 의미 있는 이유는, 이 책에서 처음으로, 단지 단순한 기계 장치가 아닌 전자 부품을 사용한 것이기 때문이다. 이것이 진정한 리치(rich) 센서다.

아날로그 입력

이전 섹션에서 우리는, 안드로이드가 핀에 인가된 전압이 있는지를 감지할 수 있고, digitalRead() 함수를 사용해 이를 읽어볼 수 있음을 배웠다. 많은 어플리케이션에서 이런 있다/없다(HIGH/LOW) 방식은 응답은 꽤 쓸 만하다. 하지만 이제부터 사용해 볼 광센서의 경우 빛이 있다/없다 뿐만 아니라 광량이 얼마나 되는지 알아내기 위해 사용할 수 있다. 이런 점이 (무언가가 있는지 없는지를 알려주는) 켜고/끄는 센서와 아날로그 센서의 차이점 이다. 아날로그 센서에서는 전체 값이 연속적으로 변한다. 이런 종류의 센서로 부터 값을 읽기 위해서는 다른 타입의 핀을 사용해야 한다.

아두이노 보드의 오른쪽 아래 부분을 보면 “Analog In”(아날로그 입력)이라 표시된 6개의 핀을 볼 수 있을 것이다. 이 핀들은 핀에 전압이 있고 없고를 알려줄 뿐 아니라, 전압이 있는 경우에는, 그 값을 알려주는 특수 핀들이다. analogRead() 함수를 사용하여 아날로그 입력 핀 중 하나에 인가된 전압을 읽어볼 수 있다. 이 함수는 0 에서 5V에 해당하는 0 부터 1023 사이의 값을 반환하므로, 핀 0번에 2.5V 의 전압이 있는 경우 analogRead(0)은 512를 반환하게 된다.

그림 5-6에 보이는 회로를 만들어 보자. 저항은 10k를 사용한다. 예제 06A 의 코드를 실행해 보면, 보드 상의 LED(4장의 “LED 깜박이기”에서 소개했던 대로 13번 핀과 GND에 LED를 추가로 설치할 수도 있다)가 센서에 비추는 빛의 양에 따른 비율로 깜박거리는 것을 볼 수 있다.

Figure 5-6. 아날로그 센서 회로
// 예제 06A: 아날로그 입력 값의
// 비율로 LED를 깜박이기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED  13 // LED가 사용하는 핀 번호
 
int val = 0;   // 센서에서 들어오는 값을
               // 저장하기 위한 변수
void setup() {
  pinMode(LED, OUTPUT); // LED는 출력
 
  // 참고: 아날로그 핀들은 자동으로
  // 입력으로 설정됨
}
 
void loop() {
 
  val = analogRead(0); // 센서로 부터
                       // 값을 읽음
 
  digitalWrite(13, HIGH); // LED를 켬
 
  delay(val); // 일정 시간만큼
              // 프로그램을 멈춤
 
  digitalWrite(13, LOW); // LED를 끔
 
  delay(val); // 일정 시간만큼
              // 프로그램을 멈춤
}

이제, 예제 06B를 시험해 보자. 그러기 전에 먼저, 여러분의 회로를 수정할 필요가 있다. 그림 5-4를 다시 보고 그림처럼, LED를 9번 핀에 연결하자. 이미 여러분의 브레드 보드에 만들어 둔 회로가 있기 때문에, 브레드보드에서 LDR 회로에 겹치지 않게 LED, 전선, 저항을 추가할 곳을 확보해야 한다.

// 예제 06B: 아날로그 입력 값으로
// 정한 밝기만큼 LED의
// 밝기를 설정하기
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define LED  9  // LED가 사용하는 핀 번호
 
int val = 0;    // 센서에서 들어오는 값을
                // 저장하기 위한 변수
 
void setup() {
 
  pinMode(LED, OUTPUT); // LED는 출력
 
  // 참고: 아날로그 핀들은 자동으로
  // 입력으로 설정됨
}
 
void loop() {
 
  val = analogRead(0); // 센서로 부터
                       // 값을 읽음
  analogWrite(LED, val/4); // 센서에서 받은
                           // 밝기 값으로
                           // LED를 켠다
 
  delay(10); // 일정 시간만큼
             // 프로그램을 멈춤
}

참고: analogRead()는 0~1023 범위의 값을 반환하는데 반해 analogWrite()는 인자 값으로 최대 255를 사용할 수 있다. 그래서 val값을 4로 나누어 밝기 값으로 사용하였다.

다른 종류의 아날로그 센서 사용해 보기

이전 섹션에서 사용한 회로를 그대로 사용하면 대동소이하게 작동하는 매우 많은 종류의 저항형 센서들을 사용해 볼 수 있다. 서미스터 (온도에 따라 저항 값이 변하는 간단한 장치)를 예로 들어 보자. 회로에서 우리는 어떻게 저항 값의 변화를 아두이노가 측정할 수 있는 전압의 변화로 바꾸는지 살펴보았다.

서미스터를 사용할 때는 읽어온 값과 실제 측정온도가 바로 매칭 되지 않음을 주의하라. 실제 온도를 알아내기 위해서는 실제 온도계가 측정한 값과 아날로그 핀으로 부터 읽을 값을 대조해 보아야 한다. 센서 값과 온도 값을 테이블로 만들어 아날로그 결과 값과 우리가 사는 세상의 온도를 맞추어 볼 수 있다.

지금까지는 LED만을 출력 장치로 사용해 봤다. 하지만 우리(사람)가 아두이노가 읽은 값을 확인해 보려면 어떻게 해야 할까? 보드가 읽은 값들을 LED를 깜박여 모스 코드로 표현할 수는 없다(사실 모스코드로 만드는 것도 가능하지만 이보다 더 사람이 읽기 쉬운 방법이 있다). 다음 섹션에서는 이 문제를 해결하기 위해 시리얼 포트를 통해 아두이노와 컴퓨터가 통신하도록 해 보겠다.

시리얼 통신

이 책의 초반부에서 여러분은 아두이노에는 IDE에서 프로세서에 코드를 업로드 할 때 사용하는 USB포트가 하나 있다고 배웠다. 좋은 소식은, 우리가 작성하는 스케치로, 아두이노가 컴퓨터로 데이터를 보내거나 컴퓨터에서 아두이노에게 명령을 전달하는데 이 USB 연결을 사용할 수 있다는 것이다. 이 기능을 사용하기 위해 이제부터 시리얼(serial) 객체(스케치를 작성하는 사람들이 사용하기 편하게 관련 기능들을 한데 묶어 놓은 것)를 사용해 볼 것이다.

시리얼 객체에는 데이터를 보내고 받기위해 필요한 모든 코드들이 포함되어 있다. 이제부터, 방금 감광저항을 사용해 만들어 본 회로를 사용하여, 센서로 받은 값을 컴퓨터에서 읽어오게 해 보자. 새 스케치를 열어 아래의 코드를 작성한다. (www.makezine.com/getstartedarduino 에서 코드를 다운받을 수도 있다)

// 예제 07: 아날로그 입력 0번에서
// 읽은 값을 컴퓨터로 전송하기
// 스케치를 올릴 후 반드시
// "시리얼 모니터(Serial Monitor)"를 클릭할 것
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define SENSOR 0  // 센서 저항에 사용할
                  // 입력 핀 선택
 
int val = 0; // 센서에서 들어오는 값을
             // 저장할 변수
 
void setup() {
 
 Serial.begin(9600); // 데이터를 컴퓨터로 전송할
                     // 시리얼 포트를 연다.
                     // 속도는 초당 9600 비트
}
 
void loop() {
 
  val = analogRead(SENSOR); // 센서로 부터
                            // 값을 읽음
 
  Serial.println(val); // 값을 시리얼 포트에
                       // 출력
 
  delay(100); // 매 전송 간
              // 100ms 씩 대기
}

아두이노에 코드를 올린 후 아두이노 IDE에서 툴바의 가장 오른쪽에 있는 “Serial Monitor” 버튼을 눌러보자. 윈도우의 밑 부분에서 숫자들이 빠르게 올라가는 것을 볼 수 있을 것이다. 이제, 어떤 종류든, 시리얼 포트를 읽을 수 있는 컴퓨터 소프트웨어를 사용해 아두이노와 대화를 할 수 있게 되었다. 시리얼 포트 통신로 대화하도록 프로그램을 작성할 수 있는 프로그래밍 언어는 매우 많다. 그 중 프로세싱(www.processing.org)은 훌륭한 선택인데, 왜냐하면 프로세세인 언어 그 자체와 IDE가 아두이노와 무척 닮았기 때문이다.

더 큰 부하를 다루기 (모터, 램프 등...)

아두이노 보드의의 각 핀들은 20 미리 암페어(20mA) 까지 전원을 공급할 수 있다. 이는 꽤 작은 량의 전류로, LED를 다루는 정도까지만 가능하다. 이 핀으로 모터같은 것을 켜려 한다면, 절대로 동작하지 않을 뿐더러, 프로세서를 홀랑 태워버릴 가능성도 있다. 모터나 백열전구 같이 큰 부화를 다루려면 아두이노로 제어할 수 있으면서, 큰 부하를 켜고 끌 수 있는 추가 부품이 필요하다. 그런 부품으로 MOSFET(모스펫) 트랜지스터가 있다. -이상한 이름은 무시하자- MOSFET은 전기적인 스위치로 세 개의 핀(다리)중 게이트(Gate)라 불리는 핀에 전원을 인가하면 스위치가 켜진다. 이는 흡사 가정용 전등 스위치와 같다고 보면 되는데, 손가락으로 스위치를 켜는 대신, 아두이노의 핀에서 MOSFET의 게이트 로 전원을 보낸다고 볼 수 있다.

참고: 모스펫(MOSFET)이라는 이름은, “금속 산화막 반도체 전계효과 트랜지스터” (metal-oxide-semiconductor field-effect transistor)의 약자 이다. 모스펫은 전계효과 이론에 기반을 둔 특별한 종류의 트랜지스터 이다. 이 말은 게이트(G)핀에 전압이 인가되면, 반도체 물질로 된 조각을 따라 -드레인(Drain)에서 소스(Source) 핀으로- 전기가 흐른다는 의미이다. 게이트(G)핀은 금속 산화막 위의 나머지 부분으로 부터 절연되어 있기 때문에 아두이노에서 모스펫으로 흘러 들어가는 전류가 없기 때문에 아주 간단하게 다룰 수 있다. 모스펫은 큰 부하를 빠른 주파수로 껐다 켜기에 이상적인 부품이다.

그림 5-7에서 팬에 붙어 있는 작은 모터를 켜고 끄기 위해, 어떻게 IRF520과 같은 모스펫을 사용하는지 볼 수 있다. 또한, 모터는 아두이노의 9V 커넥터를 전원으로 사용함을 주목하기 바란다. 이 점이 모스펫의 또 다른 장점으로, 아두이노가 사용하는 전원과 다른 전원을 사용하는 장치들을 다룰 수 있게 된다. 모스펫이 9번 핀에 연결되어 있기 때문에 analogWrite() 함수를 사용하여 PWM으로 모터의 속도를 제어할 수 있다.

복합 센서

복학센서는 digitalRead() 또는 analogRead() 보다 복잡한 방법이 필요한 정보를 만들어 내는 센서라고 말할 수 있다. 이런 센서들은 보통 센서 안에 정보를 선가공하기 위한 작은 마이크로컨트롤러를 포함하는 작은 회로가 존재한다.

초음파 거리 센서, 적외선 센서, 가속도 센서 등이 이런 복합 센서에 포함된다. 아두이노 웹사이트의 튜토리얼(Tutorials) 섹션(www.arduino.cc/en/ Tutorial/HomePage)에서 이런 센서를 사용하는 방법을 찾아볼 수 있다.

톰 이고의 책, Making Things Talk (O’Reilly)에서 이런 센서를 포함에 많은 복합 센서들에 대해 풍부하게 다루고 있다.

Figure 5-7. 아두이노를 위한 모터 회로

6/구름 잡기

이전 장들에서, 여러분은 아두이노의 기본과 기초 여러분이 사용할 수 있는 빌딩 블록들을 배웠다. 이제 여러분들에게 “아두이노 알파벳”을 구성하고 있는 것들이 무엇인지 상기시켜 주도록 하겠다.

디지털 출력

우리는 디지털 출력을 LED를 제어하는데 사용했다. 하지만 적당한 회로를 사용하면 이 핀들을 모터를 제어하거나 소리를 만드는 등 더 많은 것들을 할 수 있다.

아날로그 출력

아날로그 출력을 사용하면 LED를 단순히 켜고 끄는 것을 넘어 밝기를 조절할 수 있게 된다. 또한 모터의 속도를 제어하는데도 사용한다.

디지털 입력

디지털 입력 핀으로 푸쉬버튼이나 기울기 센서 같은 간단한 센서의 상태를 읽어볼 수 있다.

아날로그 입력

단순히 켜지고 꺼져있는지를 넘어 연속적인 신호를 보내는 가변저항 또는 조광 센서와 같은 센서를 읽을 수 있다.

시리얼 통신

시리얼 통신을 통해 컴퓨터와 대화할 수 있게 되어, 데이터를 서로 교환할 수 있다. 또는 단순히 아두이노에서 돌아가는 스케치에 어떤 일이 일어나는지 살펴보는데도 사용한다.

이 장에서는, 이전 장들에서 배운 것들을 조합하여 하나의 동작하는 어플리케이션을 만드는 방법을 다룬다. 여러분은 이번 장에서 복잡한 프로젝트를 만들기 위해 각각의 예제들을 블록화 하여 사용하는 방법을 볼 수 있을 것이다.

이제부터 내 안에 잠재된 디자이너가 등장할 차례다. 우리는 저자가 가장 좋아하는 이탈리아 디자이너인 조 콜롬보의 클래식 램프의 21세기 버전을 만들어 볼 것이다. 우리가 만들어 볼 물체는 1964년 작 “Aton”으로 불리는 램프에서 영감을 얻었다.

그림 6-1. 완성된 램프

그림 6-1 에서 보듯이 이 램프는 단순한 구 형태로, 책상에서 굴러 떨어지는 것을 방지하기 위해 커다란 구멍이 있는 받침대위에 올려있다. 이 디자인은 여러분이 램프의 방향을 다른 것으로 변경할 수 있게 한다.

기능적인 측면에서, 우리는 인터넷에 연결되는 장치를 만들 것이다. Make 블로그(blog.makezine.com)의 현재 기사 리스트를 불러와 “peace”, “love”, “arduino”라는 단어들이 얼마나 언급되었는지 횟수를 세고, 이 값들로 색을 만들어 램프에 색을 밝힐 것이다. 램프에는 램프를 켜고 끄기 위한 버튼이 하나와, 자동으로 동작하기 위한 빛 센서가 있다.

계획하기

이제, 우리가 무엇을 만들어 내려 하는지와 이를 위해서 어떤 부품들이 필요한지 살펴보자. 첫 번째로, 인터넷에 연결하기 위해 아두이노가 필요하다. 아두이노 보드는 단지 하나의 USB포트만을 가지고 있기 때문에, 인터넷 망에 바로 연결할 수는 없다. 그러므로 아두이노와 인터넷을 이어 줄 방법을 찾아야 한다. 컴퓨터에서 돌아가는 어플리케이션을 이용하는 것이 일반적이다. 어플리케이션은 인터넷에 연결되며, 데이터를 가공하며, 뽑아낸 단순화 된 정보를 아두이노에게 전달한다.

아두이노는 작은 메모리를 가진 간단한 컴퓨터이기 때문에 커다란 파일을 쉽게 처리하지 못한다. 우리가 RSS 피드에 접속해서 얻어오는 것은 매우 긴 XML 파일이며, 이를 처리하기 위해서는 훨씬 더 많은 램이 필요하다. 여기에선, 프로세싱 언어를 사용하여 XML을 단순화 하는 프록시를 구현해 볼 것이다.

   프로세싱
   프로세싱은 아두이노의 시조이다. 우리는 이 언어를 사랑하며, 초보자들에게 아름다운 코드를 만들 수 있게 프로그래밍을 가르치는데 이 언어를 사용한다. 프로세싱과 아두이노는 완벽한 조합이다. 프로세싱의 또 다른 장점은, 이 언어가 오픈 소스이며 모든 주요 플랫폼들(맥, 리눅스, 윈도) 위에서 동작한다는 것이다. 또한 이들 플랫폼들 위에서 실행되는 독립형 어플리케이션을 만들어 낼 수 있다. 추가로, 프로세싱 커뮤니티는 활발히 활동 중이며 쉽게 도움을 구할 수 있다. 그리고 수천 개의 준비된 예제 프로그램들을 커뮤니티에서 찾을 수 있다.

프록시는 다음과 같은 일들을 한다. makezine.com 에서 RSS 피드를 다운로드 하여, 그 결과물인 XML 파일에서 단어들을 모두 뽑아낸다. 그러고, 이들 전체를 살펴보며 문장에 “peace”, “love”, “arduino” 라는 단어들이 몇 번씩 나왔는지 센다. 이 세 숫자들로 부터 색 값을 계산해 아두이노에게 보낸다. 보드에서 받은 센서로 측정한 빛의 양을 컴퓨터 스크린에 표시한다.

하드웨어적인 면에서, 우리는 푸쉬버튼 예제와, 빛 센서 예제, PWM LED 제어 (3개)와 시리얼 통신 예제를 조합할 것이다.

아두이노는 간단한 장치이므로, 색을 간단한 방법으로 코드화 할 필요가 있다. 우리는, HTML에서 색을 표현하는데 사용하는 표준 방법(#뒤에 십육진수 6개)을 사용할 것이다.

16진수는 편리하다, 왜냐하면 각각의 8비트 숫자들이 정확히 두 글자에 저장되기 때문이다. 10진수를 사용하면 하나에서 세 글자로 가변적으로 표현된다. 또한, 예측 가능성으로 인해 코드가 더 단순해진다. #이 나타날 때 까지 기다린 뒤, 뒤따라오는 여섯 글자를 읽어 버퍼(데이터를 임시로 담아두기 위해 사용되는 변수)에 담아둔다. 마지막으로, 두 글자씩 나누어 세 LED중 하나의 밝기를 표현하는 바이트로 변환한다.

코딩

여러분이 실행해야 할 스케치가 두개 있다. 하나는 프로세싱 스케치, 다른 하나는 아두이노 스케치 이다. 이곳의 코드는 프로세싱 스케치 이다. 이 코드는 www.makezine.com/getstartedarduino 에서 다운로드 할 수도 있다.

// 예제 08A: 아두이노 네트워크 램프
// 일부 코드는 토드 E. 커트가 올린 블로그 포스팅
// (todbot.com)에서 영감을 받음
//
// 이 예제를 새 프로세싱 스케치에 복사해서 붙일 것
 
import processing.serial.*;
 
String feed = "http://blog.makezine.com/index.xml";
 
int interval = 10;  // 매 60초 마다 피드를 받아 옴
int lastTime;       // 마지막으로 피드 내용을 받은 시간
 
int love    = 0;
int peace   = 0;
int arduino = 0;
 
int light = 0;  // 램프에서 측정한 빛의 밝기
 
Serial port;
color c;
String cs;
 
String buffer = ""; // 아두이노에서 받아 온 글자들을 계산
 
PFont font;
 
void setup() {
  size(640,480);
  frameRate(10);    // 빈번하게 갱신할 필요는 없다
 
  font = loadFont("HelveticaNeue-Bold-32.vlw");  
  fill(255);  
  textFont(font, 32);
  // 중요 공지:
  // Serial.list()로 받아온 포트 중 첫 번째가
  // 포트가 여러분의 아두이노일 것이다. 아니라면,
  // 다음 줄 앞의 //을 지워 주석을 해제하고, 스케치를
  // 다시 실행하여 시리얼 포트 목록을 확인하라. 그리고
  // [ 와 ] 사이의 0을 여러분의 아두이노가 연결된
  // 포트의 번호로 바꾸라.
  //println(Serial.list());
  String arduinoPort = Serial.list()[0];
  port = new Serial(this, arduinoPort, 9600); // 아두이노에 접속
 
  lastTime = 0;
  fetchData();
}
 
void draw() {
  background( c );
  int n = (interval - ((millis()-lastTime)/1000));
 
  // 3 값을 기반으로 색을 구성
  c = color(peace, love, arduino);
  cs = "#" + hex(c,6); // 아두이노에 전송할 문자열 준비
 
  text("Arduino Networked Lamp", 10,40);
  text("Reading feed:", 10, 100);
  text(feed, 10, 140);
 
  text("Next update in "+ n + " seconds",10,450);
  text("peace" ,10,200);
  text(" " + peace, 130, 200);
  rect(200,172, peace, 28);
 
  text("love ",10,240);
  text(" " + love, 130, 240);
  rect(200,212, love, 28);
 
  text("arduino ",10,280);
  text(" " + arduino, 130, 280);
  rect(200,252, arduino, 28);
 
  // 화면에 색 문자열 출력
  text("sending", 10, 340);
  text(cs, 200,340);
 
  text("light level", 10, 380);
  rect(200, 352,light/10.23,28); // 1023을 100에 맞춤
 
  if (n <= 0) {
    fetchData();
    lastTime = millis();
  }
 
  port.write(cs); // 아두이노에 데이터 전송
 
  if (port.available() > 0) { // 기다리고 있는 데이터가 있는지 검사
    int inByte = port.read(); // 한 바이트를 읽음
    if (inByte != 10) { // 바이트가 새 줄(newline)인지 검사
      buffer = buffer + char(inByte); // 버퍼에 추가함
    }
    else {
 
      // 줄의 끝에 도착. 이제 데이터를 처리하자
      if (buffer.length() > 1) { // 충분한 데이터가 있는지 확실히 함
 
        // 마지막 글자(char)를 잘라냄. 이 글자는 캐리지 리턴 임
        // (캐리지 리턴은 텍스트에서 각 줄의 끝에
        // 위치하는 글자 임)
        buffer = buffer.substring(0,buffer.length() -1);
 
        // 버퍼의 스트링을 십진수로 변환
        light = int(buffer);
 
        // 다음 읽기 주기를 위해 버퍼를 비움
        buffer = "";
 
        // 우리는 아두이노에서 읽은 값들을 받은 후에
        // 처리할 것이다. 그러므로 다음에 읽는 값을 최신
        // 으로 하기 위해 버퍼에 쌓여 있던 센서에서 읽은
        // 값들을 지운다.
        port.clear(); 
      }
    } 
  }
 
}
 
void fetchData() {
  // 이 문자열(String)들은 피드를 파싱하기 위해 사용
  String data; 
  String chunk;
 
  // 카운터들을 0으로 초기화
  love    = 0;
  peace   = 0;
  arduino = 0;
  try {
    URL url = new URL(feed);  // URL을 표현하는 객체
    // 접속을 준비 함
    URLConnection conn = url.openConnection(); 
    conn.connect(); // 이제 웹사이트에 접속
 
    // this is a bit of virtual plumbing as we connect
    // the data coming from the connection to a buffered
    // reader that reads the data one line at a time.
    BufferedReader in = new
      BufferedReader(new InputStreamReader(conn.getInputStream()));
 
    // 피드의 각 줄을 읽음
    while ((data = in.readLine()) != null) {
 
      StringTokenizer st =
        new StringTokenizer(data,"\"<>,.()[] ");// 데이터를 분해
      while (st.hasMoreTokens()) {
        // 각 데이터 조각은 소문자가 된다
        chunk= st.nextToken().toLowerCase() ;
 
        if (chunk.indexOf("love") >= 0 ) // "love"를 발견했는가?
          love++;    // love를 1 만큼 증가
        if (chunk.indexOf("peace") >= 0)   // "peace"를 발견했는가?
          peace++;   // peace를 1 만큼 증가
        if (chunk.indexOf("arduino") >= 0) // "arduino"를 발견했는가?
          arduino++; // arduino를 1 만큼 증가
      }
    }
 
    // 64를 우리가 처리할 수 있는 최댓값으로 설정
    if (peace > 64)   peace = 64;
    if (love > 64)    love = 64;
    if (arduino > 64) arduino = 64;
 
    peace = peace * 4;     // 4를 곱함. 최댓값은 255가 된다
    love = love * 4;       // 이 값은 4 바이트(ARGB)로 구성된 색
    arduino = arduino * 4; // 을 만들 때 편리하다
  } 
  catch (Exception ex) { // 오류가 있으면 스케치를 멈춤
    ex.printStackTrace();
    System.out.println("ERROR: "+ex.getMessage());
  }
 
}

프로세싱 스케치가 바르게 동작하기 위해서 여러분이 해야 할 일이 두 가지 있다. 우선, 프로세싱에게 우리가 스케치에 사용할 글꼴을 생성하라고 해야 한다. 그러기 위해서, 이 스케치를 생성 및 저장하고, 스케치가 여전히 열린 상태에서 프로세싱의 Tools 메뉴를 선택하고 “Create Font”를 선택한다.

다음으로, 여러분은 스케치가 아두이노와 대화하기 위해 올바른 시리얼 포트를 사용하는지 확인해야 할 필요가 있다. 아두이노 회로를 조립하고, 아두이노 스케치를 올려보기 전에 이를 확인해야 한다. 대부분의 시스템에서 이 프로세싱 스케치는 잘 동작할 것이다. 하지만 그렇지 않고, 아두이노의 동작을 전혀 볼 수 없고, 화면에 빛 센서로부터 온 정보가 전혀 보이지 않는다면, 프로세싱 스케치의 주석 중 “중요 노트” 부분을 찾아 그곳의 설명대로 따라해 보기 바란다.

다음은 아두이노 스케치이다. (www.makezine.com/getstartedarduino 에서도 다운 가능하다.)

// 예제 08B: 아두이노 네트워크 램프
//
// 이 예제를 새 아두이노 스케치에 복사해 붙일 것
 
#define SENSOR 0   
#define R_LED 9
#define G_LED 10
#define B_LED 11
#define BUTTON 12
 
int val = 0; // 센서에서 들어오는 값을 저장하기 위한 변수
 
int btn = LOW;
int old_btn = LOW;
int state = 0;
char buffer[7] ;
int pointer = 0;
byte inByte = 0;
 
byte r = 0;
byte g = 0;
byte b = 0;
 
void setup() {
  Serial.begin(9600);  // 시리얼 포트를 연다
  pinMode(BUTTON, INPUT);
}
 
void loop() {
  val = analogRead(SENSOR); // 센서의 값 읽음
  Serial.println(val);      // 값을 시리얼 포트에
                            // 출력
 
  if (Serial.available() >0) {
 
    // 수신한 바이트를 읽음
    inByte = Serial.read();
 
    // 마커를 찾으면, 따라오는 char 6개가 색 값
    if (inByte == '#') {
 
      while (pointer < 6) { // char 6개를 처리
        buffer[pointer] = Serial.read(); // 버퍼에 저장
        pointer++; // 저장위치(pointer)를 1 만큼 이동
      }
 
      // 이제 16진수(HEX)로 저장된 3개의 숫자를 얻음
      // 이 숫자들을 r, g, b 3 바이트로 디코드 해야 함
      r = hex2dec(buffer[1]) + hex2dec(buffer[0]) * 16;
      g = hex2dec(buffer[3]) + hex2dec(buffer[2]) * 16;
      b = hex2dec(buffer[5]) + hex2dec(buffer[4]) * 16;
 
      pointer = 0; // 버퍼를 다시 사용하기 위해 저장위치를 초기화
 
    }
  }   
 
  btn = digitalRead(BUTTON); // 입력 값을 읽어 저장
 
  // 변화가 있는지 검사
  if ((btn == HIGH) && (old_btn == LOW)){
    state = 1 - state;
  }
 
  old_btn = btn; // val 값은 이제 오래됨. 저장해 둔다
 
  if (state == 1) { // 램프를 켜는 경우
 
    analogWrite(R_LED, r);  // 컴퓨터에서 보내 온
    analogWrite(G_LED, g);  // 색 값으로
    analogWrite(B_LED, b);  // LED를 켠다
  } else {
 
    analogWrite(R_LED, 0);  // 반대의 경우 끈다
    analogWrite(G_LED, 0); 
    analogWrite(B_LED, 0);
   }
 
  delay(100);                // 각 전송 간 100ms 씩 대기
}
 
int hex2dec(byte c) { // 하나의 16진 글자를 숫자로 변환
    if (c >= '0' && c <= '9') {
      return c - '0';
    } else if (c >= 'A' && c <= 'F') {
      return c - 'A' + 10;
    }
}

회로 조립하기

그림 6-2에서 어떻게 회로를 조립하는지 볼 수 있다. 다이어그램에서 LED에 연결된 저항을 제외한 모든 저항에는 10K 옴을 사용해야한다. LED에는 더 낮은 값의 저항을 사용한다.

5장의 PWM 예제에서 살펴봤듯이 LED들은 극성이 있음을 기억하자. 회로에서, 긴 핀(양극)은 오른쪽으로, 짧을 핀(음극)은 왼쪽으로 가야 한다. (그림에 보이는 것처럼 대부분의 LED는 음극 부분에 평편한 면이 있다.)

Figure 6-2. "아두이노 네트워크 램프" 회로

그림에서 보이는 것처럼 회로를 만들다 빨간색 LED 하나, 녹색 하나, 파란색 하나를 사용한다. 다음으로, 아두이노와 프로세싱에서 스케치를 불러온다. 그리고 스케치를 실행해 시험해 보자. 문제가 있다면 7장 “문제해결”을 살펴보자.

이제 브레드 보드를 유리 구에 설치하여 조립을 마무리 하자. 유리 구를 구하는 가장 간단하고 싼 방법은 이케아 “파도” 램프를 구입하는 것이다. 현재 이 램프는 14.99달러에 팔리고 있다. 6)

세 개의 LED를 각기 사용하는 대신에, 하나의 다리가 네 개 달린 RGB LED를 사용할 수도 있다. RGB LED도 그림 6-2에서 보이는 것과 매우 유사한 방법으로 연결한다. 한 가지 변경해야 하는 것은 각기 세 개의 아두이노 그라운드 핀으로의 연결 대신, 하나의 다리(공동 캐소드로 불림)를 그라운드에 연결하면 된다. SparkFun 에서 4리드(다리) RGB LED를 몇 달러에 판매한다. (www.sparkfun.com; 파트번호 COM-00105) 단색 LED와 달리, RGB LED에서는 가장 긴 다리가 그라운드에 연결된다. 나머지 짧은 다리들은 (분리된 빨강, 파랑, 녹색 LED처럼 다리와 핀 사이에 저항을 사용하여) 아두이노의 9번, 10번, 11번에 연결한다.

이제부터는 조립 방법이다

램프를 분해하여 밑 부분에서 램프로 들어가는 케이블을 제거한다. 이 램프는 더 이상 전원 콘센트를 사용하지 않게 될 것이다.

브레드보드에 아두이노를 붙이고 글루건을 사용해 브레드보드를 램프의 뒷면에 붙인다.

더 긴 전선들을 RGB LED에 납땜하고, LED를 전구가 있었던 곳에 붙인다. LED에서 온 전선들은 브레드 보드(에서 LED를 제거하기 전에 원래 연결되었던 곳)에 연결한다. 다리가 네 개인 RGB LED를 사용하다면 단지 하나의 전선만 그라운드에 연결되어야 함을 주의 하자.

구를 세워둘 만한 구멍이 있는 멋진 나무 조각을 찾거나, 램프를 살 때 딸려온 종이상자의 윗부분을 5cm 정도 잘라 램프를 거치할 구멍을 만든다. 스탠드를 더 안정감 있게 하기 위해 종이상자의 안쪽부분을 글루건을 이용해 보강한다.

구를 스탠드에 자리 잡고, USB 케이블을 윗부분으로 빼내어 컴퓨터에 연결한다.

여러분의 프로세싱 코드를 실행한다. 온/오프 버튼을 누르고, 램프가 살아나는지 보자.

연습 삼아, 방안이 어두워지면 램프가 켜지도록 코드를 추가해 보자. 또 다른 추가 기능들로는 다음과 같은 것들이 있다.

  • 기울기(틸트) 센서를 추가해 램프를 다른 방향으로 기울이면 꺼지거나 켜지도록 함.
  • 누군가 곁에 있는 것을 알아내도록 작은 PIR 센서를 추가하고, 근처에 아무도 없으면 램프가 꺼지도록 함.
  • 색을 수동으로 제어할 수 있도록 다른 모드를 생성 또는 다양한 색으로 서서히 변하도록 만듦.

다른 것들을 생각하고, 실험하고, 즐겨라!

7/문제해결

실험을 하다보면 아무것도 동작하지 않아 어떻게 고쳐야 하는 알아내야 하는 시점이 오게 된다. 문제해결(Troubleshooting)과 디버깅은 몇 가지 간단한 규칙으로 된 고대 예술인데, 이 규칙들은 많은 작업을 거치면서 얻게 된 결과물이다.

여러분이 전자와 아두이노를 다루면 다룰수록, 점점 더 배우고 경험을 쌓을수록, 궁극적으로 문제를 해결하는 과정은 덜 고통스럽게 될 것이다. 문제가 있다고 해서 기죽지 말자, 모든 문제점들은 첫인상 보다는 더 쉽다는 것을 알게 될 것이다.

아두이노 기반의 프로젝트들은 모두 하드웨어와 소프트웨어를 둘 다 만들기 때문에, 잘못된 지점을 찾아야 할 것이 한 곳 이상이다. 버그를 찾을 때는 아래의 세 가지 항목을 따르도록 하자.

이해

여러분이 사용하는 부품들이 어떻게 동작하는지 최대한 이해하도록 노력하라. 또한, 프로젝트를 완성했을 때 부품들이 어떻게 역할을 수행하는지 상상해 보도록 하자. 이 접근방법은 각각의 부품들을 독립적으로 테스트 하는 방법을 떠오르게 해 줄 것이다.

단순화와 세분화

고대 로마인들은 종종 분할통치를 언급했었다. 여러분의 이해하는 것을 바탕으로 프로젝트를 -머릿속으로- 각각의 구성부품으로 나누어 보고 각 부품들이 시작하고 끝날 때의 동작을 찾아내 보도록 하자.

제외하기와 확인하기

문제점을 살펴보는 동안, 각 구성부품을 독립적으로 테스트하여, 각각의 부품들이 개별적으로 동작하는지 확인한다. 점차적으로 프로젝트의 어떤 부품들이 역할을 수행하고 있는지와 어떤 부품들이 의심스러운지를 확실히 할 수 있게 된다.

디버깅은 이 과정들을 소프트웨어에 적용할 때 사용하는 단어이다. 1940년대의 그레이스 후퍼가 디버깅이라는 말이 처음 사용한 것으로 알려져 있다. 그 당시의 컴퓨터는 대부분 전기장치들로 구성되어 있었는데, 그 중 하나의 기계장치에 벌레들이 끼어서 멈추는 일이 발생하여 벌레를 제거(de-bug)한다는 말이 쓰이기 시작했다. 오늘날의 버그들 중 많은 부분은 더 이상 -과거에 그래왔던 것처럼- 물리적인 것(벌레)이 아니며, 가상의 것으로 보이지 않는다. 그래서 가끔은 버그를 확인하는데 길고 지루한 과정이 필요하게 되었다.

보드 테스트

가장 첫 번째 예제인 “LED 깜박이기”가 동작하지 않는가? 그렇게 의기소침할 필요는 없다. 이제부터 어떻게 해야 하는지 알아보자. 여러분의 프로젝트를 비난하기에 앞서, 여러분은 비행기 조종사들이 이륙 전에 비행기를 제대로 날게 하기 위해 체크리스트를 확인하는 것처럼, 몇 가지 것들을 순서대로 확인할 필요가 있다.

USB케이블로 아두이노를 여러분의 컴퓨터의 USB 포트에 연결한다.

  • 컴퓨터가 켜져 있는지 확인한다(어리석게 들릴 수도 있지만 이런 일이 정말로 발생한다). PWR라고 표시된 녹색 빛이 들어와 있다는 것은 컴퓨터가 아두이노에게 전원을 공급하고 있다는 것을 의미한다. 이 LED가 매우 희미한 상태라면, 전원에 무엇인가 문제가 있을 것이다. 다른 USB케이블을 사용해 보고, 컴퓨터의 USB포트와 아두이노의 USB 플러그를 살펴 손상이 없는지 확인한다. 잘못된 부분이 없다면 컴퓨터의 다른 USB포트를 사용해 보거나, 아예 다른 컴퓨터를 사용해 본다.
  • 아두이노가 새것이라면, L로 표시된 노란 LED가 불안정한 패턴으로 깜박이기 시작할 것이다. 이것은 공장에서 보드를 검사하기 위한 목적으로 심은 테스트 프로그램이다.
  • 외장 전원(어댑터)을 사용 중이며, 이전 버전의 아두이노(Extreme, NG, Diecimila)를 사용한다면, 전원이 잘 꽂혔는지 확인하고, SV1이라고 표시된 점퍼가 외장 전원 쪽의 두 핀에 연결되어 있는지 확인한다.

참고: 다른 스케치에서 문제가 발생할 경우나 보드가 제대로 동작하는지 확인할 필요가 있는 경우. 첫 번째의 “LED 깜박이기” 예제를 아두이노 IDE에서 열어 보드에 올려보자. 보드에 붙어있는 LED가 1초에 한 번씩 깜박이는 지로 보드의 이상 유무를 확인할 수 있다.

이 단계들을 모두 성공적으로 마쳤다면, 이제 여러분의 아두이노가 바르게 동작한다고 확신할 수 있다.

브레드보드에 만든 회로 테스트

이제 아두이노의 5V, GND핀에서 점퍼선을 사용해 브레드보드의 양극과 음극 레일에 연결한다. 만약, 녹색의 PWR(전원) LED가 꺼진다면 점퍼선을 즉시 제거하자. 이 반응은 의미는 여러분의 회로에 커다란 실수가 있다는 것으로, 회로 중 어딘가가 “쇼트”되어 있을 것이다. 이 경우 아두이노에서 너무 많은 전류를 끌어 쓰게 되며, 여러분의 컴퓨터를 보호하기 위해 전원을 끊게 된다.

참고: 만약 여러분의 컴퓨터에 손상을 줄 주도 모른다는 우려가 든다면, 많은 컴퓨터의 전류 보호기능은 잘 동작하며 빠르게 반응한다는 것을 기억하자. 또한 아두이노 보드에는 전류-보로 장치인 “폴리퓨즈(PolyFuse)“가 장착되어 있어 잘못된 부분이 제거되면 보드가 스스로 리셋 한다.

만약 정말로 의심스러우면, 항상 아두이노 보드를 외장 전원이 달린 USB 허브에 연결하라. 이렇게 하면 끔찍하게 잘못된 일이 벌어져도 여러분의 컴퓨터 대신 USB 허브가 전사할 것이다.

숏 서킷이 발생하면, 여러분은 “각개격파” 과정을 시작해야 한다. 반드시 프로젝트의 모든 센서들을 살펴보고, 한 번에 하나씩 연결해 보라.

언제나 가장 먼저 살펴보기 시작해야 할 것은 (5V와 GND에 연결된) 전원 이다. 둘러보고, 회로의 각각의 부분이 적절하게 전원이 연결되어 있는지 확인하라.

무언가를 고치는데 있어서 가장 중요한 규칙은 한 번에 하나씩 바꿔가며 차근차근 작업을 진행해 보는 것이다. 저자의 학교 교수님이자 첫 번째 고용주인 마우리지오 피로라(Maurizio Pirola)는 이 규칙을 내 머릿속에 밖아 두었다. 무엇인가를 디버깅할 때, 그리고 일이 잘 풀리고 있지 않을 때 마다(믿어도 된다. 이런 일은 정말 자주 일어난다) 그의 얼굴이 내 머릿속에 나타나 “한 번에 하나씩 고쳐봐… 한 번에 하나씩 고쳐봐” 하고 말을 한다. 그리고 대개 이 방법을 사용해 나는 모든 것들을 고칠 수 있었다. 이 방법이 매우 중요한 이유는, 여러분이 어떻게 문제점을 고쳤는지 알 수 있다는 것이다 (많은 수정 내용 중 어떤 것으로 인해 문제를 해결되었는지를 놓치는 경우는 정말 많기 때문에, 한 번에 하나씩 해보는 것이 정말 중요하다).

각각의 디버깅 경험으로 부터 여러분의 머리에는 결점들과 가능한 수정방법에 대한 “지식기반”이 구축된다. 그리고 여러분이 알아채기도 전에 여러분은 전문가가 되어 있을 것이다. 여러분은 매우 멋져 보이게 될 텐데, 그 이유는 신입생들이 “이게 잘 안 돼요!”라고 말하면, 여러분은 재빨리 스윽 보고, 1초도 되지 않아 답을 내어 줄 수 있기 때문이다.

문제를 고립하기

또 하나의 중요한 규칙은 문제를 재현하는 확실한 방법을 찾는 것이다. 여러분의 회로가 무작위로 이상 동작을 보인다면, 정확히 어떤 시점에 문제가 발생하는지, 원인이 무엇인지를 찾는데 전력을 다 해야 한다. 이 과정을 통해 여러분은 가능한 경로에 대해 생각해 보게 될 것이다. 또한 이 과정은 다른 사람들에게 문제점을 설명해 줄 때도 매우 유용한다.

또한, 문제점을 가능한 자세하게 기술하는 것은 해결 방법을 찾기 위한 좋은 방법이다. 문제점이 어떤지 설명해 줄 사람을 찾아보라-많은 경우, 문제를 서술하는 과정에서 여러분의 머리에서 해결방법이 떠오를 것이다. 브라이언 W. 케닝험과 롭 파이크는 저서 Practice of Programming (Addison-Wesley, 1999)에서 다음과 같은, 한 대학의 일화를 소개하고 있다. “곰돌이 인형을 헬프데스크에 두고, 이상한 버그가 있는 학생들은, 진짜 사람인 상담자에게 말하기에 앞서, 인형에게 문제를 설명해야만 한다.”

IDE에서 발생하는 문제점들

일부 경우, 특히 OS로 윈도를 사용한다면, 아두이노 IDE를 사용하면서 문제점을 발견할 수 있을 것이다.

아두이노 아이콘을 더블클릭했을 때 오류가 나온다면, 또는 아무 일도 일어나지 않는다면, 아두이노를 실행하는 다른 방법인, run.bat 파일을 더블클릭 해 보자.

또한, 윈도 사용자들은 윈도가 COM 포트 번호를 COM10 이상으로 할당하는 경우 문제가 될 가능성이 있다. 이런 일이 발생하면, 보통 아두이노에서 사용하기 위해 확실하게, 윈도에서 낮은 포트 번호를 할당하도록 해야 한다. 먼저 시작 메뉴에서 장치 관리자를 연다. 컴퓨터(비스타) 또는 내 컴퓨터(XP)에서 우-클릭하고 설정을 선택한다. 윈도 XP 에서는 하드웨어를 선택하고 장치 관리자를 선택한다. 비스타에서는 장치 관리자(창의 왼쪽에 있는 테스크 리스트에 있다.)를 클릭한다.

“포트 (COM & LPT)” 하위에 있는 시리얼 장치를 찾아보라. 포트 번호가 COM9 이하인 사용하지 않은 시리얼 장치를 찾아라. 그리고 포트 설정 탭을 선택하여 고급기능을 클릭한다. COM 포트 번호를 COM10 이상으로 설정하고 OK를 클릭, 설정 다이얼로그를 닫기 위해 다시 OK를 클릭한다.

이제, 아두이노의 USB 시리얼 포트에도 각은 일을 한다. 한 가지 바꿀 점은 COM 포트를 여러분이 비워 둔 번호에(COM9 이하로) 할당하는 것이다.

위에 제시된 방법으로 해결되지 않거나, 여기에 나오지 않은 문제를 만나게 된다면 아두이노 사이트의 문제해결 페이지, www.arduino.cc/en/Guide/Troubleshooting 을 확인해 보라.

온라인에서 도움을 얻는 방법

곤경에 빠졌을 때 도움을 요청하지 않고 혼자서 며칠씩을 허비하지 말라. 아두이노의 최대 장점 중 하나는 바로 아두이노 커뮤니티이다. 여러분의 문제점을 잘 적어서 질문한다면 언제나 커뮤니티에서 도움을 받을 수 있을 것이다.

무엇이든 검색엔진에 잘라내어 붙여보고(컨트롤 + C, 컨트롤 + V) 그 문제에 대해 언급한 사람이 있는지 살펴보는 습관을 갖도록 하라. 예를 들어, 아두이노 IDE가 거칠게 오류 문구들을 뿜어낸다면, 그 내용을 복사하여 구글에 붙여서 검색하여 결과를 살펴보라. 여러분이 작업하고 있는 코드의 일부분, 또는 단지 함수의 이름을 적어서 같은 방법으로 검색해 보자. 여러분의 주위를 둘러보라. 모든 것은 이미 발명되어 있고, 웹 페이지 어딘가에 저장되어 있다.

더 깊이 살펴보려면, 메인 웹사이트인 www.arduino.cc 부터 시작하여 FAQ(자주 묻는 질문)를 살펴보라 (www.arduino.cc/en/Main/FAQ), 그리고 playground(놀이터)를 살펴보자 (www.arduino.cc/playground). 이곳은 자유롭게 편집할 수 있는 위키로, 문서에 공헌하기 원하는 사용자라면 누구나 참여 가능하다. 위키는 전체 오픈 소스 철학에서 가장 훌륭한 것들 중 하나이다. 사람들은 여러분이 아두이노 할 수 있는 모든 것에 대해 문서화 하고 예제를 만드는데 기여한다. 프로젝트를 시작하기 전에 playground를 찾아보면 시작하는데 도움이 되는 코드 조각이나 회로도를 찾을 수 있을 것이다.

이 방법으로 아직도 답을 찾지 못했다면 포럼(www.arduino.cc/cgi-bin/yabb2/YaBB.pl)을 검색해 보라. 검색으로 찾을 수 없다면, 포럼에 질문을 올려라. 여러분의 문제점에 맞는 게시판을 골라야 한다. 하드웨어인지 소프트웨어 문제인지에 따라 각각의 영역이 있으며, 또한 포럼은 다섯 가지 언어를 지원한다. 질문에는 다음 내용을 포함하여 가능한 많은 정보를 적어라.

  • 사용하고 있는 아두이노 보드의 종류.
  • 아두이노 IDE를 실행하기 위해 사용하는 OS의 종류.
  • 여러분이 하려는 일에 대한 일반적인 설명을 적는다. 사용 중인 부품 중 이상한 부분의 데이터시트의 링크한다.

여러분이 질문을 얼마나 잘 갖추어 했느냐에 따라 답변의 개수가 결정된다.

무슨 일이 있어도 아래에 나열된 일들을 하지 않는다면 답변을 받을 확률은 올라간다. (이 규칙들은 아두이노뿐만 아니라 다른 어떤 온라인 포럼에서도 통한다)

  • 글 전체를 대문자7)로 작성. 이는 사람들이 많이 싫어하는 일이며, 여러분의 이마에 “초보자”라고 쓴 채로 돌아다니는 것과 같은 일이다.(온라인 커뮤니티에서 모두 대문자를 사용해 글을 적는 것은 “소리치는 것”을 의미한다)
  • 동일한 글을 포럼의 여러 다른 부분에 올리는 것.
  • 여러분의 글에 “어떻게 답변이 하나도 없나요?” 또는 더 안 좋은 “긴급”같이 간단한 댓글을 달아 답변을 “재촉하기”. 만약 댓글이 없다면, 여러분이 작성한 글을 살펴보라. 제목이 명확한가? 여러분이 직면한 문제를 올바른 단어를 사용해 설명하였는가? 공손한가? 항상 공손하게 질문하라.
  • “아두이노로 우주선을 만들고 싶은데 어떻게 하면 되죠?” 와 같은 글 적기. 이런 글은 사람들이 당신의 일을 당신을 위해 하길 원한다는 것을 의미하며, 진짜 팅커러 들에게 이런 접근 방법은 단순히 재미가 없다. 여러분이 만들려는 게 무엇인지 설명하고, 프로젝트의 한 부분에 관한 특정한 질문을 떼어내어 글을 쓰라.
  • 앞선 포인트의 다른 변종은, 질문이 명확한 무엇인가라면, 글에 달리는 내용에 비용이 지불되어야 한다는 것이다. 특정한 질문을 한다면 사람들은 기꺼이 당신에게 도움을 주지만, 당신의 일을 모두 해 주기를 요청한다면(그리고 돈을 주지 않는다면), 대개 별로인 답변이 달릴 것이다.
  • 학교에서 내준 것으로 의심되는 글을 올리거나, 숙제를 해달라고 포럼에 요청하기. 저자 같은 교수도 포럼을 돌아다니며 이런 학생들에게 큰 불이익을 준다.

부록 A/브레드보드

회로가 동작하도록 만들기 위해서는, 제대로 돌아가게 될 때 까지 많은 수정이 필요하다; 이것은 스케치에 해당하는 전자 분야의 일로 매우 빠르고 인터렉티브한 과정이다. 다양한 조합을 시도해 보면서 여러분의 디자인은 진화하게 된다. 최고의 결과물을 얻기 위해서는, 가장 빠르고, 실용적이며, 최대한 덜 부수는 방법으로 부품들 간의 연결을 바꿀 수 있는 방법을 사용해야 한다. 납땜은 시간이 많이 드는 과정이며, 부품들을 가열하고 식힐 때마다 매번 부품들에게 스트레스를 주기 때문에 명백히 이러한 규칙들에서 벗어난다.

이 문제의 해결책은 브레드보드라고 불리는 매우 실용적인 장치이다. 그림 A-1에서 보이듯이, 브레드보드는 스프링이 들어있는 접점인 구멍이 가득 뚫린 작은 플라스틱 보드이다. 전자부품의 다리를 구멍들 중 하나에 꽂으면, 그 구멍과 같은 세로열의 모든 구명이 전기적으로 연결된다. 각 구멍은 2.54 mm 의 간격으로 배열되어있다.

대부분의 부품들의 다리들은 표준 거리만큼 공간을 두고 배열되어 있기 때문에, 여러 개의 다리가 다린 칩은 브레드 보드에 잘 맞는다. 브레드 보드의 모든 접점들이 동일하지는 않다-약간 다른 부분이 있다. 가장 위와 아래에 있는 줄들(빨간색과 파란색이 칠해져 있고 + 와 - 가 표시되어 있다)은 가로방향으로 연결되어 있으며, 전원이나 그라운드가 필요할 때 점퍼선(회로에서 두 위치를 연결하기위해 사용하는 짧은 전선 조각)을 사용해 매우 빠르게 전원을 보드의 어느 곳으로든 전달하는 용도로 사용한다. 브레드보드에서 마지막으로 여러분이 알아야 할 것은 가운데에 위치한, 작은 칩의 넓이만큼 떨어진 큰 공간이다. 모든 세로 구멍 줄은 이 중간지점에서 끊기기 때문에, 가운데에 칩을 꽂아 넣으면 칩의 양쪽의 핀들이 쇼트 되지 않게 된다. 똑똑하지 않은가?

그림 A-1. 브레드보드

부록 B/저항과 커패시터 값 읽기

전자부품을 사용하기 위해서는 부품들을 구별할 수 있어야 하는데, 이는 초보자에게는 버거운 일 일수도 있다. 전자부품 매장에 있는 대부분의 저항들은 양쪽으로 다리들이 나와 있는 원통형의 것들로, 몸통에는 이상한 색의 선들이 그려져 있을 것이다. 최초의 상업용 저항이 만들어졌을 때는 저항의 몸통에 기록할 수 있을 만큼 작게 숫자들인 인쇄할 수 있는 방법이 없었기 때문에, 똑똑한 엔지니어들은 색갈이 있는 띠로 저항의 값을 표시하기로 했다.

현재의 초보자들은 이러한 표시들을 해독하는 방법을 알아야 한다. “기본”은 꽤 간단하다. 4개의 띠가 있고, 각 색깔들은 하나의 수자를 나타낸다. 보통, 색 띠 중 하나는 금색이다: 이 띠는 저항의 정밀도를 나타낸다. 띠들을 올바른 순서로 읽기 위해서는, 금색(또는 은색) 띠가 오른쪽에 오게 저항을 잡아야 한다. 그리고 각 색깔에 할당된 숫자들을 읽으면 된다. 아래의 표에 각 색깔에 해당하는 숫자 값들을 나열해 두었다.

검정색0
갈색1
빨강색2
주황색3
노란색4
초록색5
파란색6
보라색7
회색8
하얀색9
은색±10%
금색±5%

예를 들면, 갈색, 검은색, 주황색, 금색으로 표시된 것은 1 0 3 ±5% 를 의미한다. 쉽지 않은가? 하지만, 예외규칙이 있기 때문에 주의해야 한다. 세 번째 띠는 사실 값에 들어있는 0의 개수를 의미한다. 따라서 1 0 3 은 사실, 10 뒤에 0이 세 개 붙어 있음을 의미한다. 해서, 저항의 값은 10,000 옴 ±5% 가 된다. 전자쟁이들은 k(키로:1,000)나 M(메가:1,000,000) 단위로 값을 줄여서 적는 경향이 있기 때문에 10,000 옴은 보통 10k 옴으로, 10,000,000 은 10M 옴이라고 부른다. 엔지니어들의 모든 것들을 최적화하려는 나쁜 버릇의 결과로, 회로도들에서 보게 되는 4k7 같은 값은 4.7k 또는 4700을 의미한다는 것을 알아두자.

커패시터들은 조금 더 쉬운 방법으로 읽을 수 있다. 원통 모양의 커패시터(전해 커패시터)들은 일반적으로 값이 숫자로 인쇄되어 있다. 커패시터 값은 패럿(F) 단위를 사용한지만, 여러분이 사용하게 될 대부분의 커패시터들은 마이크로패럿(μF) 단위일 것이다. 따라서 100 μF 라고 표기된 커패시터의 값은 100 마이크로패럿 이다.

접시(납작한) 모양의 커패시터들(세라믹 커패시터)은 대부분 값을 표시할 만한 공간이 없기 때문에 피코패럿(pF)을 나타내는 세 숫자로 된 코드를 사용한다. 1,000,000 pF 은 1μF 과 같은 값이다. 저항을 읽는 방법과 유사하게, 세 번째 숫자는 앞의 두 숫자 뒤에 따라오는 0의 개수를 의미한다. 한 가지 차이점은 세 번째 숫자에 사용되는 0–5 는 0의 개수를 의미하며, 6과 7은 사용하지 않고, 8과 9는 다르게 처리한다. 8은 앞의 두 숫자에 0.01을 곱하라는 의미이며, 9는 0.01을 곱하면 된다.

따라서 104라고 표시된 커패시터의 값은 100,000 pF 또는 0.1 μF 이다. 229로 표시된 커패시터는 2.2 pF 이다.

부록 C/아두이노 퀵 레퍼런스

다음은 아두이노 언어에서 지원하는 모든 표준 명령어들에 대한 짧은 설명들이다.

더 자세한 내용을 참조하려면 다음 링크를 살펴보라: arduino.cc/en/Reference/HomePage

구조

아두이노 스케치는 두 부분으로 돌아간다.

void setup()

이곳이 여러분의 초기화 코드-스케치가 시작되어 주 작업을 반복적(loop)으로 하기에 앞서 보드를 셋업하기 위한 코드가 위치하는 곳이다.

void loop()

여러분의 주 코드는 이곳에 위치한다. 여기에 있는 명령문들은 보드가 꺼질 때 까지 계속 반복된다.

특수 기호들

아두이노에는 코드 줄, 주석, 코드 블록을 나타내기 위한 기호들이 사용된다.

; (세미콜론)

모든 명령문(코드 줄)은 세미콜론을 끝난다. 이 문법은 여러분이 자유롭게 코드를 구성할 수 있게 한다. 두개의 명령문은 같은 줄에 두는 것도, 각 명문을 세미콜론을 사용해 분리해 두면, 가능하다 (하지만, 이 경우 코드를 읽기가 더 힘들어 진다)

예제:

delay(100);

{} (중괄호)

이 기호는 코드 블록을 표시하기 위해 사용한다. 예를 들면, loop() 함수에 코드를 쓰려면, 코드의 앞뒤로 중괄호를 사용해야 한다.

예제:

void loop() {
    Serial.println("ciao");
}

주석

주석문들은 아두이노 프로세서에서 무시하는 문장 열이지만, 여러분 스스로가 이 코드 조각들이 무엇을 하는지 기억하는 용도로 정말로 유용하다. 아두이노에서 주석문들은 다음의 두 가지 스타일로 작성할 수 있다.

// 한 줄 주석: 이 문장은 줄의 끝까지 무시 됨
/* 여러 줄 주석:
    여러 줄을 사용해
    시를 작성할 수 있음
*/

상수

아두이노에는 특별한 값들로 미리 정의된 키워드들이 포함되어 있다.

예를 들어, HIGH 와 LOW는 여러분의 아두이노 핀을 켜거나 끌 때 사용된다. INPUT 과 OUTPUT은 특정 핀의 입력이나 출력으로 설정하는데 사용한다. true 와 false 는 이름대로 참과 거짓, 즉 조건문이나 표현식이 참인지 거짓인지를 의미한다.

변수

변수들은 여러분이 스케치에서 사용하거나 변경하기 위한 데이터를 저장하기 위해 아두이노의 메모리에 이름을 할당한 메모리 영역이다. 이름에서 유추할 수 있듯이 변수는 여러분이 원하는 대로 값을 바꿀 수 있다.

아두이노가 아주 간단한 프로세서이기 때문에, 변수를 선언할 때는 변수의 종류(타입)를 지정해 줘야 한다. 이렇게 함으로서 프로세서에게 여러분이 저장할 값의 크기를 알려주는 것이다.

다음은 사용 가능한 데이터 타입들이다:

boolean

참, 거짓을 의미하는 true 또는 false 두 값 중 하나를 담을 수 있다.

char

영문 한 글자(A 같은)를 담을 수 있다8). 모든 컴퓨터가 그러하듯, 여러분이 글자들을 볼 수 있어도 아두이노는 글자를 숫자로 저장한다. char를 숫자를 저장하기 위해서 사용할 때는 -128 에서 127 범위의 값을 담을 수 있다.

참고: 컴퓨터에서 주로 사용하는 문자 셋에는 두 종료가 있다. 아스키(ASCII) 와 유니코드(UNICODE)가 그것이다. 아스키는 127개의 글자들의 모음(셋)으로 시리얼 터미널 간 텍스트를 전송하거나, 메인프레임과 미니컴퓨터 같은 시간-공유 컴퓨터 시스템 등에서 사용된다. 유니코드는 훨씬 더 큰 값들의 모음으로 현대의 컴퓨터 오퍼레이팅 시스템에서 넓은 범위의 언어들(다국어)을 표현하는데 사용된다. 아스키는 여전히 라틴어와 아라비아 수, 구두점 같은 일반적인 타자기 기호를 사용하는 영어나, 이탈리아어처럼 짧은 비트수를 사용하는 언어들 주고받기에 유용하다.

byte

0에서 255 사이의 숫자들을 담는다. char와 같이 byte는 메모리에서 한 바이트만을 사용한다.

int

2 바이트의 메모리를 사용하며 -32,768 에서 32,768 사이의 숫자를 표현할 수 있다. 아두이노에서 가장 일반적으로 사용되는 데이터 타입이다.

unsigned int

int 와 같이 2 바이트를 사용하지만 unsigned(부호 없음) 라는 전치사처럼 음수 값을 담을 수 없다. 따라서 0 부터 65,535 사이의 숫자들을 담을 수 있다.

long

int의 두 배 크기의 데이터 타입으로 -2,147,483,648 에서 2,147,483,647 사이의 숫자들을 담을 수 있다.

unsigned long

long의 unsigned(부호 없는) 버전으로, 0 에서 4,294,967,295 사이의 값을 담을 수 있다.

float

이 타입은 꽤 크며, 실수(floating-point)를 담을 수 있다. 다시 말해, 소수점을 포함하는 숫자들을 담는데 사용할 수 있다. float는 여러분의 귀중한 RAM을 4바이트 사용하며, 이 타입을 다루는 함수들을 잘 동작하게 하려면 더 많은 코드 메모리가 필요하므로, float는 아껴서 사용하는 게 좋다.

double

두 배로 정밀한(Double-precision) 실수로, 최대 1.7976931348623157 x 10308 까지 담을 수 있다. 와우! 정말 크다!

string

아스키 글자들의 모음으로, 문자로 된 정보(여러분은 시리얼 포트를 사용하거나, LCD 디스플레이에 메시지를 전달할 때 string을 사용하게 될 것이다)를 담든데 사용한다. 저장 공간으로 string의 각 글자(char)들은 한 바이트를 사용하며, 아두이노에게 문자열의 끝을 알려주기 위해 널 문자(아스키코드 중 0) 하나가 추가로 쓰이게 된다.

char string1[]    = "Arduino"; // 7개의 char 문자들 + 1개의 null 문자
char string2[8] = "Arduino";   // 위와 동일

배열(array)

인덱스 값으로 접근할 수 있는 변수들의 리스트이다. array는 쉽게 접근할 수 있는, 값들로 된 테이블을 만드는데 사용한다. 예를 들어, 여러분이 LED의 밝기를 조절하기(fade) 하기 위해 밝기의 정도들을 저장하기 위해서 light01, light02, … 와 같은 여섯 개의 변수들을 만들 수도 있을 것이다. 하지만 다음과 같은 간단한 배열(array)을 사용하는 것이 더 좋은 방법이다:

int light[6] = {0, 20, 50, 75, 100};

배열을 선언하는데, 배열(array)이라는 단어는 실제로 사용되지 않는다. [] 와 {} 기호들이 배열을 선언하는 일을 한다.

제어 문

아두이노에는 여러분의 스케치의 논리적인 흐름을 제어하기 위한 키워드들이 포함되어 있다.

if . . . else

이 구조는 여러분의 프로그램에서 의사결정을 하는데 사용한다. if 뒤에는 반드시 괄호로 싼 질문이 따라와야 한다. 만약(if) 문장이 참(true)이면, 그 다음으로 나열된 것들이 실행된다. 만약 거짓(false)라면, else 문 다음에 따라오는 코드 블록이 실행된다. else 문을 사용하지 않고 if 문만을 쓰는 것도 가능하다.

예제:

if (val == 1) {
   digitalWrite(LED,HIGH);
}

for

지정한 수만큼 코드 블록을 반복한다.

예제:

for (int i = 0; i < 10; i++) {
       Serial.print("ciao");
}

switch case

여러분의 프로그램에서 if 문이 도로상의 분기점 같은 역할을 한다면, switch case 문은 복잡한 로터리 같은 기능을 제공한다. 이 구문은 여러분의 프로그램을 변수의 값에 따라서 다양한 방향으로 이끌어 주게 된다. 긴 if 문 리스트를 대치하여 코드를 간소하게 유지할 수 있기 때문에 switch case 문은 꽤 유용한다.

예제:

switch (sensorValue) {
     case 23:
        digitalWrite(13,HIGH);
        break;
     case 46:
        digitalWrite(12,HIGH);
        break;
     default: // 맞는 것이 없으면 이 내용이 실행 됨
        digitalWrite(12,LOW);
        digitalWrite(13,LOW);
}

while

if 문과 비슷하지만, 코드 블록을 지정한 상태가 참(true)인 동안(while) 계속 반복한다.

예제:

// 센서 값이 512 미만일 때 LED를 깜작이기
sensorValue = analogRead(1);
while (sensorValue < 512) {
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,HIGH);
    delay(100);
    sensorValue = analogRead(1);
}

do . . . while

while 문과 같지만, 상태를 평가하기에 전에 코드를 먼저 실행한다. 이 구문은 상태를 검사하기에 앞서 여러분의 코드 블록을 적어도 한번 수행해야 하는 경우에 사용한다.

예제:

do   {
   digitalWrite(13,HIGH);
   delay(100);
   digitalWrite(13,HIGH);
   delay(100);
   sensorValue = analogRead(1);
} while (sensorValue < 512);

break

이 명령어는 반복문에서 빠져나와 반복문 아래에 위치한 코드를 수행하게 한다. 또한, switch case 구문에서 각각의 섹션들을 분리하기 위해서도 사용된다.

예제:

// 센서 값이 512 미만일 때 LED를 깜작이기
do   {
    // 버튼이 눌리면 반복문을 빠져 나감
    if (digitalRead(7) == HIGH)
       break;
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,HIGH);
    delay(100);
    sensorValue = analogRead(1);
} while (sensorValue < 512);

continue

루프 안에서 사용하면, 루프안의 남은 코드들을 건너뛰고 강제로 다시 상태를 검사하도록 한다.

Example:

for (light = 0; light < 255; light++)
{
   // 140 보다 크고 200 보다 작은 강도는 생략
   if ((x > 140) && (x < 200))
     continue;
   analogWrite(PWMpin, light);
   delay(10);
}

return

실행중인 함수를 멈추고 함수에서 되돌아가도록(return) 한다. 또한 함수 안에서 값을 반환하는데 이 명령어를 사용할 수 있다. 예를 들어, computeTemperature() 라는 온도를 계산하는 함수를 호출하고, 결과 값을 여러분의 코드로 반환하게 하려면, 아래와 같이 함수를 작성해야 한다.

int computeTemperature() {
     int temperature = 0;
     temperature = (analogRead(0) + 45) / 100;
     return temperature;
}

계산과 수식

특별한 문법을 사용하여 여러분의 아두이노에게 복잡한 계산을 하도록 할 수 있다. + 와 - 는 여러분이 학교에서 배운 것과 같은 동작을 한다, 곱셈은 * 로 표시하며, 나눗셈은 / 로 표시한다.

추가로 “모듈로” (%)라 불리는 특별한 연산자가 있다. 이 연산자는 정수로 나눈 나머지를 반환한다. 수식들을 그룹화하기 위해 얼마든지 괄호를 사용할 수 있다. 여러분이 학교에서 수학 시간에 배운 것과 다르게, 꺾인 괄호와 중괄호는 다른 용도(각각, 배열의 인덱스와 코드 블록으로 쓰임)로 위해 사용되므로 수식에 사용할 수 없다.

예제

a =   2 + 2;
light = ((12 * sensorValue) - 5 ) / 2;
remainder = 3 % 2; // 3 / 2의 나머지는 1이므로 remainder는 1이 됨

비교 연산자

if, while, for 문에서 조건문을 기술할 때 다음의 연산자들을 사용할 수 있다:

  • == 같다
  • != 다르다
  • < 작다
  • > 크다
  • ⇐ 작거나 같다
  • >= 크거나 같다

논리 연산자

여러 개의 조건문을 조합할 때 이 연산자들을 사용한다. 예를 들어, 센서로 부터 받은 값이 5에서 10 사이인지 검사하고자 한다면 다음과 같이 적을 수 있다:

if ((sensor => 5) && (sensor <=10))

논리 연산자는 세 가지가 종류가 있다. 모든 조건이 참이어야 참(and); &&, 조건 중 하나가 참이면 참(or); || 역(not); !

복합 연산자

이 연산자들은 코드를 값을 증가시키는 것 같은 매우 빈번한 동작을 좀 더 간결화 하기 위한 연산자이다.

예를 들어 value 값을 1 증가 시키려면 다음과 같이 쓸 수 있지만:

value = value +1;

복합 연산자를 쓰면 아래와 같이 줄일 수 있다:

value++;

증가와 감소 (-- 와 ++)

이 연산자들은 값을 1 만큼 증가 또는 감소시킨다. 주의해야 할 것이 하나 있는데, i++ 값을 먼저 평가하고 i를 1 만큼 증가시키는 반면, ++i 는 먼저 i 를 1 만큼 증가시킨 후 값을 평가한다. 같은 규칙이 - - 에도 적용된다. 9)

+= , –=, *= and /=

이러한 연산자들은 특정 수식을 더 짧게 쓸 수 있도록 해 준다. 다음의 두 표현은 동일한 결과가 나온다.

a = a + 5;
a += 5;

입/출력 함수

아두이노에는 입력과 출력을 처리하는 함수들이 있다. 이 책의 예제 프로그램들에서 이 함수들을 이미 보았을 것이다.

pinMode(pin, mode)

디지털 핀을 입력이나 출력으로 재설정 한다.

예제:

pinMode(7,INPUT); // 7번 핀을 입력으로 설정

digitalWrite(pin, value)

디지털 핀을 켜거나 끈다. digitalWrite를 사용하려면 우선 pinMode 함수로 명시적으로 핀을 출력(OUTPUT)으로 설정해야 한다.

예제:

digitalWrite(8,HIGH); // 8번 핀을 켬

int digitalRead(pin)

입력 핀의 상태를 읽는다. 핀에 전압이 인가되어 있으면 HIGH를, 전압이 없으면 LOW를 반환한다.

예제:

val = digitalRead(7); // 7번 핀을 읽어 val에 저장

int analogRead(pin)

아날로그 입력 핀에 인가된 전압을 읽어 0 에서 5V 전압을 의미하는, 0 에서 1023 사이의 값을 반환.

예제:

val = analogRead(0); // 아날로그 입력 핀 0번을 읽어 val에 저장

analogWrite(pin, value)

PWM 표시가 있는 핀의 PWM 비율을 변경한다. 11, 10, 9, 6, 5, 3번 핀들이 PWM을 지원할 것이다. 인자 value로 쓸 수 있는 값은 0 에서 255 사이로 0 에서 5V 전압을 의미한다.

예제:

analogWrite(9,128); // 9번 핀에 연결된 LED를 50% 밝기로 함

shiftOut(dataPin, clockPin, bitOrder, value)

데이터를 디지털 출력의 개수를 확장하는, 쉬프트 레지스터에 전달한다. 이 프로토콜은 하나의 핀을 데이터(dataPin)로, 또 하나의 핀을 클록(clockPin)으로 사용한다. bitOrder는 바이트의 순서(가장 낮은 비트가 먼저 오는지, 가장 높은 비트가 먼저 오는지)를 정한다. value는 실제도 전달할 바이트 이다.

예제:

shiftOut(dataPin, clockPin, LSBFIRST, 255);

unsigned long pulseIn(pin, value)

디지털 입력 핀으로 들어오는 펄스의 길이를 측정한다. 예를 들면, 적외선 센서나, 가속도 센서(accelerometers)같이 출력 값을 펄스의 길이 변화로 내는 센서들을 읽을 때 유용하다.

예제:

time = pulsein(7,HIGH); // 다음 펄스가 high인
                        // 시간을 측정

시간 함수

아두이노에는 시간이 얼마나 흘렀나를 측정하는 함수와, 스케치를 잠시 멈추는 함수들을 제공한다.

unsigned long millis()

스케치가 시작한 뒤로 흐른 시간을 미리 초 단위로 반환한다.

예제:

duration = millis()-lastTime; // 지난 시간 "lastTime"에서 시간이 얼마나 흘렀는지 계산

delay(ms)

주어진 미리 초만큼 프로그램을 잠시 멈춤

예제:

delay(500); // 0.5 초간 프로그램을 멈춤

delayMicroseconds(us)

주어진 마이크로 초 만큼 프로그램을 잠시 멈춘다.

예제:

delayMicroseconds(1000); // 1 미리 초 동안 대기

수학 함수

아두이노에는 많은 일반 수학 함수와 삼각 함수들이 포함되어 있다.

min(x, y)

두 값 x, y 중 더 작은 값을 반환한다.

예제:

val = min(10,20); // val 값은 10이 됨

max(x, y)

두 값 x, y 중 더 큰 값을 반환한다.

예제:

val = max(10,20); // val 값은 20이 됨

abs(x)

x의 절댓값, 음수인 경우 양수로 변환한 값을 반환한다. x가 5인 경우 5가 반환되며, x가 -5인 경우에도 5가 반환된다.

예제:

val = abs(-5); // val 값은 5가 됨

constrain(x, a, b)

a 와 b 사이로 제약된 x 값을 반환. 만약 x가 a보다 작으면, 이 함수는 그냥 a를 반환한다. 만약 x가 b보다 크면, 반환 값은 b가 된다.

예제:

val = constrain(analogRead(0), 0, 255); // val 값이 255가 넘지 않도록 함

map(value, fromLow, fromHigh, toLow, toHigh)

fromLow 부터 fromHigh 범위의 값을 toLow 에서 toHigh 범위로 사상(map) 한다. 아날로그 센서에서 읽은 값을 처리하는데 매우 유용하다.

예제:

val = map(analogRead(0),0,1023,100, 200); // 아날로그 핀 0번에서
                                          // 읽은 값을 100 에서 200
                                          // 사이로 사상

double pow(base, exponent)

기수(base)의 지수(exponent) 제곱을 반환한다.

예제:

double x = pow(y, 32); // y의 32승 값을 x에 저장

double sqrt(x)

x의 제곱근(루트:square root)을 반환한다.

예제:

double a = sqrt(1138); // 대략 33.73425674438

double sin(rad)

라디안단위로 주어진 각의 사인(sine) 값을 반환한다.

예제:

double sine = sin(2); // 대략 0.90929737091

double cos(rad)

라디안단위로 주어진 각의 코사인(cosine) 값을 반환한다.

예제:

double cosine = cos(2); // 대략 -0.41614685058

double tan(rad)

라디안단위로 주어진 각의 탄젠트(tangent) 값을 반환한다.

예제:

double tangent = tan(2); // 대략 -2.18503975868

난수(random) 함수

무작위로 추출한 숫자(난수)를 사용하려면, 아두이노의 유사난수 생성기를 사용할 수 있다.

randomSeed(seed)

아두이노의 유사난수 생성기를 초기화 한다. 비록 random()으로 발생한 수의 분포가 기본적으로 무작위일지라도, 어떤 순서로 발생하는지는 예측이 가능하다. 그래서 난수 생성기를 특정 난수 값으로 초기화 할 필요가 있다. 만약 연결하지 않은 아날로그 입력 핀이 있다면, 이 핀이 주변 환경(라디오 신호, 우주선, 핸드폰에서 나오는 전자기적 간섭, 형광등)으로부터 영향을 받아 임의의 노이즈 값을 반환하므로 이를 사용하라.

예제:

randomSeed(analogRead(5)); // 아날로그 핀 5번의 노이즈에서 랜덤 사용

long random(max)

long random(min, max)

정해준 최소(min)와 최대(max - 1) 값 사이의, long integer 타입의 유사랜덤 값을 반환한다. 최솟값을 지정하지 않으면, 최솟값은 0이 된다.

예제:

long randnum = random(0, 100); // 0 부터 99 사이의 수
long randnum = random(11);     // 0 부터 10 사이의 수

시리얼 통신

5장에서 살펴 본 것과 같이, 여러분은 USB 포트를 통해 시리얼 통신 프로토콜로 아두이노와 통신할 수 있다. 다음이 시리얼 함수들이다.

Serial.begin(speed)

시리얼 데이터를 주고받을 수 있도록 아두이노를 준비한다. 일반적으로 이 함수와, 아두이노 IDE의 시리얼 모니터의 시리얼 포트의 속도(speed)로 초당 9600 비트(9600 bps)를 사용하지만, 다른 속도를 사용할 수도 있다. 보통 115,200 bps 이상은 사용하지 않는다.

예제:

Serial.begin(9600);

Serial.print(data)

Serial.print(data, encoding)

데이터를 시리얼 포트로 전송한다. 인코딩(encoding)은 옵션으로, 지정하지 않았을 때는 데이터를 가능한 한 평범한 텍스트처럼 취급한다.

예제:

Serial.print(75);         // "75" 출력
Serial.print(75, DEC);    // 위와 동일
Serial.print(75, HEX);    // "4B" (75 의 16진수
Serial.print(75, OCT);    // "113" (75 의 8진수)
Serial.print(75, BIN);    // "1001011" (75 의 2진수)
Serial.print(75, BYTE);   // "K" (바이트를 그대로 전송하면 
                          // 결과적으로 ASCII값 75, "K"가 된다)

Serial.println(data)

Serial.println(data, encoding)

데이터를 입력하고 리턴이나 엔터를 눌렀을 때처럼, 캐리지 리턴과 라인피드(\r\n, 줄 바꿈)가 추가된다는 것을 제외하면 Serial.print()와 동일하다.

예제:

Serial.println(75);          // "75\r\n" 출력
Serial.println(75, DEC);     // 위와 동일
Serial.println(75, HEX);     // "4B\r\n"
Serial.println(75, OCT);     // "113\r\n"
Serial.println(75, BIN);     // "1001011\r\n"
Serial.println(75, BYTE);    // "K\r\n"

int Serial.available()

read() 함수에서 사용하기 위해 시리얼 포트에 읽지 않은 바이트가 얼마나 있는지를 반환한다. 가능한 모든 데이터를 read() 로 읽은 뒤에는 새로운 데이터가 시리얼 포트에 올 때 까지 Serial.available()은 0을 반환한다.

예제:

int count = Serial.available();

int Serial.read()

도착하는 시리얼 데이터에서 한 바이트를 읽어(fetch)온다.

예제:

int data = Serial.read();

Serial.flush()

시리얼 포트로 도착하는 데이터들이 여러분의 프로그램이 처리할 수 있는 것 보다 빨리 들어오기 때문에, 아두이노는 모든 들어오는 데이터를 버퍼에 보관한다. 이 버퍼를 깨끗이 비우고 앞으로 새로운 데이터로 채우고자 한다면, flush() 함수를 사용하라.

예제:

Serial.flush();

부록 D/회로도 읽기

지금까지, 이 책에서는 회로를 조립하는 방법을 설명하기 위해 아주 자세한 그림을 사용했다. 하지만, 여러분이 생각하는 것처럼, 이 방법은 여러분의 경험한 회로를 빠르게 문서화하기에 좋은 방법이 아니다.

모든 분야에서 -좀 더 빠르게 또는 늦게- 비슷한 문제가 발생한다. 음악에서는, 여러분이 만든 훌륭한 노래를 음악 기보법을 사용해 기록해야 한다.

엔지니어들(실용적인 사람들)은, 회로를 문서화해서 나중에 다시 만들어 볼 수 있게 하기 위해서 또는, 누군가에게 전달하기 위해 회로의 본질만을 기록하는 방법을 개발했다.

전자 분야에서는 회로도를 사용해 회로를 기술하면, 커뮤니티의 다른 사람들도 여러분의 회로를 이해할 수 있게 된다. 각각의 부품들은 심벌로 표현되는데, 심벌의 모양은 각 부품의 모양이나, 본질적인 것을 요약한 것이다. 예를 들면, 커패시터는 두개의 금속판을 공기나 플라스틱으로 분리하여 만들며, 기호도 그런 모양이다.

또 다른 명확한 예는 원통형 물체에 구리선을 감아 만든 인덕터로, 당연히 기호도 같은 모양이다:

부품들 간의 연결은 보통 전선이나, 인쇄된 기판위의 트랙으로 이루어진다. 회로도에서는 간단히 선으로 표현한다. 두 전선이 연결되어 있을 때, 이 연결점은 두 선이 교차되는 곳에 커다란 점을 그려 표시한다.

이것이 기본적인 회로도를 이해하기 위해 필요한 모든 것이다. 다음은, 좀 더 이해하기 쉬운 심벌들과 심벌이 의미하는 것들의 리스트이다:

아마도 여러분들은 여기 있는 기호들의 변종을 접하게 될 수도 있다(예로, 두 종류의 저항 기호를 그림에서 볼 수 있다). 위키백과, en.wikipedia.org/wiki/Electronic_symbol 에서 더 많은 전자 기호들을 살펴보기 바란다. 편의상, 회로도는 왼쪽에서 오른쪽으로 그린다. 예를 들면, 라디오의 회로도를 그릴 때는, 왼쪽에 안테나부터 그리기 시작하여, 라디오 신호가 흘러가는 대로 오른쪽으로 그려 (가장 오른쪽에) 스피커를 그린다.

다음의 회로도는 이 책의 초반에 등장했던 푸쉬버튼 회로를 그린 것이다:

references

1)
옮긴이 주: 독일의 유명한 산업 디자이너
2)
옮긴이 주: 이 단어의 의미를 함축하는 마땅한 한글 단어는 찾기 어려운데, 척척박사 같은 사람을 생각하면 된다
3)
옮긴이 주: Sniffin'glue, 최초의 펑크 록 팬 잡지 중 하나
4)
Quoted in Sara Reese Hedberg, “MIT Media Lab’s quest for perceptive computers,” Intelligent Systems and Their Applications, IEEE, Jul/Aug 1998.
5)
옮긴이 주: 오래된 아두이노 보드들은 더 적은 저장용량과 메모리가 있는 ATMega168을, 그 이전에는 ATMega8을 사용했었다.
6)
역자 주: 안타깝게도 이 램프의 국내 가격은 4~6만원 이다. 대안을 찾아보자!
7)
옮긴이 주: 국내 포럼에서라면 모든 글자에 색을 사용하는 것과 같음
8)
옮긴이 주: 한글은 한 글자에 2~3 char가 필요하다
9)
옮긴이 주: 반복문과 비교문에서 값의 평가 순서가 문제가 될 수 있다. 어떤 줄임식을 써야하는지 확실하지 않다면 비슷한 일을 하는 다른 코드에서는 어떻게 쓰였는지를 확인해 보자.
getting_started_with_arduino.txt · Last modified: 2013/08/03 05:04 (external edit)