500 likes | 788 Views
Ubiquitous Sensor Networks. Ubiquitous Sensor Networks. #2 : Sensors & EEPROM Control, Serial ID Read, RTC (Hanback’s zigbeX & TinyOS ver.1.1.7). 2007. 1. 30. DoHyun. Ji. Contents. 2. 3. 1. 4. EEPROM Control. Serial ID Read. Sensor Control. RTC Example. ①. CDS Sensor Control.
E N D
Ubiquitous Sensor Networks Ubiquitous Sensor Networks #2 : Sensors & EEPROM Control, Serial ID Read, RTC (Hanback’s zigbeX & TinyOS ver.1.1.7) 2007. 1. 30 DoHyun. Ji
Contents 2 3 1 4 EEPROM Control Serial ID Read Sensor Control RTC Example ① CDS Sensor Control ② SHT11 Sensor Control ③ BS520 Sensor Control / RF Transmit.
① CDS Sensor Control 1. Sensor Control • Configuration includes OscopeMsg; configuration Oscilloscope { } implementation { components Main, OscilloscopeM , TimerC , LedsC , DemoSensorC as Sensor , UARTComm as Comm; // Serial 통신을 위해 UARTComm 이용 Main.StdControl -> OscilloscopeM; Main.StdControl -> TimerC; OscilloscopeM.Timer -> TimerC.Timer[unique("Timer")]; // 타이머 OscilloscopeM.Leds -> LedsC; OscilloscopeM.SensorControl -> Sensor; OscilloscopeM.ADC -> Sensor; OscilloscopeM.CommControl -> Comm; // UARTComm 에 연결 OscilloscopeM.ResetCounterMsg -> Comm.ReceiveMsg[AM_OSCOPERESETMSG]; OscilloscopeM.DataMsg -> Comm.SendMsg[AM_OSCOPEMSG]; }
① CDS Sensor Control 1. Sensor Control • Module includes OscopeMsg; module OscilloscopeM { provides interface StdControl; uses { interface Timer; interface Leds; interface StdControl as SensorControl; // SensorControl 의 StdControl interface ADC; // ADC 센서 interface StdControl as CommControl; // CommControl 의 StdControl interface SendMsg as DataMsg; // 송신 인터페이스 interface ReceiveMsg as ResetCounterMsg; // 수신 인터페이스 } }
① CDS Sensor Control 1. Sensor Control • Module (con’d) implementation { uint8_t packetReadingNumber; // 한 패킷의 Reading 번호 uint16_t readingNumber; // 전체 패킷의 Reading 번호 TOS_Msg msg[2]; // 두개의 버퍼 선언(충돌 방지, 2개 교대로 사용) uint8_t currentMsg; // 버퍼 포인터, 버퍼의 주소 저장 command result_t StdControl.init() { call Leds.init(); // LED 초기화 call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); call SensorControl.init(); // 센서 초기화 call CommControl.init(); // UARTComm 초기화 atomic { currentMsg = 0; // 각 변수 초기화 packetReadingNumber = 0; readingNumber = 0; } dbg(DBG_BOOT, "OSCOPE initialized\n"); return SUCCESS; }
① CDS Sensor Control 1. Sensor Control • Module (con’d) command result_t StdControl.start() { call SensorControl.start(); // 센싱 시작 call Timer.start(TIMER_REPEAT, 125);// 125ms 마다 타이머 이벤트 call CommControl.start(); // 통신 시작 return SUCCESS; } command result_t StdControl.stop() { call SensorControl.stop(); // 센싱 정지 call Timer.stop(); // 타이머 정지 call CommControl.stop(); // 통신 정지 return SUCCESS; } event result_t Timer.fired() { return call ADC.getData(); // 타이머 만료시 센싱정보 읽어와 dataReady() 호출함 }
① CDS Sensor Control 1. Sensor Control • Module (con’d) async event result_t ADC.dataReady(uint16_t data) { struct OscopeMsg *pack; // OscopeMsg 구조체를 포인팅하는 변수 atomic { pack = (struct OscopeMsg *)msg[currentMsg].data; // 읽어낸 센싱데이터를 OscopeMsg 로 전송 가능하도록 형변환 pack->data[packetReadingNumber++] = data; // 현재 읽어온 데이터를 구조체의 데이터배열에 저장 readingNumber++; // 패킷번호 카운팅 dbg(DBG_USR1, "data_event\n"); if (packetReadingNumber == BUFFER_SIZE) { post dataTask(); // 버퍼가 가득차면 전송, 버퍼크기는 10 } } if (data > 0x0300) // 768 보다 값이 크면 call Leds.redOn(); // 빨간 LED 켜기 else // 작으면 call Leds.redOff(); // 빨간 LED 끄기 return SUCCESS; }
① CDS Sensor Control 1. Sensor Control • Module (con’d) task void dataTask() { struct OscopeMsg *pack; // OscopeMsg 구조체를 포인팅하는 변수 atomic { pack = (struct OscopeMsg *)msg[currentMsg].data; // 읽어낸 센싱데이터를 OscopeMsg 로 전송 가능하도록 형변환 packetReadingNumber = 0; // 패킷 카운팅 초기화 pack->lastSampleNumber = readingNumber; // 최종 샘플링한 패킷번호 기록 } pack->channel = 1; // 채널 pack->sourceMoteID = TOS_LOCAL_ADDRESS; // 현재 모트의 ID if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg), &msg[currentMsg])) // UARTComm 으로 메시지 전송 { atomic { currentMsg ^= 0x1; // XOR 로 버퍼 변경(1->0, 0->1), 교대로 버퍼 사용 } call Leds.yellowToggle(); // 노란led 상태변경 } } struct OscopeMsg { uint16_t sourceMoteID; uint16_t lastSampleNumber; uint16_t channel; uint16_t data[BUFFER_SIZE]; };
① CDS Sensor Control 1. Sensor Control • Module (con’d) // 메시지의 송신이 완료되면 발생하는 이벤트 event result_t DataMsg.sendDone(TOS_MsgPtr sent, result_t success) { return SUCCESS; } // 오실로스코프에서 Reset 메시지를 보내면 발생하는 이벤트 event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m) { atomic { readingNumber = 0; // 패킷 번호를 처음부터 다시 매긴다. } return m; }
② SHT11 Sensor Control 1. Sensor Control • Configuration includes OscopeMsg; configuration Oscilloscope { } implementation { components Main, OscilloscopeM , TimerC , LedsC , HumidityC as SHT11 , UARTComm as Comm; // SHT11, Serial 통신 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; // SplitControl : 한백전자 ZigbeX 에 탑재된 SHT11 센서용 인터페이스 OscilloscopeM.CommControl -> Comm; // Serial 통신 인터페이스 OscilloscopeM.ResetCounterMsg -> Comm.ReceiveMsg[AM_OSCOPERESETMSG]; // 패킷 카운터 리셋 인터페이스 OscilloscopeM.DataMsg -> Comm.SendMsg[AM_OSCOPEMSG]; // 메시지 전송 인터페이스 }
② SHT11 Sensor Control 1. Sensor Control • Module includes OscopeMsg; module OscilloscopeM { provides interface StdControl; uses { interface Timer; interface Leds; interface StdControl as SensorControl; // SensorControl 의 StdControl interface ADC as SHT11_Humidity; // ADC 인터페이스의 rename interface ADC as SHT11_Temp; // ADC 인터페이스의 rename interface ADCError as SHT11_Humidity_Error; interface ADCError as SHT11_Temp_Error; // 인터페이스 rename interface StdControl as CommControl; // 인터페이스 rename interface SendMsg as DataMsg; interface ReceiveMsg as ResetCounterMsg; interface SplitControl; // SHT11 제어용 인터페이스 } }
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) implementation { uint8_t TemppacketReadingNumber; // 단일온도패킷 카운팅 변수 uint8_t HumipacketReadingNumber; // 단일습도패킷 카운팅 변수 uint16_t TempreadingNumber; // 전체온도패킷 카운팅 변수 uint16_t HumireadingNumber; // 전체습도패킷 카운팅변수 TOS_Msg tempmsg[2]; TOS_Msg humimsg[2]; // 각 메시지별 버퍼 uint8_t currentTempMsg; uint8_t currentHumiMsg; // 현재 버퍼의 주소 저장(0 or 1) uint16_t timetick; // 시간 uint8_t mytemp, myhumi; void calc_SHT11(uint16_t p_humidity ,uint16_t p_temperature);
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) command result_t StdControl.init() { call Leds.init(); // LED 초기화 call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); //call SensorControl.init(); //zigbex 에서 사용하는 센서 종류가 달라서 주석처리 call CommControl.init(); // Serial 통신 초기화 call SplitControl.init(); // SHT11 센서 초기화 atomic { currentTempMsg = 0; // 각 변수들의 초기화 currentHumiMsg = 0; TemppacketReadingNumber = 0; HumipacketReadingNumber = 0; TempreadingNumber = 0; HumireadingNumber = 0; } dbg(DBG_BOOT, "OSCOPE initialized\n"); return SUCCESS; }
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) command result_t StdControl.start() { //call SensorControl.start(); //zigbex 에서 사용하는 센서 종류가 달라서 주석처리 call Timer.start(TIMER_REPEAT, 125); // 125ms 마다 타이머 이벤트 call CommControl.start(); // UartComm 통신 시작 call SplitControl.start(); // SHT11 센싱 시작 return SUCCESS; } command result_t StdControl.stop() { //call SensorControl.stop(); call Timer.stop(); // 타이머 정지 call CommControl.stop(); // 통신 정지 call SplitControl.stop(); // 센싱 정지 return SUCCESS; } event result_t Timer.fired() { timetick++; // 시간 카운팅. 왜하는지....? //return call SHT11_Temp.getData(); return call SHT11_Humidity.getData(); // 습도 데이터 가져오기, SHT11_Humidity.dataReady() 호출 }
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) async event result_t SHT11_Humidity.dataReady(uint16_t data) { // SHT11_Humidity.getData() 에 의해 호출 struct OscopeMsg *pack; // OscopeMsg 구조체 포인팅 변수 atomic { pack = (struct OscopeMsg *)humimsg[currentTempMsg].data; // 읽어낸 센싱데이터를 OscopeMsg 로 전송 가능하도록 형변환 calc_SHT11(data,data); // 데이터 변환(c, %rh) pack->data[HumipacketReadingNumber++] = myhumi; // 변환된 데이터를 전송할 구조체 값에 저장 HumireadingNumber++; // 패킷번호 카운팅 dbg(DBG_USR1, "data_event\n"); if (HumipacketReadingNumber == BUFFER_SIZE) { post dataTaskHumi(); // 버퍼가 가득차면 전송 } } if (data > 0x0300) // 값이 0x300 이상일때 call Leds.redOn(); // 빨간 LED 켜기 else call Leds.redOff(); return SUCCESS; }
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) task void dataTaskHumi() { struct OscopeMsg *pack; // OscopeMsg 구조체를 포인팅하는 변수 atomic { pack = (struct OscopeMsg *)humimsg[currentHumiMsg].data;// 읽어낸 센싱데이터를 OscopeMsg 로 전송 가능하도록 형변환 HumipacketReadingNumber = 0; // 습도패킷 카운팅 초기화 pack->lastSampleNumber = HumireadingNumber;// 최종 샘플링한 습도패킷번호 기록 } pack->channel = 2; // 채널 2 로 설정(온도와의 충돌 방지) pack->sourceMoteID = TOS_LOCAL_ADDRESS; // 현재 모트의 ID if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct OscopeMsg), &humimsg[currentHumiMsg]))// UARTComm 으로 메시지 전송 { atomic { currentHumiMsg ^= 0x1; // XOR 로 버퍼 변경(1->0, 0->1), 교대로 버퍼 사용 } call Leds.yellowToggle(); // 노란led 상태변경 } }
② SHT11 Sensor Control 1. Sensor Control • Module (con’d) task void dataTaskTemp() { …….. } // SplitControl 인터페이스에 의해 필요한 함수들, 반드시 기술해줘야 함 event result_t DataMsg.sendDone(TOS_MsgPtr sent, result_t success) { return SUCCESS; } event result_t SplitControl.initDone() { return SUCCESS; } event result_t SplitControl.startDone() { return SUCCESS; } event result_t SplitControl.stopDone() { return SUCCESS; } event result_t SHT11_Humidity_Error.error(uint8_t token) { return SUCCESS; } event result_t SHT11_Temp_Error.error(uint8_t token) { return SUCCESS; } event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m) { atomic { // PC의 오실로스코프에서 리셋 신호 전달시 TempreadingNumber = 0; // 카운팅 번호 초기화 HumireadingNumber = 0; } return m; } void calc_SHT11(uint16_t p_humidity ,uint16_t p_temperature){ ………… }
③ BS520 Sensor Control / RF Transmit. 1. Sensor Control • Configuration includes OscopeMsg; configuration Oscilloscope { } implementation { components Main, OscilloscopeM , TimerC, LedsC , Ultrared as Sensor , GenericComm as Comm; // BS520 센서, RF 통신 컴포넌트 Main.StdControl -> OscilloscopeM; Main.StdControl -> TimerC; OscilloscopeM.Timer -> TimerC.Timer[unique("Timer")]; // 타이머 OscilloscopeM.Leds -> LedsC; OscilloscopeM.SensorControl -> Sensor; // 센서 인터페이스 OscilloscopeM.ADC -> Sensor; // ADC OscilloscopeM.CommControl -> Comm; // RF 통신 OscilloscopeM.ResetCounterMsg -> Comm.ReceiveMsg[AM_OSCOPERESETMSG]; // 패킷 카운터 리셋 인터페이스 OscilloscopeM.DataMsg -> Comm.SendMsg[AM_OSCOPEMSG]; // 메시지 전송 인터페이스 }
③ BS520 Sensor Control / RF Transmit. 1. Sensor Control • Module includes OscopeMsg; module OscilloscopeM { ……..// 인터페이스 선언부 } } implementation { ………… // 선언부 command result_t StdControl.init() { ………… } command result_t StdControl.start() { ………… } command result_t StdControl.stop() { ………… } event result_t Timer.fired() { return call ADC.getData(); // 타이머 만료시 센싱정보 읽어와 dataReady() 호출함 } async event result_t ADC.dataReady(uint16_t data) { …………… }
③ BS520 Sensor Control / RF Transmit. 1. Sensor Control • Module (con’d) task void dataTask() { struct OscopeMsg *pack; // OscopeMsg 구조체를 포인팅하는 변수 atomic { pack = (struct OscopeMsg *)msg[currentMsg].data; // 읽어낸 센싱데이터를 OscopeMsg 로 전송 가능하도록 형변환 packetReadingNumber = 0; // 패킷 카운팅 초기화 pack->lastSampleNumber = readingNumber; // 최종 샘플링한 패킷번호 기록 } pack->channel = 1; // 채널 번호 설정 pack->sourceMoteID = TOS_LOCAL_ADDRESS; // 현재 모트의 ID if (call DataMsg.send(TOS_BCAST_ADDR, sizeof(struct OscopeMsg), &msg[currentMsg])) // Broadcast 모드로 RF 메시지 전송 { atomic { currentMsg ^= 0x1; // XOR 로 버퍼 변경(1->0, 0->1), 교대로 버퍼 사용 } call Leds.yellowToggle(); // 노란led 상태변경 } }
③ BS520 Sensor Control / RF Transmit. 1. Sensor Control • Module (con’d) event result_t DataMsg.sendDone(TOS_MsgPtr sent, result_t success) { return SUCCESS; // 사용하지 않지만 메시지의 송신이 완료되면 발생하는 이벤트로서 필요함 } event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m) { atomic { readingNumber = 0; // 패킷 번호를 처음부터 다시 매긴다. } return m; }
1. Sensor Control • Sensing Test
EEPROM의 주소 제어용 레지스터 EEPROM의 데이터 제어용 레지스터 2. EEPROM Control • EEPROM • ATmega128 에 내장, 매개변수 저장용도로 사용 • ATmega128 내부의 레지스터를 이용하여 제어, 4KB 의 용량을 가짐
EEPROM 컨트롤 레지스터 2. EEPROM Control • EEPROM (con’d) • 데이터 저장 순서 • ①. EEARH/EEARL 에 저장할 주소 설정 (Max 4096byte) • ②. EEDR 에 저장할 데이터 기록(8bit = 1byte) • ③. EECR 의 EEMWE(EEPROM Master Write Enable) 비트를 1로 Set • ④. EECR 의 EEWE(EEPROM Write Enable) 비트를 1로 Set • 레지스터 이름 • EEARH/EEARL : EEPROM Address Register High/Low • EEDR : EEPROM Data Register • EECE : EEPROM Control Register • EERIE : EEPROM Ready Interrupt Enable • EEMWE, EEWE, EERE(EEPROM Read Enable)
2. EEPROM Control • Interface • Configuration interface EEProm { // EEPROM 제어에 필요한 인터페이스 async command uint8_t read( uint8_t location); // read async command void write(uint16_t location, uint8_t data); // write async command void ram2eeprom( uint8_t *dst, uint8_t *src, uint8_t length); // ram to rom async command void eeprom2ram( uint8_t *dst, uint8_t *src, uint8_t length); // rom to ram } configuration EEPromC{ provides interface EEProm as EEp; } implementation { components Main, ZigbeXInterruptC, EEPromM, LedsC; Main.StdControl -> EEPromM.StdControl; // EEPROM 제어 인터페이스 EEPromM.Leds -> LedsC; // LED 제어 인터페이스 EEPromM.eeRomReady -> ZigbeXInterruptC.eeRomReady; //ZigbeXInterrupt; EEp = EEPromM; // EEProm 인터페이스와 EEPromM 의 상호 와이어링 }
2. EEPROM Control • Module module EEPromM { provides { interface StdControl; interface EEProm; // 현재 모듈에서 제공 } uses { interface ZigbeXInterrupt as eeRomReady; // Zigbex 의 인터페이스 사용 interface Leds; } } implementation { task void rom_temp_compare(); // task preprocessing uint8_t rom[13]="parkyounggyu"; // 저장할 롬 데이터 문자열 uint8_t temp[13]; // 임시 문자열 변수 command result_t StdControl.init() { call Leds.init(); // LED 초기화 call Leds.redOff(); call Leds.greenOff(); call Leds.yellowOff(); call eeRomReady.enable(); // Zigbex Interrupt 초기화, EEPROM 관련 인터럽트 Enable return SUCCESS; }
2. EEPROM Control • Module (con’d) command result_t StdControl.start() { call EEProm.ram2eeprom((uint8_t)0x0,rom, 13); // EEPROM 에 13바이트 기록하기 call EEProm.eeprom2ram(temp,0x0,13); // EEPROM 에서 13바이트 가져오기 post rom_temp_compare(); // 초기 문자열과, 기록된 문자열 비교 return SUCCESS; } command result_t StdControl.stop() { call eeRomReady.disable(); // EEPROM 인터럽트 Disable return SUCCESS; } async command void EEProm.ram2eeprom(uint8_t *dst, uint8_t *src, uint8_t length) { // EEPROM 에 데이터를 저장하는 함수 while(length--) { while (EECR & 0x02); // EECR 값이 변경될때까지 기다림, 0x02 => EEWE EEAR = (uint16_t)dst++; // 저장할 초기 주소 설정 EEDR = *src++; // EEDR에 1byte의 데이터 기록 EECR |= 0x04; // Set EEMWE EECR |= 0x02; // Set EEWE } }
2. EEPROM Control • Module (con’d) async command void EEProm.eeprom2ram( uint8_t *dst, uint8_t *src, uint8_t length) { // EEPROM 에 저장된 데이터를 가져오는 함수 atomic { int n=0; while(length--) { while (EECR & 0x02); // EEWE 가 Set 될때까지 기다림 EEAR = (uint16_t)src++; // 읽어올 주소의 설정 EECR |= 0x01; // Set EERE dst[n++] = EEDR; // EEDR 의 데이터 가져옴 } } } async event void eeRomReady.fired() { // EEPROM 에 Write 동작이 한번씩 일어날때마다 이벤트 발생 static uint8_t data1=0; // 첫 이벤트에는 0으로 설정 if(data1 == 0) { // 기록 시작시 call Leds.redOn(); // 빨간 LED 켜기 } else if(data1 == 13) { // 기록 완료시 call Leds.greenOn(); // 초록 LED 켜기 } data1++; }
2. EEPROM Control • Module (con’d) task void rom_temp_compare() { int i; for (i=0 ; i<13 ; i++) { if ( rom[i] != temp[i]) // 코드오류;; return; // 두 문자열의 값이 다르면 return } call Leds.yellowOn(); // 문자열이 같으면 노란 LED 켜기 } async command uint8_t EEProm.read( uint8_t location) { …………. } async command void EEProm.write(uint16_t location, uint8_t data) { …………. }
3. Serial ID Read • DS-2401 to ATmega128 Protocol • Initialization
3. Serial ID Read • DS-2401 to ATmega128 Protocol (con’d) • Write-One, Write-zero
3. Serial ID Read • DS-2401 to ATmega128 Protocol (con’d) • Read-data
3. Serial ID Read • Configuration configuration Ds2410P{ } implementation{ components Main, Ds2410PM, LedsC, GenericComm as Comm, TimerC; Main.StdControl -> Ds2410PM; // DS2410 컴포넌트에 연결 Main.StdControl -> TimerC; // Timer Ds2410PM.CommControl->Comm; // RF Comm Ds2410PM.Send->Comm.SendMsg[11]; Ds2410PM.Timer -> TimerC.Timer[unique("Timer")]; Ds2410PM.Leds -> LedsC; // LED 컴포넌트 연결 } 3. Serial ID Read
3. Serial ID Read • Module module Ds2410PM { provides { interface StdControl; } uses { interface Timer; interface Leds; interface StdControl as CommControl; // RF Comm interface SendMsg as Send; // 송신 인터페이스 } } 3. Serial ID Read
3. Serial ID Read • Module (con’d) implementation { TOS_Msg msg_buf; // 전송 메시지 버퍼 TOS_MsgPtr msg; // 버퍼 포인터 bool gfReadBusy; // 플래그 uint8_t serialId[8]; // 시리얼 ID 저장 배열 int A,B,C,D,E,F,G,H,I,J; void serialIdByteWrite(uint8_t data); // 함수 preprocessing bool serialIdRead(); #define SERIAL_ID_LOW() TOSH_MAKE_SERIAL_ID_OUTPUT(); TOSH_CLR_SERIAL_ID_PIN(); #define SERIAL_ID_OPEN() TOSH_SET_SERIAL_ID_PIN(); TOSH_MAKE_SERIAL_ID_INPUT(); #define SERIAL_ID_READ() TOSH_READ_SERIAL_ID_PIN() void tickDelay(int tick){ TOSH_uwait(tick); }; // Implementation is platform specific void SetSpeed(int standard) { …………. }
3. Serial ID Read • Module (con’d) int OWTouchReset() { // One-Wire 초기화 int result; TOSH_CLR_SERIAL_ID_PIN(); // DDRA CLR, 핀을 Low 로 SERIAL_ID_LOW(); // DDRA SET, PORTA CLR => LOW 유지 tickDelay(H); // 480us 유지, T_RSTL SERIAL_ID_OPEN(); // DDRA CLR, PORTA SET tickDelay(I); // 70us 유지, T_PDL result = (SERIAL_ID_READ() & 0x01); // 샘플링, 펄스값을 읽어서 저장(0 or 1) tickDelay(J); // 410us 유지, reset sequence 를 마무리지음 return result; // 읽어낸 핀 값 리턴 }
3. Serial ID Read • Module (con’d) void OWWriteBit(int bit) { if (bit) { // Write '1' bit :: Write-One SERIAL_ID_LOW(); // Drives DQ low , LOW 로 셋 tickDelay(A); // 6us 유지, T_LOW1 SERIAL_ID_OPEN(); // HIGH tickDelay(B); // 64us 유지, T_SLOT + T_REC(recovery) } else { // Write '0' bit :: Write-zero SERIAL_ID_LOW(); // Drives DQ low, LOW 로 셋 tickDelay(C); // 60us 유지, T_LOW0 SERIAL_ID_OPEN(); // Releases the bus => HIGH 로 셋 tickDelay(D); // 10us 유지, T_REC } }
3. Serial ID Read • Module (con’d) int OWReadBit() { int result; SERIAL_ID_LOW(); // Drives DQ low, LOW 로 셋 tickDelay(A); // 6us 유지, T_LOWR SERIAL_ID_OPEN(); // Releases the bus => HIGH 로 셋 tickDelay(E); // 9us 유지, T_RDV - T-LOWR :: A + E = T_RDV result = (SERIAL_ID_READ() & 0x01); // 읽어낸 비트 샘플링 tickDelay(F); // 55us 유지, 10us 의 recovery 시간 포함, T_SLOT 채우기, 60us < T_SLOT 120us return result; } uint8_t serialIdByteRead() { // 한 바이트의 시리얼ID 읽어오기 uint8_t loop, result=0; for (loop = 0; loop < 8; loop++) { result >>= 1; if (OWReadBit()) result |= 0x80; // 값이 존재하면 MSB = 1 // MSB 에 기록후 logical right shift 반복하여 값을 가져옴. } return result; }
3. Serial ID Read • Module (con’d) void serialIdByteWrite(uint8_t data) { uint8_t loop; for (loop = 0; loop < 8; loop++) { OWWriteBit(data & 0x01); // LSB 기록 data >>= 1; // LSB 에 기록후 logical right shift 반복하여 값을 기록 } } command result_t StdControl.init() { TOSH_MAKE_SERIAL_ID_INPUT(); // 포트 초기화 [ DDRA CLR ] …………… msg = &msg_buf; // 메시지 버퍼로 포인터 세팅 SetSpeed(1); // 표준 클럭으로 설정 return SUCCESS; } command result_t StdControl.start() { TOSH_SET_SERIAL_ID_PIN(); // pullup 레지스터 활성화, HIGH 로 셋 call CommControl.start(); // 통신 시작 call Timer.start(TIMER_REPEAT, 2000); // 2000ms 마다 타이머 작동 return SUCCESS; }
3. Serial ID Read • Module (con’d) • event result_t Timer.fired() { • call Leds.redToggle(); // 빨간 LED 상태 변경 • serialIdRead(); // 시리얼 ID 읽어오기 • return SUCCESS; • } • bool serialIdRead() { • uint8_t* sdata = (uint8_t*)(msg_buf.data); // 버퍼와 시리얼 ID 데이터가 같은 주소를 가지도록 설정 • if (OWTouchReset()) // 통신 버스 리셋 (MASTER RESET PULSE) • return FALSE; // 디바이스가 없으면, 즉 버스가 없으면 FALSE 리턴, 정상적으로 리셋이 된 경우 0 이 돌아와야 함. • call Leds.greenOn(); // 초록이 켜기 • serialIdByteWrite(0x33); // 0x33 펄스 전송, READ ROM • call Leds.yellowOn(); // 노랭이 켜기 • for(cnt = 0; cnt < 8; cnt ++){ • serialId[cnt] = serialIdByteRead(); // 한바이트씩 읽어서 배열에 저장: 8*8, 48bit • tickDelay(10); // 10 tick 딜레이 걸어주기 • } • sdata[0] = serialId[0]; sdata[1] = serialId[1]; sdata[2] = serialId[2]; sdata[3] = serialId[3]; • sdata[4] = serialId[4]; sdata[5] = serialId[5]; sdata[6] = serialId[6]; sdata[7] = serialId[7]; sdata[8] = 0x99; • call Send.send(TOS_BCAST_ADDR, 9, msg); // RF 전송 • return TRUE; • }
4. RTC Example • RTC4513 Registers • 각 주소는 4개의 비트로 구성, 4비트씩 BCD 코드로 구성됨 • READ, WRITE 시 LSB 부터 처리함
4. RTC Example • RTC Headers /* HBE_RTC.h */ #define Register_S1 0x00 #define Register_S10 0x10 #define Register_Ml1 0x20 #define Register_Ml10 0x30 #define Register_H1 0x40 #define Register_H10 0x50 #define Register_D1 0x60 #define Register_D10 0x70 #define Register_MO1 0x80 #define Register_MO10 0x90 #define Register_Y1 0xA0 #define Register_Y10 0xB0 #define Register_W 0xC0 #define Register_CD 0xD0 #define Register_CE 0xE0 #define Register_CF 0xF0 …………………. /* rtc4513Msg.h */ enum { BUFFER_SIZE = 20 }; struct rtcMsg { uint16_t sourceMoteID; uint16_t lastSampleNumber; uint8_t data[BUFFER_SIZE]; }; struct rtcResetMsg { /* Empty payload! */ };
4. RTC Example • Configuration includes rtc4513Msg; configuration rtc4513test { } implementation { components Main, rtc4513testM // 모듈 추가 , TimerC // 타이머 , LedsC // LED , HBE_RTCC // HBE_RTC 컴포넌트 로드 , UARTComm as Comm; // Serial 통신 Main.StdControl -> rtc4513testM; Main.StdControl -> TimerC; rtc4513testM.Timer -> TimerC.Timer[unique("Timer")]; // 타이머 rtc4513testM.Leds -> LedsC; rtc4513testM.rtcControl -> HBE_RTCC; // 인터페이스 연결 rtc4513testM.HBE_RTC -> HBE_RTCC; rtc4513testM.CommControl -> Comm; rtc4513testM.ResetCounterMsg -> Comm.ReceiveMsg[AM_RTC4513RESET]; rtc4513testM.DataMsg -> Comm.SendMsg[AM_RTC4513]; }
4. RTC Example • Module includes rtc4513Msg; includes HBE_RTC; #define Register_S1 0x00 #define Register_S10 0x10 #define Register_Ml1 0x20 ………….. module rtc4513testM { provides interface StdControl; uses { interface Timer; interface Leds; interface StdControl as rtcControl; interface HBE_RTC; interface StdControl as CommControl; interface SendMsg as DataMsg; interface ReceiveMsg as ResetCounterMsg; } }
4. RTC Example • Module (con’d) implementation { uint8_t packetReadingNumber; // 한 패킷의 Reading 번호 uint16_t readingNumber; // 전체 패킷의 Reading 번호 TOS_Msg msg[2]; // 두개의 버퍼 선언(충돌 방지, 2개 교대로 사용) uint8_t currentMsg; // 버퍼 포인터, 버퍼의 주소 저장 void dataTask(); command result_t StdControl.init() { call Leds.init(); // LED 초기화 call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); call rtcControl.init(); // RTC 컴포넌트 초기화 call CommControl.init(); // UARTComm 초기화 atomic { currentMsg = 0; // 각 변수 초기화 packetReadingNumber = 0; readingNumber = 0; } call HBE_RTC.RTC_setdate(2007-1970,1,30,5); // 2007년 1월 30일 5주 call HBE_RTC.RTC_settime(15,20,13); // 오후 3시 20분 13초 return SUCCESS; }
4. RTC Example • Module (con’d) command result_t StdControl.start() { call rtcControl.start(); // RTC 제어 시작 call Timer.start(TIMER_REPEAT, 500); // 500ms 마다 타이머 작동 call CommControl.start(); // UARTComm 시작 return SUCCESS; } command result_t StdControl.stop() { call rtcControl.stop(); // 각 컴포넌트 정지 call Timer.stop(); call CommControl.stop(); return SUCCESS; } event result_t Timer.fired() { readingNumber++; // 패킷번호 카운팅 dataTask(); // RTC 값 가져오기 return SUCCESS; }
4. RTC Example • Module (con’d) void dataTask() { struct rtcMsg *pack; // rtcMsg 구조체를 포인팅하는 변수 uint8_t datetime; // RTC 정보를 읽어올 임시변수 atomic { pack = (struct rtcMsg *)msg[currentMsg].data;// 버퍼 데이터를 rtcMsg 에 맞도록 형변환 packetReadingNumber = 0; // 패킷 카운팅 초기화 pack->lastSampleNumber = readingNumber; // 최종 샘플링한 패킷번호 기록 } pack->sourceMoteID = TOS_LOCAL_ADDRESS; // 현재 모트의 ID pack->data[0]=1; pack->data[1]=9; datetime = call HBE_RTC.RTC_getbyte(Register_Y10); // 10-year 읽어오기 datetime+=7; if (datetime >= 10){ datetime=0; pack->data[1]++; if(pack->data[1]>=10){ pack->data[1]=0; pack->data[0]++; } }
4. RTC Example • Module (con’d) pack->data[2] = datetime; datetime = call HBE_RTC.RTC_getbyte(Register_Y1); // 1-year 읽어오기 pack->data[3]=datetime; pack->data[4]='/'; datetime = call HBE_RTC.RTC_getbyte(Register_MO10); // 10-month 읽어오기 pack->data[5]=datetime; datetime = call HBE_RTC.RTC_getbyte(Register_MO1); // 1-month 읽어오기 pack->data[6]=datetime; pack->data[7]='/'; …………………. datetime = call HBE_RTC.RTC_getbyte(Register_S10); // 10-second 읽어오기 pack->data[17]=datetime; datetime = call HBE_RTC.RTC_getbyte(Register_S1); // 1-second 읽어오기 pack->data[18]=datetime; pack->data[19]='\r'; if (call DataMsg.send(TOS_UART_ADDR, sizeof(struct rtcMsg), &msg[currentMsg])) // Serial 전송 { atomic { currentMsg ^= 0x1; } // XOR 로 버퍼 변경(1->0, 0->1), 교대로 버퍼 사용 call Leds.yellowToggle(); // 노란led 상태변경 }
4. RTC Example • Result 02:수요일, 07:2007년, 01: 1월, 03 00: 30일, 01 05: 15시, 0301: 31분, 00 07: 7초