<283130C1D6294C454420B9D720BCBEBCAD20C1A6BEEE2E687770>

Similar documents
<4D F736F F F696E74202D205BBDC7BDC0345DC1B6B5B5BCBEBCADC1A6BEEE2E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - [이론4]TinyOS와NesC [호환 모드]

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202834C1D6C2F7207E2038C1D6C2F729>

슬라이드 1

(b) 미분기 (c) 적분기 그림 6.1. 연산증폭기연산응용회로

금오공대 컴퓨터공학전공 강의자료

K&R2 Reference Manual 번역본

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

Chapter #01 Subject

Microsoft PowerPoint - chap06-2pointer.ppt

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Lab 3. 실습문제 (Single linked list)_해답.hwp

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202834C1D6C2F7207E2038C1D6C2F729>

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

Lab 4. 실습문제 (Circular singly linked list)_해답.hwp

슬라이드 1

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A634C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

API 매뉴얼

BMP 파일 처리

API 매뉴얼

11장 포인터

윤성우의 열혈 TCP/IP 소켓 프로그래밍

실험 5

UI TASK & KEY EVENT

OSTSen-THL100 사용자설명서 Ver 1.1 Onsystech OSTSen-THL100 Ver1.1 1 of 8 Onsystech

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

실험 5

온습도 판넬미터(JTH-05) 사양서V1.0

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

정보보안 개론과 실습:네트워크

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

chap 5: Trees

OSTSen-PIR100 사용자설명서 Ver 1.1 Onsystech OSTSen-PIR100 V1.1 1 of 8 Onsystech

OCW_C언어 기초

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

쉽게 풀어쓴 C 프로그래밍

PowerPoint Presentation

Microsoft PowerPoint - additional01.ppt [호환 모드]

Microsoft PowerPoint - Java7.pptx

PowerPoint 프레젠테이션

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Microsoft PowerPoint - chap06-5 [호환 모드]

Microsoft PowerPoint - ch07 - 포인터 pm0415

PowerPoint 프레젠테이션

Microsoft Word - Lab.4

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

C 언어 프로그래밊 과제 풀이

중간고사

ISP and CodeVisionAVR C Compiler.hwp

슬라이드 1

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

UI TASK & KEY EVENT

KNK_C_05_Pointers_Arrays_structures_summary_v02

untitled

Chapter 4. LISTS

Microsoft PowerPoint - chap10-함수의활용.pptx

Microsoft PowerPoint - chap05-제어문.pptx

Microsoft PowerPoint - C++ 5 .pptx

Microsoft PowerPoint - chap03-변수와데이터형.pptx

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

PowerPoint 프레젠테이션

Microsoft Word - LKP-RTD 사용자 설명서

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

구조체정의 자료형 (data types) 기본자료형 (primitive data types) : char, int, float 등과같이 C 언어에서제공하는자료형. 사용자정의자료형 (user-defined data types) : 다양한자료형을묶어서목적에따라새로운자료형을

Microsoft PowerPoint - chap01-C언어개요.pptx

OSTSen-MOS100 사용자설명서 Ver 1.1 Onsystech OSTSen-MOS100 Ver of 8 Onsystech

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

제1장 Unix란 무엇인가?

Microsoft Word - Lab.7

PowerPoint Template

Microsoft PowerPoint - C프로그래밍-chap03.ppt [호환 모드]

(b) 연산증폭기슬루율측정회로 (c) 연산증폭기공통모드제거비측정회로 그림 1.1. 연산증폭기성능파라미터측정회로

12 강. 문자출력 Direct3D 에서는문자를출력하기위해서 LPD3DXFONT 객체를사용한다 LPD3DXFONT 객체생성과초기화 LPD3DXFONT 객체를생성하고초기화하는함수로 D3DXCreateFont() 가있다. HRESULT D3DXCreateFont

UI TASK & KEY EVENT

1장. 유닉스 시스템 프로그래밍 개요

커알못의 커널 탐방기 이 세상의 모든 커알못을 위해서

이도경, 최덕재 Dokyeong Lee, Deokjai Choi 1. 서론

OCW_C언어 기초

Chapter. 14 DAC 를이용한 LED 밝기제어 HBE-MCU-Multi AVR Jaeheung, Lee

슬라이드 1

Microsoft PowerPoint - es-arduino-lecture-03

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

PowerPoint Presentation

11장 포인터

<4D F736F F F696E74202D B3E22032C7D0B1E220C0A9B5B5BFECB0D4C0D3C7C1B7CEB1D7B7A1B9D620C1A638B0AD202D20C7C1B7B9C0D320BCD3B5B5C0C720C1B6C0FD>

0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4

Microsoft PowerPoint - 제11장 포인터(강의)

C 프로그램의 기본

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

