400 likes | 428 Views
Explore sensor control, light measurement, data processing techniques, and serial communication in the field of ubiquitous computing. Learn how to measure light intensity using a photodetector sensor.
E N D
Spring Semester, 2011 Ubiquitous Computing Practice- Part 2(Sensors, Serial Communication) - Laboratory of Intelligent Networks@ KUT (http://link.kut.ac.kr) Yong-hwan Kim
3. 조도 센서 제어 빛의 광량을 측정하는 조도 센서의 동작 및 센싱 데이터 처리 및 확인 Ubiquitous Computing
조도 센서 CDS • 조도 센서 CDS • ZigbeX-II에 장치되어 있는 조도 센서 CDS는 ATmega 128(ZigbeX-II의 8bit CPU)의 INT0과 ADC0 사이에 연결되어있다. • 조도 센서인 CDS는 주변의 광량에 따라 자신의 저항이 변하게 된다. • 결국, 출력포트인 ADC0에서는 변화된 전압의 양에 의해 광량을 감지할 수 있다. Ubiquitous Computing
Timer component를 이용하여 일정 시간마다 조도값을 읽어 시리얼통신하는 예제 OscilloscopeAppC.nc 1 2 3 4 5 6 7 8 9 10 11 12 13 configuration OscilloscopeAppC { } implementation { components OscilloscopeC, MainC, LedsC, new TimerMilliC (), new PhotoSensorC () as Sensor, SerialActiveMessageC as Comm; OscilloscopeC.Boot -> MainC; OscilloscopeC.SerialControl ->Comm; OscilloscopeC.AMSend ->Comm.AMSend[AM_OSCILLOSCOPE]; OscilloscopeC.Receive -> Comm.Receive[AM_OSCILLOSCOPE]; OscilloscopeC.Timer ->TimerMilliC; OscilloscopeC.Read ->Sensor; OscilloscopeC.Leds ->LedsC; } 별칭하여 사용 CDS 센서값 위한 component PC와 Serial 통신을 위한 component 상수값 0x93, 같은 type의 interface 간에만 송/수신 Ubiquitous Computing
기본 지식 • SerialControl interface(원형은 SplitControl) • AMSend interface Ubiquitous Computing
기본 지식 • Receive interface • Read interface Ubiquitous Computing
OscilloscopeC.nc • OscilloscopeC.nc 파일 • 경로: • /opt/tinyos-2.x/contrib/zigbex/Oscilloscope/OscilloscopeC.nc • 함수 실행순서 • Boot.booted() → SerialControl.start () • SerialControl.startDone () → startTimer () • startTimer () → Timer.startPeriodic () • 반복 Timer.fired () → Read.read () → 조도값 측정 → Read.read Done() → AMSend.send () Ubiquitous Computing
OscilloscopeC.nc 1: #include "Timer.h" 2: #include "Oscilloscope.h" 3: module OscilloscopeC 4: { 5: uses { 6: interface Boot; 7: interface SplitControl as SerialControl; 8: interface AMSend; 9: interface Receive; 10: interface Timer<TMilli>; 11: interface Read<uint16_t>; 12: interface Leds; 13: } 14: } 15: implementation 16: { 17: message_t sendbuf; 18: bool sendbusy; 19: oscilloscope_t local; 20: uint8_t reading; 21: bool suppress_count_change; 1~2: OscilloscopeC.nc 에서는 먼저 include 명령어 를 통해 Timer.h, Oscilloscope.h 에 있는 내용을 참 조한다. 5~13: uses에는 Module파일에서 사용할 인터페이스 들을 기술하고 있다. 17~21: 사용될 구조체변수 및 각종 변수들을 선언한 다. Ubiquitous Computing
OscilloscopeC.nc 22: void report_problem() { 23: call Leds.led0Toggle(); 24: } 25: void report_sent() { 26: call Leds.led1Toggle(); 27: } 28: void report_received() { 29: call Leds.led2Toggle(); 30: } 31: event void Boot.booted() 32: { 33: local.interval = DEFAULT_INTERVAL; 34: local.id = TOS_NODE_ID; 35: if (call SerialControl.start() != SUCCESS) 36: report_problem(); 37: } 38: void startTimer() 39: { 40: call Timer.startPeriodic(local.interval); 41: reading = 0; 42: } 22~24: 해당 함수 호출 시적색 LED를 토글시킨다. 25~27: 해당 함수 호출 시녹색 LED를 토글시킨다. 28~30: 해당 함수 호출 시황색 LED를 토글시킨다. 31~38: Boot.booted 함수에는 oscilloscope.h 헤더 파일에 정의된 oscilloscope_t 구조체 변수 local의 interval 과 id를 초기화 한다. 이어서 Serial통신을 하기 위해 SerialControl.start() 를 호출하여 시리얼을 시작한다. 시리얼 start 함수 호 출 시 성공하지 못했을 경우에는 report_problem()함 수를 호출하여 적색LED를 토글시킨다. Ubiquitous Computing
OscilloscopeC.nc 43: event void SerialControl.startDone (error_t error) { 44: startTimer(); 45: } 46: event void SerialControl.stopDone (error_t error) { 47: } 48: event message_t* Receive.receive (message_t* msg, void* payload, uint8_t len) { 49: oscilloscope_t *omsg = payload; 50: report_received(); 51: if (omsg->version > local.version) 52: { 53: local.version = omsg->version; 54: local.interval = omsg->interval; 55: startTimer(); 56: } 43~45: 시리얼 컴포넌트의 시작이 완료되면 SerialControl.startDone() 이벤트 함수가 호출된다. 이제 시리얼이 초기화되어 통신이 가능하므로 여기에 주기적인 동작을 위해 Timer를 시작한다. 46: SerialControl.stopDone() 은 사용하지 않더라도 구현해야 한다. 왜냐하면 SplitControl (SerialControl) interface를 사용하기 때문이다. Ubiquitous Computing
OscilloscopeC.nc 57: if (omsg->count > local.count) 58: { 59: local.count = omsg->count; 60: suppress_count_change = TRUE; 61: } 62: return msg; 63: } 64: event void Timer.fired() { 65: if (reading == NREADINGS) 66: { 67: if (!sendbusy && sizeof local <= call AMSend.maxPayloadLength()) 68: { 69: memcpy(call AMSend.getPayload (&sendbuf), &local, sizeof local); 70: if (call AMSend.send (AM_BROADCAST_ADDR, &sendbuf, sizeof local) == SUCCESS) 71: sendbusy = TRUE; 72: } 64~82: 타이머 만기시 Timer.fired() 이벤트 함수가 호출되고, 이 함수에서는 oscilloscope_t 구조체의 데이터를 저장하는 readings변수에 10개의 CDS데이 터가 다 입력됐을 경우, AMSend.send함수를 통해 데이터를 전송한다. 성공시 bool형 변수인 sendbusy 에 TRUE 값을 준다. 성공 하지 못했을 경우에는 report_problem()를 호출하여 적색 LED를 토글시킨 다. Payload에 접근할 때 AMSend.getPayload (&sendbuf)를 호출하면 Payload의 시작주소를 리턴 하게 된다. 그리고 함수의 마지막에 Read.read() 를 호출하여 CDS센서의 ADC 값을 요청한다. 실패 시에는 report_problem()를 호출하여 적색 LED 를 토글시킨다. Ubiquitous Computing
OscilloscopeC.nc 73: if (!sendbusy) 74: report_problem(); 75: reading = 0; 76: if (!suppress_count_change) 77: local.count++; 78: suppress_count_change = FALSE; 79: } 80: if (call Read.read() != SUCCESS) 81: report_problem(); 82: } 83: event void AMSend.sendDone (message_t* msg, error_t error) { 84: if (error == SUCCESS) 85: report_sent(); 86: else 87: report_problem(); 88: sendbusy = FALSE; 89: } 83: Serial 전송이 완료되면 녹색 LED 토글시킨다. Ubiquitous Computing
OscilloscopeC.nc 90: event void Read.readDone(error_t result , uint16_t data) { 91: if (result != SUCCESS) 92: { 93: data = 0xffff; 94: report_problem(); 95: } 96: local.readings[reading++] = data; 97: report_received(); 98: } 99: } 90~98: 조도 측정이 완료 되면 Read.readDone 이벤 트 함수가 호출되고 파리미터로 넘어온 조도 ADC값 을 local구조체의 readings 필드에 입력한다. 그런 후 report_received() 함수를 호출하여 황색 LED를 토글 시킨다. Ubiquitous Computing
Oscilloscope.h • Oscilloscope.h 에 정의된 데이터 포멧 enum{ NREADINGS = 10, /* Number of readings per message */ DEFAULT_INTERVAL = 256, /* Default sampling period. */ AM_OSCILLOSCOPE = 0x93 }; typedef nx_struct oscilloscope { nx_uint16_t version; /* Version of the interval. */ nx_uint16_t interval; /* Samping period. */ nx_uint16_t id; /* Mote id of sending mote. */ nx_uint16_t count; /* The readings are samples count * NREADINGS onwards */ nx_uint16_t readings[NREADINGS]; } oscilloscope_t; Ubiquitous Computing
Oscilloscope 예제 실습 $ cd /opt/tinyos-2.x/contrib/zigbex/Oscilloscope $ make zigbex Ubiquitous Computing
Oscilloscope 예제 실습 • USB-ISP와 ZigbeX노드를 결합 • USB-ISP mode는 ISP로 설정 • AVR Studio에서 Tools → Program AVR → Auto Connect 메뉴를 선택 • … 버튼을 눌러 Oscilliscope\build\zigbex\main.hex 선택 후 Program 버튼을 눌러 프로그램함 Ubiquitous Computing
데이터 확인(serial 통신) • SerialForwarder • 모트가 전송한 데이터를 시리얼 포트로부터 받아 처리 • port를 확인(명령어 motelist 또는 장치관리자 이용) • background program으로 수행(명령어 끝에 &붙임) • java program(Oscilloscope/java 내에 존재) • 위 프로그램이 분석한 정보를 바탕으로 화면에 비주얼하게 보여주는 프로그램 • USB-ISP의 스위치는 UART로 설정 $ java net.tinyos.sf.SerialForwarder –comm serial@COMX:57600 & $ cd /opt/tinyos-2.x/contrib/zigbex/Oscilloscope/java $ make $ ./run Ubiquitous Computing
(참고) java compile • java 프로그램 호환과정 • 1. javac 설치 폴터 환경변수 추가 • 2. Cygwin에서 tos-install-jni 수행 후, 결과 디렉토리를 환경변수 추가 • 3. /opt/tinyos-2.x/support/sdk/java 에서 make • 4. chmod -R 755 /opt/Java • 5. 2의 디렉토리에서 getenv.dll과 toscomm.dll을 찾아 window/system32/로 복사 Ubiquitous Computing
4. 온/습도 센서 제어 SHT11을 이용하여 온/습도를 얻고 시리얼 통신으로 확인 Ubiquitous Computing
온, 습도 센서 SHT11 • 온, 습도 센서 SHT11 • SHT11은 ZigbeX의 CPU와 직접적으로 연결되어 있다. • SHT11는 측정한 아날로그 신호를 디지털 신호로 바꾸어주는 ADC 기능을 내장하고 있어, CPU에 데이터를 바로 전송할 수 있다. • SHT11은 2개의 선을 통해 클럭(Clock)과 Data를 ATmega 128에 전송한다. Ubiquitous Computing
OscilloscopeSHT11 예제의 구성 • TimerC: 500ms 마다 Timer.fired() 호출 • SensirionSht11C : 온/습도의 측정값을 얻을 수 있는 component로,Sensor로 변경된 이름 사용 • SerialActiveMessageC: 시리얼 통신을 위한 component로,Comm으로 변경된 이름 사용 Ubiquitous Computing
기본 지식 • SensirionSht11C component • 온, 습도 제어 component Ubiquitous Computing
OscilloscopeAppC.nc configuration OscilloscopeAppC { } implementation { components OscilloscopeC, MainC, LedsC, new TimerMilliC (), new SensirionSht11C () as Sensor, SerialActiveMessageC as Comm; OscilloscopeC.Boot -> MainC; OscilloscopeC.Timer -> TimerMilliC; OscilloscopeC.Read_Humidity -> Sensor.Humidity; OscilloscopeC.Read_Temp -> Sensor.Temperature; OscilloscopeC.Leds -> LedsC; OscilloscopeC.SerialControl -> Comm; OscilloscopeC.AMSend -> Comm.AMSend[AM_OSCILLOSCOPE]; OscilloscopeC.Receive -> Comm.Receive[AM_OSCILLOSCOPE]; } //SensorSht11C는 온도와 습도 각각의 Read interface를제공하므로 두 개의 interface를wiring해야 함 Ubiquitous Computing
OscilloscopeC.nc • OscilloscopeC.nc 파일 • 경로: • /opt/tinyos-2.x/contrib/zigbex/ OscilloscopeSHT11/OscilloscopeC.nc • define 문에 따라 온도/습도 값을 전송 • 함수 실행순서(반복) • Timer.fired () → Read_Temp.read () → 온도값 읽기 • Read_Temp.readDone () → Read_Humidity.read () → 습도값 읽기 • Read_Humidity.readDone () → calc_SHT11(온도와 습도를 알맞게 변환) → AMSend.send () #define GET_HUMIDITY_DATA 0 이면 온도값 전송 #define GET_HUMIDITY_DATA 1 이면 습도값 전송 Ubiquitous Computing
OscilloscopeC.nc 1: #include "Timer.h" 2: #include <stdio.h> 3: #include "Oscilloscope.h" 4: #define GET_HUMIDITY_DATA 0 //0이면 온도 1이면 습도 5: module OscilloscopeC 6: { 7: uses { 8: interface Boot; 9: interface SplitControl as SerialControl; 10: interface AMSend; 11: interface Receive; 12: interface Timer<TMilli>; 13: interface Read<uint16_t> as Read_Humidity; 14: interface Read<uint16_t> as Read_Temp; 15: interface Leds; 16: } 17:} 18: implementation { 19: void calc_SHT11(uint16_t p_humidity , uint16_t p_temperature); 20: ... 3: include 를 통해 Oscilloscope.h 내용을 참조. 4: 온도 값을 전송할지, 습도 값을 전송할지 구분. #define GET_HUMIDITY_DATA 0 이면 온도값 #define GET_HUMIDITY_DATA 1 이면 습도값 7~16: OscilloscopeC 내에서 사용할 인터페이스들을 uses안에 기술한다. 18: implementation에서는 위에서 선언된 인터페이스 를 이용하여 실제 프로그램을 기술한다. Ubiquitous Computing
OscilloscopeC.nc 21: event void Timer.fired() { 22: if (reading == NREADINGS) 23: { 24: if(!sendbusy && sizeof local <= call AMSend.maxPayloadLength()) 25: { 26: memcpy(call AMSend. getPayload(&sendbuf), &local, sizeof local); 27: if(call AMSend.send (AM_BROADCAST_ADDR, &sendbuf, sizeof local) == SUCCESS) 28: sendbusy = TRUE; 29: } 30: if (!sendbusy) 31: report_problem(); 32: reading = 0; 33: if (!suppress_count_change) 34: local.count++; 35: suppress_count_change = FALSE; 36: } 37: if(call Read_Temp.read() != SUCCESS) 38: report_problem(); } 21~76: SHT11센서는 습도를 계산하기 전에 온도에 대한 정보를 필요로 한다. Timer.fired 이벤트 함수에 서 call Read_Temp.read()로 온도값을 요청하고, 해당 값이 반환되는 call Read_Temp.readDone() 이벤트 함수에서 습도값을 위해 Read_Humidity.read()를 호출한다. Ubiquitous Computing
OscilloscopeC.nc 40: event void Read_Humidity.readDone (error_t result, uint16_t data) { 41: if (result == SUCCESS) 42: { 43: atomic { 44: T_humi = data; 45: } 46: calc_SHT11(T_humi,T_temp); 47: if(GET_HUMIDITY_DATA){ 48: local.readings[reading++] = myhumi; 49: } 50: else{ 51: local.readings[reading++] = mytemp; 52: } 53: } 54: else{ 55: local.readings[reading++] = 0xffff; 56: report_problem(); 57: } 58: report_received(); 59: } 60: event void Read_Temp.readDone (error_t result, uint16_t data) { 61: if (result == SUCCESS) 62: { 63: atomic T_temp = data; 65: if(call Read_Humidity.read() != SUCCESS) 66: report_problem(); 67: } 68: else{ 69: report_problem(); 70: local.readings[reading++] = 0xffff; 71: } 72: } 73: void calc_SHT11(uint16_t p_humidity , uint16_t p_temperature) { 74: const float C1=-4.0; // for 12 Bit 75: ... 76: } 77 :} Ubiquitous Computing
OscilloscopeSHT11 예제 실습 • 컴파일 후 AVR Studio를 이용하여 노드에 포팅 • 자바 애플리케이션으로 확인 $ cd /opt/tinyos-2.x/contrib/zigbex/OscilloscopeSHT11 $ make zigbex $ java net.tinyos.sf.SerialForwarder –comm serial@COMX:57600 & $ cd /opt/tinyos-2.x/contrib/zigbex/Oscilloscope/java $ make $ ./run Ubiquitous Computing
java Listen 이용 $ export MOTECOM=serial@COMX:57600 $ java net.tinyos.tools.Listen //message_t 내용 출력 Ubiquitous Computing
SerialTest 이용 • SerialTest • 다운로드 (SerialTest.exe) • 실행 후 Port Configuration 수행하여 해당 포트번호와 57600 Baud 설정 후 Open Port 수행 Ubiquitous Computing
(참고) 데이터 분석 * Serial_Echo_Test 예제 참고 Ubiquitous Computing
TOS_Message(TinyOS→PC) • SYNC_BYTE • 데이터의 시작과 끝 0x7E • Packet Type • 0x45 : ack가 필요 없는 사용자 패킷 • Payload • DispatchID 0x00 (시리얼 메시지임을 의미) • CRC (Cycling Redundancy Check) • payload에 0x7E가 들어올 경우: 0x7D 0x5E • payload에 0x7D가 들어올 경우: 0x7D 0x5D (RFC 1662) Ubiquitous Computing
message_t 구조체 • /opt/tinyos-2.x/tos/types/message.h • serial 통신 및 RF 통신용 구조체 typedef nx_struct message_t { nx_uint8_t header[sizeof(message_header_t)]; nx_uint8_t data[TOSH_DATA_LENGTH]; //28 nx_uint8_t footer[sizeof(message_footer_t)]; //CRC 2byte nx_uint8_t metadata[sizeof(message_metadata_t)]; } message_t; Ubiquitous Computing
serial_header_t • 시리얼 통신을 위한 컴포넌트인 SerialActiveMessageC 사용시 header 영역에 들어가는 값 • /opt/tinyos-2.x/tos/lib/serial/Serial.h typedef nx_struct serial_header { nx_am_addr_t dest; //메시지 받는 하드웨어 주소(0xFFFF) nx_am_addr_t src; //패킷 보내는 노드의 주소 nx_uint8_t length; //data영역의 길이 nx_am_group_t group; //group id(0x00) nx_am_id_t type; //SerialActiveMessageC 배열에 } serial_header_t; 넣은 숫자 Ubiquitous Computing
cc2420_header_t • RF 무선통신을 위한 ActiveMessageC, AMSenderC, AMReceiverC 사용시 header 영역에 들어가는 값 • /opt/tinyos-2.x/tos/chips/cc2420/CC2420.h typedef nx_struct cc2420_header_t { nxle_uint8_t length; nxle_uint16_t fcf; nxle_uint8_t dsn; nxle_uint16_t destpan; nxle_uint16_t dest; nxle_uint16_t src; nxle_uint8_t type; } cc2420_header_t; Ubiquitous Computing
Oscilloscope(조도 센서 예제) data • /opt/tinyos-2.x/contribe/zigbex/Oscilloscope/Oscilloscope.h typedef nx_struct oscilloscope { nx_uint16_t version; /* Version of the interval. */ nx_uint16_t interval; /* Samping period. */ nx_uint16_t id; /* Mote id of sending mote. */ nx_uint16_t count; /* The readings are samples count * NREADINGS onwards */ nx_uint16_t readings[NREADINGS]; } oscilloscope_t; Ubiquitous Computing
Oscilloscope(조도 센서 예제) 패킷 분석 message_t serial_header_t oscilloscope_t Ubiquitous Computing
Oscilloscope(조도 센서 예제) 패킷 분석 7E 45 00 FF FF 00 00 1C 00 93 00 00 01 00 00 01 00 0A 05 0D 05 0E 05 08 05 08 05 1C 05 0A 05 14 05 1A 05 10 05 22 9F 45 7E 7E : 시작을 나타냄 45 : ACK가 필요 없는 패킷 타입 00 : DispatchID (시리얼은 0을 갖는다) FF FF : dst 주소 (0xFFFF 는 broadcast를 의미 – default 값) 00 00 : src 주소 (src 주소 설정 함수를 호출하지 않으면 0x0000) 1C : 데이터 length (28을 의미) 00 : group 93 : type 00 00 : version 01 00 : interval (256을 의미) 00 01 : id count : 00 0A (10번째 패킷을 의미) 05 0D : readings[0] (조도값 1) … 05 22 : readings[9] (조도값 10) 9F 45 : CRC 체크 byte 7E : 끝을 나타냄 Ubiquitous Computing
PC → TinyOS • SYNC_BYTE • 데이터의 시작과 끝 0x7E • Packet Type • 0x44 : ack가 필요한 사용자 패킷 • Sequence • 패킷의 재전송 Sequence를 의미하는 번호 (새 패킷은 0을 가짐) • Payload • DispatchID 0x00 (시리얼 메시지임을 의미) • CRC (Cycling Redundancy Check) • payload에 0x7E가 들어올 경우: 0x7D 0x5E • payload에 0x7D가 들어올 경우: 0x7D 0x5D (RFC 1662) Ubiquitous Computing