Ubiquitous Computing Practice - Part 3(RF통신, MAC 프로토콜) - Spring Semester, 2011 Ubiquitous Computing Practice - Part 3(RF통신, MAC 프로토콜) - Laboratory of Intelligent Networks @ KUT (http://link.kut.ac.kr) Yong-hwan Kim
5. Photo 센서 제어(RF 통신) BS520 Photo 센서를 이용하여 빛과 적외선을 측정하고 그 결과를 RF 무선통신을 통해 다른 노드에 전송 Ubiquitous Computing
적외선 센서 BS520 적외선 센서 BS520 적외선 센서인 BS520은 ATmega128의 ADC1과 연결되어 있다. 적외선의 강약에 따라 BS520의 출력 AD가 변화하기 때문에, ADC1로 들어오는 전류 변화량에 따라 적외선 값을 측정할 수 있다. Ubiquitous Computing
OscilloscopeUltraredRF 예제의 구성도 무선통신 시리얼케이블 ZigbeX 1 ZigbeX 0 OscilloscopeUltraRF BaseStation 1번 노드 – 256ms 마다 측정한 Photo 값을 10번 모아 RF 무선통신을 통해 주위에 broadcast 0번 노드 – RF 데이터를 수신하여 serial 전송 Ubiquitous Computing
OscilloscopeUltraredRF 예제의 구성 ActiveMessageC : RF 상태 관련 초기화(SplitControl 사용) AMSender, AMReceiverC : message 전송, 수신 AM_OSILLOSCOPE는 메시지 type 설정됨 message type이 AM_OSCILLOSCOPE일 경우만 receive Ubiquitous Computing
OscilloscopeApp.nc configuration OscilloscopeAppC { } implementation { components OscilloscopeC, MainC, LedsC, new TimerMilliC (), new SensirionSht11C() as Sensor, SerialActiveMessageC , new AMSenderC (AM_OSCILLOSCOPE), new AMReceiverC (AM_OSCILLOSCOPE); OscilloscopeC.Boot -> MainC; OscilloscopeC.RadioControl -> ActiveMessage; Oscilloscope.AMSend ->AMSenderC; Oscilloscope.Receive ->AMReceiverC; Oscilloscope.Timer ->TimerMilliC; Oscilloscope.Read ->Sensor; Oscilloscope.Leds ->LedsC; } Ubiquitous Computing
OscilloscopeC.nc OscilloscopeC.nc 파일 경로: 함수 실행순서 /opt/tinyos-2.x/contrib/zigbex/ OscilloscopeUltraredRF/OscilloscopeC.nc 함수 실행순서 Boot.booted() → RadioControl.start () RadioControl.startDone () → startTimer () startTimer () → Timer.startPeriodic () 반복 Timer.fired () → Read.read () → 적외선값 측정 → 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 RadioControl; 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 에 있는 내용을 참조한다. 3~14: Module파일에 uses에는 사용할 인터페이스 들을 기술하고 있다. Ubiquitous Computing
OscilloscopeC.nc 22: void report_problem() { call Leds.led0Toggle(); } 23: void report_sent() { call Leds.led1Toggle(); } 24: void report_received() { call Leds.led2Toggle(); } 25: event void Boot.booted() { 26: local.interval = DEFAULT_INTERVAL; 27: local.id = TOS_NODE_ID; 28: If (call RadioControl.start() != 29: SUCCESS) report_problem(); 30: } 31: void startTimer() { 32: call Timer.startPeriodic(local.interval); 33: reading = 0; 34: } 35: event void RadioControl.startDone (error_t error) { 36: startTimer(); 37: } 38: event void RadioControl.stopDone 39: } 25~30: Boot.booted함수에서는 oscilloscope.h 헤더 파일에 있는 oscilloscope_t 구조체 변수 local의 interval 과 id를 초기화 하고, ActiveMessageC에서 제공하는 RadioControl.start()를 호출하여 RF통신을 위한 초기화를 수행한다. 35~37: 시리얼 컴포넌트의 초기화가 완료되면 RadioControl.startDone 이벤트 함수가 호출되고, 이제 시리얼이 초기화되어 통신이 가능하므로 여기에 센서 데이터를 읽어올 Timer를 시작한다. Ubiquitous Computing
OscilloscopeC.nc 40: event message_t* Receive.receive (message_t* msg, void* payload, uint8_t len) { 41: oscilloscope_t *omsg = payload; 42: report_received(); 43: if (omsg->version > local.version) 44: { 45: local.version = omsg->version; 46: local.interval = omsg->interval; 47: startTimer(); 48: } 49: if (omsg->count > local.count) 50: { 51: local.count = omsg->count; 52: suppress_count_change = TRUE; 53: } 54: return msg; 55: } 56: event void Timer.fired() { 57: if (reading == NREADINGS) 58: { 60: If (!sendbusy && sizeof local <= call AMSend.maxPayloadLength()) 40~55: AM_OSCILLOSCOPE type을 갖는 데이터를 RF로부터 수신했을 경우 Receive.receive이벤트 함 수가 호출되며, 수신한 메시지의 Payload영역에 저 장한 oscilloscope_t 구조체의 데이터에 따라 센싱 타이머 주기와 count필드의 값을 수동으로 변경 하게 된다. 56~75: 타이머 이벤트가 발생할 때 마다 Timer.fired() 이벤트 함수가 호출된다. 이 함수에서는 oscilloscope_t 구조체의 데이터를 저장하는 readings변수에 10개의 데이터가 다 입력됐을 경우, AMSend.send함수를 통해 데이터를 전송한다. 성공 시 bool형 변수인 sendbusy에 TRUE 값을 준다. 성공 하지 못했을 경우에는 report _problem()를 호출하여 적색 LED를 토글시킨다. Ubiquitous Computing
OscilloscopeC.nc 61: { 62: memcpy(call AMSend. 61: { 62: memcpy(call AMSend. getPayload(&sendbuf), &local, sizeof local); 63: if (call AMSend.send (AM_BROADCAST_ADDR, &sendbuf, sizeof local) == SUCCESS) 64: sendbusy = TRUE; 65: } 66: if (!sendbusy) 67: report_problem(); 68: reading = 0; 69: if (!suppress_count_change) 70: local.count++; 71: suppress_count_change = FALSE; 72: } 73: if (call Read.read() != SUCCESS) 74: report_problem(); 75: } Ubiquitous Computing
OscilloscopeC.nc 76: event void AMSend.sendDone(message_t* msg, error_t error) { 77: if (error == SUCCESS) 78: report_sent(); 79: else 80: report_problem(); 81: sendbusy = FALSE; 82: } 83: event void Read.readDone(error_t result, uint16_t data) { 84: if (result != SUCCESS) 85: { 86: data = 0xffff; 87: report_problem(); 88: } 89: local.readings[reading++] = data; 90: report_received(); 91: } 92: } 76~82: 메시지 전송이 완료 되었을 경우 성공하면 report_sent() 함수를 호출하여 녹색LED를 토글시 키고, 실패 시에는 report_problem() 함수를 호출하 여 적색LED를 토글시킨다. 83~91: 데이터 전송이 완료되면 Read.readDone 이벤트 함수가 호출되고 ADC값을 local구조체의 readings 필드에 입력한다. 그런 후 report_received() 함수를 호출하여 황색 LED를 토글시킨다. Ubiquitous Computing
BaseStation BaseStation 경로 /opt/tinyos-2.x/contrib/zigbex/BaseStation/ 무선으로 받은 데이터는 시리얼로 전송 시리얼로 받은 데이터는 무선으로 전송 Ubiquitous Computing
CFLAGS += -DDEFINED_TOS_AM_GROUP=0x22 Group Id Broadcast 전송이므로 다른 조의 AM_OSCILLOSCOPE 타입의 패킷이 나의 BaseStation으로 전송 가능 Makefile에 다음 줄을 추가 후 컴파일 CFLAGS += -DDEFINED_TOS_AM_GROUP=0x22 그룹을 나눔으로써 그룹 아이디가 다를 경우 패킷이 CPU 쪽으로 올라오지 않도록 하는 방법이지만 RF채널을 변경한 것은 아니므로 충돌문제나 기타 성능향상은 되지 않음 Ubiquitous Computing
OscilloscopeUltraredRF 예제 실습 BaseStation 컴파일 및 포팅 OscilloscopeUltraredRF 컴파일 및 포팅 java program을 이용하여 데이터 확인 $ cd /opt/tinyos-2.x/contrib/zigbex/BaseStation $ make zigbex $ cd /opt/tinyos-2.x/contrib/zigbex/OscilloscopeUltraredRF $ make zigbex $ java net.tinyos.sf.SerialForwarder –comm serial@COMX:57600 & $ cd java $ make $ ./run Ubiquitous Computing
6. 기본 무선통신 프로토콜 MAC 프로토콜의 특징과 사용법을 실제 무선 송수신 예제를 통해 연습 Ubiquitous Computing
OSI 7계층 실제 서비스 구현 HTTP, SMTP, 채팅 프로그램 상호간의 접속이 이루어지도록 함 TCP, UDP 네트워크 라우팅, 흐름 제어 IP 신뢰성 있는 정보 수단 제공(에러 검출, 재전송, 충돌 회피) 연속적 비트 스트림 전송 Ubiquitous Computing
기본 지식 TinyOS의 기본 MAC 프로토콜 TinyOS에서는 무선 RF 칩 CC2420의 제어를 위해 CC2420Radio 컴포넌트를 제공하고 있으며, CC2420Radio 컴포넌트에는 TinyOS에서 사용되는 간단한 MAC 프로토콜도 함께 구현됨 앞에서 사용한 ActiveMessageC, AMSenderC, AMReceiverC 중 AMSenderC는 Queue를 가지고 CC2420ActiveMessageC 컴포넌트에게 전송할 데이터를 하나씩 처리하는 스케줄링 기능 지원 무선 MAC 형태 CSMA/CA 방식 반송파 감지 RSSI 기반의 CCA(Clear Channel Assessment : RSSI 값이 일정 threshold 값 이상이면 전송안함) 랜덤 Backoff MacBackoff 및 Random 컴포넌트 제공(데이터 전송 전에 [0,N] 숫자 중 하나를 랜덤 선택하여 그 시간만큼 기다린 후 전송) 재전송 기법 DATA/ACK 형태의 패킷 전송(DATA에 대한 ACK가 오지 않으면 충돌으로 간주하고 재전송) Carrier Sense Multiple Access/Collision Avoidance Ubiquitous Computing
BasicMAC.nc 1초마다 조도 센서로부터 측정값을 받은 후 그 내용을 RF 무선 통신을 위해 주변 노드에게 전달 Ubiquitous Computing
BasicMAC.nc configuration BasicMAC { } implementation { components MainC, BasicMACM, new TimerMilliC(), LedsC , new PhotoSensorC() as Photo, ActiveMessageC , new AMSenderC(AM_BMACMSG), new AMReceiverC(AM_BMACMSG); BasicMACM.Boot -> MainC; BasicMACM.Packet ->ActiveMessageC; BasicMACM.Timer -> TimerMilliC; BasicMACM.Leds -> LedsC; BasicMACM.Photo -> Photo; BasicMACM.CommControl -> ActiveMessageC; BasicMACM.RecvMsg -> AMReceiverC; BasicMACM.DataMsg -> AMSenderC; } Ubiquitous Computing
BasicMACM.nc BasicMACM.nc 파일 경로: 함수 실행순서 /opt/tinyos-2.x/contrib/zigbex/BasicMAC/BasicMACM.nc 함수 실행순서 Boot.booted() → SerialControl.start () SerialControl.startDone () → startTimer () startTimer () → Timer.startPeriodic () 반복 Timer.fired () → Read.read () → 조도값 측정 → Read.read Done() → AMSend.send () Ubiquitous Computing
BasicMACM.nc 1: module BasicMACM 2: { 3: uses { 4: interface Timer<TMilli>; 5: interface Leds; 6: interface Read<uint16_t> as Photo; 7: interface SplitControl as CommControl; 8: interface AMSend as DataMsg; 9: interface Receive as RecvMsg; 10: interface Packet; 11: interface Boot; 12: } 13: }implementation{ 14: struct BasicMAC_Msg *pack; 15: message_t sendmsg; 16: uint8_t recvNumber; 17: uint16_t seq_; 18: event void Boot.booted() { 19: call CommControl.start(); 20: recvNumber = 0; 21: seq_ = 0; 22: } 18: Main 컴포넌트에 의해 먼저 시작되는 Boot.booted() 함수에서는 CommControl 인터페이 스를 start하고 이 예제에서 사용할 여러 변수들을 초기화한다. Ubiquitous Computing
BasicMACM.nc 23: event void CommControl.startDone 23: RF의 초기화가 완료되면 (error_t error) { 24: call Timer.startPeriodic(1000); 25: } 26: event void CommControl.stopDone 27: } 28: event void Photo.readDone (error_t result,uint16_t data) { 29: if(result == SUCCESS){ 30: struct BasicMAC_Msg BasicMAC_M; 31: BasicMAC_M.seq = seq_++; 32: BasicMAC_M.TTL = Default_TTL; 33: BasicMAC_M.SenderID = TOS_NODE_ID; 34: BasicMAC_M.data[0] = data ; 35: memcpy(call DataMsg.getPayload( &sendmsg), (uint8_t *)&BasicMAC_M, sizeof(struct BasicMAC_Msg)); 36: call Packet.setPayloadLength(&sendmsg, 23: RF의 초기화가 완료되면 CommControl.startDone( ) 이벤트 함수가 호출되면 1초마다 주기적인 동작을 수행하도록 Timer.startPeriodic(1000) 함수를 호출한다. 28: 조도 센서값의 측정이 끝나면 Photo.readDone( ) 함수호출되고, 이 함수 내에서는 받은 조도 데이터를 BasicMAC_M 구조체 변수에 저장한다. 그리고 DataMsg.send(...) 함수를 통해 무선으로 해당 데이 터를 브로드 캐스팅(AM_BROADCAST_ADDR)한다. 하지만 AM_BROADCAST_ADDR 대신 특정 번호를 주소 필드에 기입하게 되면, 해당 번호를 아이디로 갖는 노드만 데이터를 받게 되는 유니캐스팅이 일어 난다. Ubiquitous Computing
BasicMACM.nc 37: if (call DataMsg.send(AM_BROADCAST_ADDR, &sendmsg, call Packet.payloadLength (&sendmsg)) == SUCCESS){ 38: call Leds.led2On(); //Yellow On 39: } 40: } 41: } 42: event void DataMsg.sendDone(message_t* msg, error_t error) { 43: if (error == SUCCESS){ 44: call Leds.led2Off(); //Yellow Off 45: } 46: } 47: event void Timer.fired() { 48: call Leds.led1Toggle(); //Green Toggle 49: call Photo.read(); 50: } 51: event message_t* RecvMsg.receive (message_t* msg, void* payload, uint8_t len) { 52: call Leds.led0Toggle(); //Red Toggle 53: return msg; 54: } 55: } 47: Timer에 의해 1초마다 Timer.fired()가 호출되면, Photo.read() 함수를 호출하여 ADC[0]에 있는 조도 센서값을 Photo 컴포넌트에게 요청한다. 51: 다른 노드로부터 무선 데이터를 받게 될 경우, RecvMsg.receive (...) 함수가 호출된다. 프로그래머 는 받은 데이터의 처리를 위해, RecvMsg.receive (...) 함수 내에 기술하여 수신 프로그램을 작성할 수 있다. Ubiquitous Computing
BMAC.h BMAC.h 에 정의된 데이터 포멧 #define DATA_MAX 10 struct BasicMAC_Msg { uint16_t seq; //패킷 번호 uint16_t TTL; //무한 루프를 방지하기 위한 값 (현재 예제에서는 사용 안됨) uint16_t SenderID; //소스 노드의 address uint16_t data[DATA_MAX]; //측정된 조도값 }; enum { AM_BMACMSG = 10 Ubiquitous Computing
BasicMAC 예제 실습 BasicMAC 컴파일 및 포팅 AVR Studio를 이용하여 두 개의 센서 노드에 각각 reinstall된 hex파일을 program 함. 두 개의 센서 노드의 전원을 on하게 되면 1초마다 Green LED와 Yellow LED의 빛이 깜박 거리는 것을 확인 한쪽 Yellow LED가 순간 깜박 거릴 때 (데이터를 송신한 후), 다른 쪽 노드의 Red LED (송신된 데이터를 모두 수신한 후)가 on/off를 반복함을 확인 $ cd /opt/tinyos-2.x/contrib/zigbex/BasicMAC $ make zigbex $ make zigbex reinstall.0 //0번 아이디 $ make zigbex reinstall.1 //1번 아이디 Ubiquitous Computing