Microsoft PowerPoint - [2009] 02.pptx

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

PowerPoint 프레젠테이션

Microsoft PowerPoint - 08-C-App-19-Quick-Preprocessor

Transcription:

실험 06 LED 및센서제어 < 실험목표 > LED 제어컴포넌트와 Timer 컴포넌트를응용하여 LED 의 on/off 를모스부호화하는방법을알아본다. 장비에장치되어있는조도센서에대해살펴보고, TinyOS 의 Oscilloscope 프로그램을통해측정된조도값을확인하는방법을알아본다. SHT11 센서를이용하여온도및습도값을측정하고, 그결과를시리얼통신을통해 PC 로전달하는방법을알아본다. - 1 -

(1) 모스부호와 LED 이장에서실습할 HelloWorld 애플리케이션은 "hello,world" 문자를모스부호로바꾸어 LED 에표 시하는프로그램이다. 모스부호는단점 (dot) 과단점의 3 배길이인장점 (dash) 으로구성되며, 문자 와문자사이에는 2 단점길이의간격을취한다. 예비보고서에서조사할모스부호를 LED 의온 / 오프에활용하여 hello,world" 단어를만들어보자. (2) 조도센서 조도를측정할수있는 CDS 센서는 Atmega128 의 INT0 와 ADC0 사이에연결되어있다. CDS 센서는주변의광량에따라자신의저항값이변하므로, INT0 로부터들어오는 3V 전압은광량에따라변화하는 CDS 의저항성분에의해영향을받는다. 그렇기때문에출력포트인 ADC0 에서는변화된전압의양에의해광량을감지할수있다. 그림 1 은 CDS 센서와 Atmega128 의연결모양을그린회로도이다. [ 그림 1] 조도센서와 CPU 사이의인터페이스 - 2 -

TinyOS 에서는조도센서를제어하기위해 Photo 컴포넌트라는것을제공하고있다. Photo 컴포넌트에서는 StdControl.init() 함수에의해노드가초기화를시작할때 ADCControl.bindPort(TOS_ADC_PHOTO_PORT, TOSH_ACTUAL_PHOTO_PORT) 함수를호출하여 INT0 의전압을활성화시켜조도센서에의한광량값을측정할수있도록한다. 표 2 는조도센서로활성화된 ADCC 컴포넌트에서제공하는함수들의목록이다. 특정 ADC 포트지정 ADC 의값얻기 함수및내용 ADCControl.bindPort() - 원하는 ADC 포트값을설정한다 (ADC 0 번포트는조도센서와연결되어있음 ). ADC.getData() - 앞에서설정된 ADC 포트로부터측정된값을얻기위해호출된다. event ADC.dataReady(uint16_t data) - ADC 가측정한값을 event 형태로반환한다. [ 표 2] ADCC 인터페이스에서제공하는함수들 Photo 컴포넌트를사용하는상위프로그램에서는조도데이터를얻기위해 ADC.getData() 함수를호출한다. ADC.getData() 함수가호출되면 CPU 의 INT0 와 ADC0 사이에있는 CDS 센서에의해조도정보를얻게되고, 그값은 event 형태로반환되는 ADC.dataReady(uint16_t data) 함수를통해상위컴포넌트에게전달된다. (3) 온도및습도센서 주변의온도및습도값을측정할수있는센서 SHT11 은 Atmega128 과직접연결되어있다. SHT11 센서는자체적으로측정한아날로그신호를디지털신호로바꾸어주는 ADC 기능이있어, 센싱한데이터를바로 CPU 로전송할수있다. SHT11 은 2 개의선을통해클럭과데이터를 Atmega128 에전송한다. [ 그림 2] 온습도센서와회로도 - 3 -

SHT11 로부터측정된센서값을읽기위해서는 Atmega128 과연결된두라인을통해일정한 클럭과명령어를입력시켜야한다. Atmega128 은데이터라인을통해비트단위의명령어를 SHT11 센서와주고받은후, 실제센서값을얻어온다. 데이터라인은클럭신호가 HIGH 일때만 값을읽어오는데, 이때데이터라인의신호는변하지않아야한다. 전송을시작하기전전송 시작을알리는펄스를먼저입력한후, 주소비트와명령어를 SHT11 에보내고사용자가 원하는데이터를읽어온다. 주소비트는현재 000 만사용하고있으며, SHT11 칩에전송하는 명령어는표 3 에나타나있다. 만약습도데이터를읽어오고싶다면주소비트 000 다음으로 00101 명령어를데이터라인으로보내주면된다. 명령어 코드 Reserved 0000x Measure Temperature 00011 Measure Humidity 00101 Read Status Register 00111 Write Status Register 00110 Reserved 0101x-1110x Soft reset 11110 [ 표 3] SHT11 온습도센서의명령어코드 명령어를넣어주면 Atmega128 은 SHT11 센서가습도측정을완료할때까지기다린다. 12 비트의습도데이터를얻기위해서는약 55ms 정도의시간이소요된다. 측정이완료되면 SHT11 은데이터라인을 LOW 로만들어준후, Atmega128 에게데이터를전송한다. Atmega128 은데이터라인을통해 12 비트의측정된데이터를읽어온후, CRC 에러체크필드의내용에따라 ACK 전송여부를결정한다. 만약데이터를읽어올수없다면 SHT11 과의접속을리셋시킨다. 해당하는명령어를보내주는함수는 HumidityProtocolM.nc 에 static inline char processcommand(int cmd) 라는함수로정의되어있다. 함수내용을살펴보면인터럽트초기화를거쳐 reset() 에정의되어있는내용에의해 Atmega128 과 SHT11 과의연결을재설정하고전송시작을알리는 initseq() 를호출한다. 그리고 CMD 에들어가는명령어에따라해당하는동작을하게된다. 습도값얻기 온도값얻기 함수및내용 Humidity.getData() - 앞에서설정된 ADC 포트로부터측정된값을얻기위해호출된다. event Humidity.dataReady(uint16_t data) - ADC 가측정한값을 event 형태로반환한다. Temperature.getData() - 앞에서설정된 ADC 포트로부터측정된값을얻기위해호출된다. event Temperature.dataReady(uint16_t data) - ADC 가측정한값을 event 형태로반환한다. [ 표 4] ADCC 인터페이스에서제공하는함수들 TinyOS 에서는 SHT11 온습도센서를제어하기위해 HumidityC 컴포넌트를제공하고있다. HumidityC 컴포넌트하위컴포넌트인 HumidityProtocolC 의도움으로습도측정값을얻을수있는 Humidity.getData() 함수와온도측정값을얻을수있는 Temperature.getData() 함수를제공받는다. 사용자는두함수를이용하여 SHT11 센서에온도및습도측정값을요청할수있고, - 4 -

event 형태의함수인 Humidity.dataReady(uint16_t data) 와 Temperature.dataReady(uint16_t data) 를통해습도및온도값을얻을수있다. (1) host PC, 모트 1 개, ISP 프로그램툴, 연결케이블 (1) 이장의이론파트의내용을실험전에숙지하여다음에관하여정리하시오. 1-1) 영문자와숫자, 마침표 (Period), 컴마 (Comma), 물음표 (Query) 에대해서모스부호를조사해정리하시오. 1-2) ADC 에서포트값을설정하는함수와측정된값을얻기위한함수를쓰시오 1-3) 습도값과온도값을얻기위한함수를쓰시오. (2) 4.(1) 에서수행하는모스부호프로그램실험을수행하기위하여소스코드를완성해보자. (3) 3.(2) 에서작성한프로그램을참고하여모스부호로자신의학번과이름을찍고 LED 로표현하도록프로그램을작성해보자. (4) 4.(2), (3) 에서수행하는센서제어프로그램실험을참고하여 1 초간격으로조도센싱, 온도센싱을번갈아수행하는프로그램을작성해보자. (1) 모스부호프로그램 HelloWorld 애플리케이션은 hello,world" 문자를모스부호로바꾸어 LED 에표시하는프로그램이 다. 본예제프로그램은 C: Program Files UCB cygwin opt tinyos-1.x contrib zigbex helloworld 폴더에있다. a. HelloWorld.nc HelloWorld 예제에서사용하는컴포넌트들의선언및연결구성은 configuration 파일인 HelloWorld.nc 에서확인할수있다. configuration HelloWorld { implementation { components Main, HelloWorldM, TimerC, LedsC; Main.StdControl -> HelloWorldM; Main.StdControl -> TimerC; HelloWorldM.Timer -> TimerC.Timer[ unique("timer") ]; HelloWorldM.Leds -> LedsC; - 5 -

HelloWorld 예제에서는 Timer 를세팅하여정한시간만큼 LED 를온 / 오프함으로써원하는영문자를모스부호로표현할수있다. 시간세팅과 LED 의온 / 오프를제어하기위해 HelloWorld.nc 파일에서 TimerC 컴포넌트와 LedsC 컴포넌트를선언하고, 자신의 module 인 HelloWorldM 컴포넌트와연결시킨다. b. HelloWorldM.nc 실제 HelloWorld 프로그램이구현되어있는 module 파일인 HelloWorldM.nc 파일을살펴보자. HelloWorldM.nc 파일을열면다음과같은소스코드를확인할수있다. #define MORSE_WPM 12 /* 분당문자전송속도 */ #define MORSE_UNIT ( 1200 / MORSE_WPM ) /* 한모스부호를나타내기위한밀리초 */ module HelloWorldM { provides { interface StdControl; uses { interface Timer; interface Leds; implementation { command result_t StdControl.init() { call Leds.init(); call Leds.redOff(); call Leds.yellowOff(); call Leds.greenOff(); command result_t StdControl.start() { // 1000ms 후에 Timer.fired() 가한번호출됨 return call Timer.start( TIMER_ONE_SHOT, 1000 ); command result_t StdControl.stop() { return call Timer.stop(); event result_t Timer.fired() { /* static char *morse 변수에 hello,world 문자열의포인터를저장한다. */ static char *morse = ".....-...-.. --- --..-- " ".-- ---.-..-.. -.. "; static char *current; - 6 -

if(!current ) current = morse; switch( *current ) { case ' ': /* pause: 두번의모스 units 시간동안 off 한다 */ dbg( DBG_USR1, "Morse: pause n" ); call Timer.start( TIMER_ONE_SHOT, 2 * MORSE_UNIT ); current++; break; case '.': /* dot: 한번의모스 unit 동안 on 하고한번의 unit 동안 off */ /* 소스코드채울부분 */ break; case '-': /* dash: 세번의모스 unit 동안 on 하고한번의 unit 동안 off */ /* 소스코드채울부분 */ break; default: /* 잘못된문자 : ignore */ dbg( DBG_USR1, "Morse: illegal character! n" ); break; /* 문자열의마지막 (Null 문자 ) 에오면 return 한다 */ if(!*current ) current = morse; HelloWorld 는하나의완전한애플리케이션으로실행되기위해서필수적으로요구되는 Main 컴포넌트를하부컴포넌트로두고, 다른컴포넌트들과자신의 module 부분을연결한다. Main 컴포넌트에의해처음실행되는것은 HelloWorldM 의 StdControl.init() 함수이다. 이함수안에는 LED 에대한초기화및오프에대한명령어가실행된다. 그다음호출되는함수는 StdControl.start() 함수로서, Timer 컴포넌트를통해 1 초 (1000) 후에한번의알람 (TIMER_ONE_SHOT) 만이호출되도록설정한다. Timer 컴포넌트는설정된대로 1 초후에 signal 을통해 HelloWorldM 내의 Timer.fired() 함수를호출하게되며, Timer.fired() 함수에서는 static 포인터변수인 morse 에저장되어있는 'hello,world' 모스값에따라 Red LED 의온 / 오프를명령하게된다. 예를들어, 모스부호공백 에서는 2 x MORSE_UNIT 시간동안 LED 에아무런변화를주지않고, 모스부호점. 에서는 MORSE_UNIT 시간동안 Red LED 를켠후, 다시 MORSE_UNIT 시간동안 Red LED 를오프시켜 current++ 를통해다음모스부호로넘어간다. 모스부호바 - 에서는 3 x MORSE_UNIT 시간동안 Red LED 를켠후, 역시 MORSE_UNIT 시간동안 Red LED 를오프시키고 current++ 를통해다음모스부호로넘어간다. 이와같은알고리즘에의해 HelloWorld 프로그램이설치된센서노드는 Red LED 를통해 'hello,world" 의모스부호를출력한다. - 7 -

(2) Oscilloscope 예제를이용한조도센서제어 Oscilloscope 예제는 125ms 마다 CDS 센서로부터측정값을받은후그내용을시리얼케이블을통해 PC 로전달하는프로그램이다. Oscilloscope 는 Oscilloscope.nc 와 OscilloscopeM.nc, OscopeMsg.h 의총 3 개파일로구성되어있다. Oscilloscope.nc 는각컴포넌트간의연결관계를나타내는 config 굵성되 tion 파일이며, OscilloscopeM.nc 는실제예제의동작이기술된 module 파일이다. OscopeMsg.h 는센서에서받아온데이터를 UART( 시리얼 ) 를통해주고받을수있도록 TinyOS 에서정의된데이터패킷구조체가선언되어있다. Oscilloscope 예제는크게 PC 와의시리얼통신을위한 UARTComm 컴포넌트와조도센서값을 얻기위한 DemoSensorC 컴포넌트, 그리고주기적인알람과동작여부를눈으로보여주기위한 TimerC 와 LedsC 컴포넌트로구성된다. 본예제프로그램은 C: Program Files UCB cygwin opt tinyos-1.x contrib zigbex Oscilloscope 폴더에있다. a. Oscilloscope.nc Oscilloscope.nc 파일에는 Oscilloscope 예제에서사용할여러컴포넌트들의선언및그들간의연결에대한내용이기술되어있다. 컴포넌트들은선언후프로그래머의편의에따라다른이름으로사용될수있다. 예를들면아래파일에기술되어있는 'DemoSensorC as Sensor' 의의미는 DemoSensorC 컴포넌트를 Sensor 라는이름으로사용하겠다는의미이며, 이문장이후로 Sensor 라는단어는 DemoSensorC 컴포넌트를의미한다. 같은인터페이스를갖는여러컴포넌트들을동시에사용할경우, 프로그램을기술할때컴포넌트이름간에혼돈이발생할수있기때문에 'UARTComm as Comm' 형태로인터페이스의이름을바꾸기도한다. 혹은 module 파일을고치지않고 configuration 파일의컴포넌트이름만교환함으로써다른동작이실행될수있도록할경우에도다른이름을선언한다. configuration Oscilloscope { implementation { components Main, OscilloscopeM, TimerC, LedsC, DemoSensorC as Sensor, UARTComm as Comm; Main.StdControl -> OscilloscopeM; Main.StdControl -> TimerC; OscilloscopeM.Timer -> TimerC.Timer[unique("Timer")]; - 8 -

OscilloscopeM.Leds -> LedsC; OscilloscopeM.SensorControl -> Sensor; OscilloscopeM.ADC -> Sensor; OscilloscopeM.CommControl -> Comm; OscilloscopeM.ResetCounterMsg -> Comm.ReceiveMsg[AM_OSCOPERESETMSG]; OscilloscopeM.DataMsg -> Comm.SendMsg[AM_OSCOPEMSG]; 여기서선언된 DemoSensorC 컴포넌트는 /opt/tinyos-1.x/sensorboards/basicsb 폴더에있는 DemoSensorC.nc 파일을호출한것으로, 조도센서를제어하는 Photo 컴포넌트를그대로링크하는컴포넌트이다. 이번예제는 DemoSensorC 컴포넌트를통해센서노드의조도값을받아오지만실제로는 DemoSensorC 컴포넌트의하부컴포넌트로구현되어있는 Photo 컴포넌트가조도값을제공한다. 다음으로선언된 UARTComm 컴포넌트는 PC 와의시리얼통신을위해만들어진컴포넌트로서 ReceiveMsg 인터페이스와 SendMsg 인터페이스를통해다음과같은함수를제공한다. ReceiveMsg SendMsg 함수및내용 event TOS_MsgPtr receive(tos_msgptr m) - 시리얼케이블을통해 PC 로부터어떠한메시지를받았을경우 event 형태로호출되는함수로, TOS_Msg 형태의포인터를반환한다. send(...) - 센서노드에서 PC 로 TOS_Msg 형태의파일을보내기위해호출되는함수이다. senddone(...) - send(...) 함수를통해메시지가모두전송되었을때 event 형태로호출되는함수이다. [ 표 5] UARTComm 에서제공하는함수들 b. OscilloscopeM.nc includes OscopeMsg; module OscilloscopeM { provides interface StdControl; uses { interface Timer; interface Leds; interface StdControl as SensorControl; interface ADC; interface StdControl as CommControl; interface SendMsg as DataMsg; interface ReceiveMsg as ResetCounterMsg; implementation - 9 -

{ uint8_t packetreadingnumber; uint16_t readingnumber; TOS_Msg msg[2]; uint8_t currentmsg; command result_t StdControl.init() { call Leds.init(); call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); call SensorControl.init(); call CommControl.init(); atomic { currentmsg = 0; packetreadingnumber = 0; readingnumber = 0; dbg(dbg_boot, "OSCOPE initialized n"); command result_t StdControl.start() { call SensorControl.start(); call Timer.start(TIMER_REPEAT, 125); call CommControl.start(); command result_t StdControl.stop() { call SensorControl.stop(); call Timer.stop(); call CommControl.stop(); task void datatask() { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)msg[currentmsg].data; packetreadingnumber = 0; pack->lastsamplenumber = readingnumber; pack->channel = 1; pack->sourcemoteid = TOS_LOCAL_ADDRESS; - 10 -

if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg), &msg[currentmsg])) { atomic { currentmsg ^= 0x1; call Leds.yellowToggle(); async event result_t ADC.dataReady(uint16_t data) { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)msg[currentmsg].data; pack->data[packetreadingnumber++] = data; readingnumber++; dbg(dbg_usr1, "data_event n"); if (packetreadingnumber == BUFFER_SIZE) { post datatask(); if (data > 0x0300) call Leds.redOn(); else call Leds.redOff(); event result_t DataMsg.sendDone(TOS_MsgPtr sent, result_t success) { event result_t Timer.fired() { return call ADC.getData(); event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m) { atomic { readingnumber = 0; return m; - 11 -

OscilloscopeM.nc 에서는먼저 include 명령어를통해 Oscilloscope.h 에있는내용을참조한후, module 안에 StdControl 인터페이스를 provide 로선언한다. 그리고 OscilloscopeM 내에서사용할인터페이스들을 use 로선언하는데, 이중센서와관련된인터페이스는 SensorControl 과 ADC 이다. 여기서 SensorControl 은 DemoSensorC 의 StdControl 을 rename 한것으로, Oscilloscope 자체적으로사용하는 StdControl 과 UARTComm 에서사용하는 StdControl 과의혼돈을방지하기위해 rename 한것이다. CDS 센서와관련된또하나의인터페이스는 ADC 이다. ADCC 는 CDS 센서로부터들어오는아날로그데이터를디지털로변환해주는장치와관련된컴포넌트이다. 참고로 ADCC.ADC[0] 은 CDS 센서의데이터를 ADC 로변환해주는포트이고 ADCC.ADC[1] 은적외선센서의데이터를변환해주는포트이다. DemoSensorC 컴포넌트의하위 Photo 컴포넌트에서는 ADC[0] 값을 CDS 센서의데이터값으로설정해주기때문에, 현파일에서사용된 ADC 인터페이스는오직 CDS 센서만을제어한다. 결국예제프로그램에서는 ADC 의포트번호와상관없이 ADC.getData() 함수와 ADC.dataReady() 함수를사용하여센서주변의조도값을얻어올수있다. OscilloscopeM.nc 의동작을순서대로살펴보자. Main 컴포넌트에의해제일먼저실행되는 StdControl.init() 함수에서 LED, SensorControl, CommControl 컴포넌트들및여러변수들을모두초기화한다. StdControl.start() 에서는 SensorControl, CommControl 을시작하고 Timer 를 125ms 마다한번씩 signal 을발생시키도록 Timer.start(TIMER_REPEAT, 125) 함수를호출한다. StdControl.stop() 에서는 SensorControl, CommControl 을정지하게하고 Timer 도정지시킨다. Timer 컴포넌트에의해 125ms 마다 signal 이발생하여 Timer.fired() 가호출되고, 그함수내부에서는 ADC.getData() 함수를호출하여 ADC[0] 에있는조도측정값을요청한다. 조도값의측정이끝나면 result_t ADC.dataReady(uint16_t data) 함수가 event 형태로 OscilloscopeM 파일내에서호출된다. 이함수내에서는받은조도측정값을시리얼통신으로 PC 에전달하기위해 OscopeMsg.h 에정의된패킷포맷형식으로변환시킨다. 그후, task 로된 datatask() 함수를호출하여 ADC.dataReady(uint16_t data) 함수로부터받은측정값을 DataMsg.send() 함수를통해시리얼로 PC 에게전송한다. OscilloscopeM 파일내에구현된내용을요약하자면, 125ms 마다측정한조도값을 UARTComm 컴포넌트의 Comm 인터페이스를통해 PC 로전송하는프로그램이다. c. OscopeMsg.h OscilloscopeM 파일에서사용한 Oscope 데이터포맷을정의하는헤더파일로, 포맷의구조는 그림 3 과같다. sourcemoteid lastsamplenumber channel Data[10] [ 그림 3] Oscope 메시지의형태 실제코드는다음과같다. - 12 -

enum { BUFFER_SIZE = 10 ; struct OscopeMsg { uint16_t sourcemoteid; uint16_t lastsamplenumber; uint16_t channel; uint16_t data[buffer_size]; ; struct OscopeResetMsg { /* Empty payload! */ ; enum { AM_OSCOPEMSG = 10, AM_OSCOPERESETMSG = 32, AM_ZIGBEXMSG = 0x27, AM_ZIGBEXRESETMSG = 0x28 ; 연결케이블을통해프로그램된센서노드로부터전송된데이터를확인하기위해서오실로스코프 자바애플리케이션을실행한다. 아래와같은명령어를입력하여애플리케이션을실행시킨다. export MOTECOM=serial@COM1:57600 java net.tinyos.oscope.oscilloscope 여기서 COM1 은센서가 PC 의 COM1 포트에연결되었을경우의세팅값이다. 장치관리자에서센서와 PC 가어느포트로연결되어있는지확인한후적절한값으로세팅한다. 자바애플리케이션을통해데이터가시리얼로전달되는것을확인할수있고빛의양에따라데이터를나타내는선이변화되는것을볼수있다. 혹시그래프가잘보이지않을경우 Scrolling 을체크하면그래프를확인할수있다. 그래도보이지않으면방향버튼을눌러서그래프를찾으면된다. - 13 -

[ 그림 4] 조도센서값을 Oscilloscope 로본결과 (3) 온도및습도센서제어 OscilloscopeSHT11 예제는앞에서조도측정을위해만들었던 Oscilloscope 예제와매우비슷하다. OscilloscopeSHT11 예제는 125ms 마다 HumidityC 컴포넌트를통해습도센서로부터측정값을받은후, 시리얼케이블을통해받은데이터를 PC 로전달하는프로그램이다. OscilloscopeSHT11 은 Oscilloscope.nc, OscillsocopeM.nc, OscopeMsg.h 의세가지파일로구성된다. 본예제프로그램은 C: Program Files UCB cygwin opt tinyos-1.x contrib zigbex OscilloscopeSHT11 폴더에있다. a. Oscilloscope.nc OscilloscopeSHT11 예제의 configuration 파일인 Oscilloscope.nc 에는하나의애플리케이션을시작할수있는 Main 컴포넌트와 125ms 마다 Timer.fired() 함수를호출하기위한 TimerC 컴포넌트, LED 를제어하기위한 LedsC 컴포넌트, 온도및습도의측정값을얻을수있는 HumidityC 컴포넌트그리고시리얼통신을위한 UARTComm 컴포넌트가선언되어있다. 여기서 HumidityC 컴포넌트와 UARTComm 컴포넌트는각각 SHT11 과 Comm 이라는이름으로선언되어사용된다 (HumidityC as SHT11, UARTComm as Comm). configuration Oscilloscope { implementation - 14 -

{ components Main, OscilloscopeM, TimerC, LedsC, HumidityC as SHT11, UARTComm as Comm; Main.StdControl -> OscilloscopeM; Main.StdControl -> TimerC; OscilloscopeM.Timer -> TimerC.Timer[unique("Timer")]; OscilloscopeM.Leds -> LedsC; //OscilloscopeM.SensorControl -> SHT11.; OscilloscopeM.SHT11_Humidity -> SHT11.Humidity; OscilloscopeM.SHT11_Temp -> SHT11.Temperature; OscilloscopeM.SHT11_Humidity_Error->SHT11.HumidityError; OscilloscopeM.SHT11_Temp_Error->SHT11.TemperatureError; OscilloscopeM.SplitControl->SHT11.SplitControl; OscilloscopeM.CommControl -> Comm; OscilloscopeM.ResetCounterMsg -> Comm.ReceiveMsg[AM_OSCOPERESETMSG]; OscilloscopeM.DataMsg -> Comm.SendMsg[AM_OSCOPEMSG]; 위의소스코드를통해, 사용된컴포넌트및 OscilloscopeM 과의연결구조를알수있다. b. OscilloscopeM.nc 다음으로 Oscilloscope 예제프로그램의 module 인 OscilloscopeM.nc 파일을살펴본다. OscilloscopeM.nc 파일을열면다음과같은소스코드를확인할수있다. includes OscopeMsg; module OscilloscopeM { provides interface StdControl; uses {... implementation { uint8_t TemppacketReadingNumber;... uint8_t mytemp, myhumi; void calc_sht11(uint16_t p_humidity,uint16_t p_temperature); - 15 -

command result_t StdControl.init() { call Leds.init(); call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); call CommControl.init(); call SplitControl.init(); atomic { currenttempmsg = 0; currenthumimsg = 0; TemppacketReadingNumber = 0; HumipacketReadingNumber = 0; TempreadingNumber = 0; HumireadingNumber = 0; dbg(dbg_boot, "OSCOPE initialized n"); command result_t StdControl.start() { call Timer.start(TIMER_REPEAT, 125); call CommControl.start(); call SplitControl.start(); command result_t StdControl.stop() { call Timer.stop(); call CommControl.stop(); call SplitControl.stop(); // 측정한온도값을시리얼통신을통해 PC 로전달하는함수 task void datatasktemp() { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)tempmsg[currenttempmsg].data; TemppacketReadingNumber = 0; pack->lastsamplenumber = TempreadingNumber; pack->channel = 1; pack->sourcemoteid = TOS_LOCAL_ADDRESS; // 시리얼통신을위해호출되는함수 if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg), - 16 -

&tempmsg[currenttempmsg])) { atomic { currenttempmsg ^= 0x1; call Leds.yellowToggle(); // 측정한습도값을시리얼통신을통해 PC 로전달하는함수 task void datataskhumi() { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)humimsg[currenthumimsg].data; HumipacketReadingNumber = 0; pack->lastsamplenumber = HumireadingNumber; pack->channel = 2; pack->sourcemoteid = TOS_LOCAL_ADDRESS; /* Try to send the packet. Note that this will return * failure immediately if the packet could not be queued for * transmission. */ if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg), &humimsg[currenthumimsg])) { atomic { currenthumimsg ^= 0x1; call Leds.yellowToggle(); // 온도정보를반환하는함수 async event result_t SHT11_Temp.dataReady(uint16_t data) { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)tempmsg[currenttempmsg].data; calc_sht11(data,data); pack->data[temppacketreadingnumber++] = mytemp; TempreadingNumber++; dbg(dbg_usr1, "data_event n"); - 17 -

if (TemppacketReadingNumber == BUFFER_SIZE) { post datatasktemp(); if (data > 0x0300) call Leds.redOn(); else call Leds.redOff(); // 습도정보를반환하는함수 async event result_t SHT11_Humidity.dataReady(uint16_t data) { struct OscopeMsg *pack; atomic { pack = (struct OscopeMsg *)humimsg[currenttempmsg].data; calc_sht11(data,data); pack->data[humipacketreadingnumber++] = myhumi; HumireadingNumber++; dbg(dbg_usr1, "data_event n"); if (HumipacketReadingNumber == BUFFER_SIZE) { post datataskhumi(); if (data > 0x0300) call Leds.redOn(); else call Leds.redOff();... event result_t Timer.fired() { timetick++; //return call SHT11_Temp.getData(); return call SHT11_Humidity.getData(); event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m) { atomic { TempreadingNumber = 0; HumireadingNumber = 0; return m; - 18 -

// 디지털로들어오는값을온도와습도단위로변환해주는함수 void calc_sht11(uint16_t p_humidity,uint16_t p_temperature) { const float C1=-4.0; // for 12 Bit const float C2= 0.0405; // for 12 Bit const float C3=-0.0000028; // for 12 Bit const float T1=0.01; // for 14 Bit @ 5V const float T2=0.00008; // for 14 Bit @ 5V float rh_lin; // rh_lin: 습도값 float rh_true; // rh_true: 온도값으로보정된습도값 float t_c; // t_c : Temperature [C] float rh=(float)p_humidity; // rh: 디지털습도값 [Ticks] 12 Bit float t=(float)p_temperature; // t: 디지털온도값 [Ticks] 14 Bit t_c=t*0.01-40; // 디지털온도값을 [C] 단위의온도값으로계산 rh_lin=c3*rh*rh + C2*rh + C1; // [%RH] 단위의습도값계산 rh_true=(t_c-25)*(t1+t2*rh)+rh_lin; // 온도값으로습도값보정 if(rh_true>100)rh_true=100; // 최대범위조정 if(rh_true<0.1)rh_true=0.1; // 최소범위조정 mytemp=(uint8_t)t_c; // [C] 단위온도값저장 myhumi=(uint8_t)rh_true; // [%RH] 단위습도값저장 OscilloscopeM.nc 에서는우선 OscopeMsg 를 include 시킨후, 실제구현부분에서사용할여러컴포넌트의인터페이스들을기술한다. implementation 의첫부분에서는사용할여러변수들및부수적인서브함수들을선언한다. 처음호출되는 StdControl.init() 함수는여러컴포넌트들및변수들의초기화와관련된일을처리한다. 그다음호출되는 StdControl.start() 함수에서는 125ms 시간마다반복해서 signal 을발생시키는 Timer 컴포넌트및시리얼통신부분을담당하는 CommControl 컴포넌트그리고 SHT11 컴포넌트와관련있는 SplitControl 컴포넌트를활성화시킨다. StdContro.start() 에서설정된 Timer 컴포넌트에의해 125ms 마다 Timer.fired() 함수가호출되고, 이함수에서는 SHT11_Humidity.getData() 함수를통해 SHT11 칩에게습도값을요청한다. 주석처리된 SHT11_Temp.getData() 함수를사용하면온도값을요청할수있다. HumidityC 컴포넌트는 SHT11 센서로부터요청한결과값을받은후, event 형태의 SHT11_temp.dataReady(uint16_t data) 함수나 SHT11_Humidity.dataReady(uint16_t data) 함수를통해상위컴포넌트에게센서값을전달한다. 이예제에서는 SHT11_Humidity.getData() 함수만호출했기때문에, - 19 -

SHT11_Humidity.dataReady(uint16_t data) 함수만동작될것이다. SHT11 칩으로부터습도나온도값을받게되면, calc_sht11(p_humidity, p_temperature) 를호출 하여, 받은측정값을실제사용되는온도및습도단위 (C, %RH) 로바꿔변수 myhumi 와 mytemp 에각각저장한다. 그후, datataskhumi() 함수나 datatasktemp() 함수를통해얻은센서값을시리얼통신을통해 PC 로전송한다. 사용자는자바애플리케이션을사용하여센서노드가시리얼통신으로전송하는 데이터값을확인할수있다. (1) 예비보고서에작성한모스부호프로그램을실제로센서에올려서잘못된부분을수정하 여프로그램을완성시키고소스코드를첨부하라. (2) 예비보고서에작성한센서제어프로그램을실제로센서노드에올려서잘못된부분을 수정하여프로그램을완성시키고실행중인오실로스코프프로그램을캡쳐하여수정된소스코드와 함께첨부하라. - 20 -