होममेड डिवाइसेस के साथ एक बाहरी Buro H999 वायरलेस थर्मामीटर का उपयोग करना

बाहरी वायरलेस थर्मामीटर H999 के साथ मौसम स्टेशन Buro H146G में हर कोई अच्छा है। लेकिन सिर्फ उसके फीके एलसीडी पर रीडिंग देखने के लिए अच्छी रोशनी की जरूरत होती है। और यह मेरे लिए बेहतर होगा यदि खिड़की के बाहर तापमान और आर्द्रता का उत्पादन पर्याप्त रूप से उज्ज्वल संकेतकों (उदाहरण के लिए, आईएन -12 गैस-डिस्चार्ज संकेतकों पर घड़ी के साथ तापमान और आर्द्रता प्रदर्शन के संयोजन) पर प्रदर्शित किया गया था। इस तरह के एक शिल्प को बनाना मुश्किल नहीं है, लेकिन आपको वायरलेस थर्मामीटर के साथ विनिमय के प्रोटोकॉल को जानने की आवश्यकता है। हवा पर तापमान और आर्द्रता प्राप्त करने के लिए वायरलेस मौसम स्टेशन थर्मामीटर के उपयोग के बारे में पहले से ही लेख हैं। लेकिन Buro स्टेशनों के लिए, एक्सचेंज प्रोटोकॉल अभी तक वर्णित नहीं किया गया है। तो, हमें इसे ठीक करने की आवश्यकता है: शायद कोई काम आ सकता है।

इंटरनेट पर, मुझे BURO स्टेशनों के आदान-प्रदान के लिए प्रोटोकॉल का विवरण नहीं मिला। और इसका मतलब है कि आपको इस वायरलेस सेंसर के आदान-प्रदान के प्रोटोकॉल को खोलना होगा।

मेरा बाहरी थर्मामीटर इस तरह दिखता है:



एक चीनी सुपर-पुनर्योजी 433.92 मेगाहर्ट्ज रिसीवर को आस्टसीलस्कप से जोड़कर और थर्मामीटर पर टेस्ट बटन दबाकर, यह स्पष्ट रूप से दिखाई दे रहा था कि ट्रांसमिशन दाल कैसे चल रही थी। खैर, चूंकि आवृत्ति छोटा है, रिसीवर का आउटपुट एक प्रतिरोधक विभक्त के माध्यम से साउंड कार्ड के इनपुट से जुड़ा था। रिकॉर्ड की गई ध्वनि फ़ाइल को संसाधित करने के बाद, तुलनित्र ने निम्नलिखित तस्वीर निकाली:



अन्य मौसम केंद्रों की तरह, ड्यूटी चक्र को बदलकर मॉड्यूलेशन किया जाता है। प्रसारण घड़ी ब्लॉक से शुरू होता है, फिर एक और घड़ी संकेत होता है, और फिर डेटा होता है, जिसके बाद अंतिम घड़ी संकेत जाता है। घड़ी संकेत के बाद दो शून्य, जाहिरा तौर पर, डेटा की शुरुआत के पहचानकर्ता हैं - किसी भी मामले में, मैंने कभी भी उनके बदलाव पर ध्यान नहीं दिया है। एक शुरुआत और अंत घड़ी के साथ डेटा को छह बार दोहराया जाता है। डेटा एक्सचेंज nibbles द्वारा किया जाता है।

डिकोडिंग के लिए, मैंने पहली घड़ी और दो शून्य पर प्राप्त करना शुरू किया, और आखिरी घड़ी पर समाप्त करने का फैसला किया।

इस तरह के सिग्नल को डिकोड करने के लिए, सिग्नल ड्रॉप्स के बीच की अवधि की गणना करना पर्याप्त है।

इसके लिए, मैंने Atmega8 नियंत्रक के लिए एक सरल परीक्षण कार्यक्रम लिखा:

Atmega8 के लिए कार्यक्रम
//---------------------------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------------------------- #include <avr/io.h> #include <util/delay.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #include <stdio.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <string.h> #include <stdbool.h> #include <stdint.h> //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- #define F_CPU 8000000UL //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //   UART, / #define UART_SPEED 9600UL //---------------------------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------------------------- //  enum BLOCK_TYPE { BLOCK_TYPE_UNKNOW,//  BLOCK_TYPE_DIVIDER,// BLOCK_TYPE_SYNCHRO,// BLOCK_TYPE_ONE,// BLOCK_TYPE_ZERO// }; //  enum MODE { MODE_WAIT_SYNCHRO,//  MODE_WAIT_ZERO_FIRST,//   MODE_WAIT_ZERO_SECOND,//   MODE_RECEIVE_DATA//  }; //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- static const uint16_t MAX_TIMER_INTERVAL_VALUE=0xFFFF;//    static volatile bool TimerOverflow=false;//    static uint8_t Buffer[20];//   static uint8_t BitSize=0;//   static uint8_t Byte=0;//  //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void InitAVR(void);//  void UART_Write(unsigned char byte);//   COM- void SendText(const char *text);//   COM- void RF_Init(void);// void RF_SetTimerOverflow(void);//    void RF_ResetTimerOverflow(void);//    bool RF_IsTimerOverflow(void);//,     uint16_t RF_GetTimerValue(void);//   void RF_ResetTimerValue(void);//   BLOCK_TYPE RF_GetBlockType(uint32_t counter,bool value);//   void RF_AddBit(bool state);//   void RF_ResetData(void);//    void RF_AnalizeCounter(uint32_t counter,bool value,MODE &mode);//  //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- int main(void) { InitAVR(); _delay_ms(200); SendText("Thermo unit\r\n"); _delay_ms(200); sei(); while(1); cli(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void InitAVR(void) { //  DDRB=0; DDRD=0; DDRC=0; //   PORTB=0; PORTD=0; PORTC=0; //    UART UCSRB=(1<<RXEN)|(1<<TXEN)|(0<<RXCIE); //RXCIE=1    ( I=1   SREG) :      UART  //TXCIE=1    ( I=1   SREG) :      UART  //UDRIE=1    ( I=1   SREG) :      UART  //RXEN=1 :  ,  D0   UART. //TXEN=1 :  ,  D1   UART. //CHR9=1 :       11  (9   + -  + -). //RXB8- - //TXB8- - //      unsigned long speed=F_CPU/(16UL); speed=(speed/UART_SPEED)-1UL; UBRRH=(speed>>8)&0xff; UBRRL=speed&0xFF; RF_Init(); } //---------------------------------------------------------------------------------------------------- //   COM- //---------------------------------------------------------------------------------------------------- void UART_Write(unsigned char byte) { while(!(UCSRA&(1<<UDRE))); UDR=byte; } //---------------------------------------------------------------------------------------------------- //   COM- //---------------------------------------------------------------------------------------------------- void SendText(const char *text) { while((*text)) { UART_Write(*text); text++; } } //---------------------------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------------------------- void RF_Init(void) { //   ACSR=(0<<ACD)|(1<<ACBG)|(0<<ACO)|(0<<ACI)|(1<<ACIE)|(0<<ACIC)|(0<<ACIS1)|(0<<ACIS0); //ACD -   (0 - !) //ACBG -       ' //ACO -   ( ) //ACI -     //ACIE -     //ACIC -       T1 //ACIS1,ACID0 -      //  T1   31250  TCCR1A=(0<<WGM11)|(0<<WGM10)|(0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0); //COM1A1-COM1A0 -   OC1A //COM1B1-COM1B0 -   OC1B //WGM11-WGM10 -    TCCR1B=(0<<WGM13)|(0<<WGM12)|(1<<CS12)|(0<<CS11)|(0<<CS10)|(0<<ICES1)|(0<<ICNC1); //WGM13-WGM12 -    //CS12-CS10 -    (      256 (  31250 )) //ICNC1 -       //ICES1 -      TCNT1=0;//   TIMSK|=(1<<TOIE1);//    ( T1 ) } //---------------------------------------------------------------------------------------------------- //    //---------------------------------------------------------------------------------------------------- void RF_SetTimerOverflow(void) { cli(); TimerOverflow=true; sei(); } //---------------------------------------------------------------------------------------------------- //    //---------------------------------------------------------------------------------------------------- void RF_ResetTimerOverflow(void) { cli(); TimerOverflow=false; sei(); } //---------------------------------------------------------------------------------------------------- //,     //---------------------------------------------------------------------------------------------------- bool RF_IsTimerOverflow(void) { cli(); bool ret=TimerOverflow; sei(); return(ret); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- uint16_t RF_GetTimerValue(void) { cli(); uint16_t ret=TCNT1; sei(); return(ret); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void RF_ResetTimerValue(void) { cli(); TCNT1=0; sei(); RF_ResetTimerOverflow(); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- BLOCK_TYPE RF_GetBlockType(uint32_t counter,bool value) { static const uint32_t DIVIDER_MIN=(31250UL*12)/44100UL; static const uint32_t DIVIDER_MAX=(31250UL*25)/44100UL; static const uint32_t ZERO_MIN=(31250UL*80)/44100UL; static const uint32_t ZERO_MAX=(31250UL*100)/44100UL; static const uint32_t ONE_MIN=(31250UL*160)/44100UL; static const uint32_t ONE_MAX=(31250UL*200)/44100UL; static const uint32_t SYNCHRO_MIN=(31250UL*320)/44100UL; static const uint32_t SYNCHRO_MAX=(31250UL*400)/44100UL; if (counter>DIVIDER_MIN && counter<DIVIDER_MAX) return(BLOCK_TYPE_DIVIDER);// if (counter>ZERO_MIN && counter<ZERO_MAX) return(BLOCK_TYPE_ZERO);// if (counter>ONE_MIN && counter<ONE_MAX) return(BLOCK_TYPE_ONE);// if (counter>SYNCHRO_MIN && counter<SYNCHRO_MAX) return(BLOCK_TYPE_SYNCHRO);// return(BLOCK_TYPE_UNKNOW);//  } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void RF_AddBit(bool state) { if ((BitSize>>2)>=19) return;//  Byte<<=1; if (state==true) Byte|=1; BitSize++; if ((BitSize&0x03)==0) { Buffer[(BitSize>>2)-1]=Byte; Byte=0; } } //---------------------------------------------------------------------------------------------------- //    //---------------------------------------------------------------------------------------------------- void RF_ResetData(void) { BitSize=0; Byte=0; } //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void RF_AnalizeCounter(uint32_t counter,bool value,MODE &mode) { //   BLOCK_TYPE type=RF_GetBlockType(counter,value); if (type==BLOCK_TYPE_UNKNOW) { mode=MODE_WAIT_SYNCHRO; RF_ResetData(); return; } if (type==BLOCK_TYPE_DIVIDER) return;//    //      if (mode==MODE_WAIT_SYNCHRO)//  { if (type==BLOCK_TYPE_SYNCHRO) { mode=MODE_WAIT_ZERO_FIRST; return; } mode=MODE_WAIT_SYNCHRO; RF_ResetData(); return; } if (mode==MODE_WAIT_ZERO_FIRST || mode==MODE_WAIT_ZERO_SECOND)//   { if (type==BLOCK_TYPE_SYNCHRO && mode==MODE_WAIT_ZERO_FIRST) return;//  if (type==BLOCK_TYPE_ZERO && mode==MODE_WAIT_ZERO_FIRST) { mode=MODE_WAIT_ZERO_SECOND; return; } if (type==BLOCK_TYPE_ZERO && mode==MODE_WAIT_ZERO_SECOND) { mode=MODE_RECEIVE_DATA; return; } mode=MODE_WAIT_SYNCHRO; RF_ResetData(); return; } //  if (type==BLOCK_TYPE_SYNCHRO)//  { uint8_t size=(BitSize>>2); char str[30]; if (size!=10) { mode=MODE_WAIT_SYNCHRO; RF_ResetData(); return; } //  for(uint8_t n=0;n<size;n++) { uint8_t b=Buffer[n]; uint8_t mask=(1<<3); for(uint8_t m=0;m<4;m++,mask>>=1) { if (b&mask) SendText("1"); else SendText("0"); } SendText(" "); } uint8_t channel=Buffer[2]&0x03; uint8_t key=(Buffer[8]>>3)&0x01; uint8_t h=(Buffer[7]<<4)|(Buffer[6]);// int16_t temp=(Buffer[5]<<8)|(Buffer[4]<<4)|(Buffer[3]);// int16_t k=18; int16_t t=(10*(temp-1220))/k; sprintf(str,"%i",key); SendText("Key:"); SendText(str); sprintf(str,"%i",channel+1); SendText(" Ch:"); SendText(str); sprintf(str,"%i",h); SendText(" H:"); SendText(str); SendText("%, T:"); if (t<0) { t=-t; sprintf(str,"-%i.%i",(int)(t/10),(int)(t%10)); } else { sprintf(str,"%i.%i",(int)(t/10),(int)(t%10)); } SendText(str); SendText(" C\r\n"); mode=MODE_WAIT_SYNCHRO; RF_ResetData(); return; } //  if (type==BLOCK_TYPE_ONE) { RF_AddBit(true); return; } if (type==BLOCK_TYPE_ZERO) { RF_AddBit(false); return; } mode=MODE_WAIT_SYNCHRO; RF_ResetData(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //---------------------------------------------------------------------------------------------------- //    T1 (16-  )   //---------------------------------------------------------------------------------------------------- ISR(TIMER1_OVF_vect) { RF_SetTimerOverflow(); } //---------------------------------------------------------------------------------------------------- //     //---------------------------------------------------------------------------------------------------- ISR(ANA_COMP_vect) { ACSR&=0xFF^(1<<ACIE);//  ACSR|=(1<<ACI);//    static MODE mode=MODE_WAIT_SYNCHRO; //   uint16_t length=RF_GetTimerValue(); if (RF_IsTimerOverflow()==true) length=MAX_TIMER_INTERVAL_VALUE;// ,    RF_ResetTimerValue(); //   bool value=true; if (ACSR&(1<<ACO)) value=false; RF_AnalizeCounter(length,value,mode); ACSR|=(1<<ACIE);//  } 


रिसीवर आउटपुट पिन 13 (एआईएन 1) से जुड़ा है। Atmega अधिकतम 232 कंप्यूटर के COM पोर्ट (या USB-COM एडाप्टर) के माध्यम से जोड़ता है। पोर्ट स्पीड 9600 बॉड।

डीकोडिंग के बाद, हमें निम्नलिखित डेटा स्ट्रीम मिलती है (मैं दो प्रमुख शून्य को बाहर निकालता हूं):

// बिना बटन, चैनल 1
1100 1100 0000 1110 1000 0110 1100 0001 0000 1001 आर्द्रता: 28% तापमान: 25.4
// कोई बटन नहीं, चैनल 2
1100 1100 0001 1110 1000 0110 1101 0001 0000 0110 आर्द्रता: 29% तापमान: 25.4

कुल पैकेज इस तरह दिखता है:



I0-I7 - थर्मामीटर की पहचानकर्ता। हर बार जब थर्मामीटर चालू होता है, तो पहचानकर्ता बदल जाता है।

C0-C1 - चैनल (कुल 3 संभावित हैं)। चैनल खरोंच से गिने जाते हैं।

H0-H7 - आर्द्रता। प्रतिशत के रूप में आर्द्रता के रूप में पढ़ा जाता है, लेकिन तापमान (T0-T11) किसी कारण से मौसम स्टेशनों के लिए एक असामान्य प्रारूप में निर्धारित होता है। विभिन्न मौसम केंद्रों के विनिमय प्रोटोकॉल के विवरणों को देखते हुए, जो मैंने पाया, एक डिग्री के दसवें हिस्से में तापमान और थर्मामीटर की निचली सीमा में एक बदलाव के साथ उम्मीद करेंगे। तो, नहीं। प्रयोगों से पता चला कि इस मौसम स्टेशन का तापमान कोड डिग्री सेल्सियस (T-1220) / 18 में बदल जाता है। इन मैजिक नंबरों को कैसे जानते हैं केवल चीनी जो इस एक्सचेंज प्रोटोकॉल के साथ आए थे।

जैसा कि टिप्पणियों में सुझाए गए वौल्वोअर में, स्टेशन एक डिग्री फ़ारेनहाइट के दसवें हिस्से में तापमान को स्थानांतरित करता है, इसलिए डिग्री सेल्सियस में एक सार्थक अनुवाद 0.1 * (T-320) * 5 / 9-500 = 0.1 * (T-1220) / 1.8 होगा।

बिट K, TEST बटन दबाने से मेल खाती है।

शेष क्षेत्रों का असाइनमेंट स्थापित नहीं किया जा सका, लेकिन यह पता चला कि थर्मामीटर पर फ़ारेनहाइट / सेल्सियस स्विच का मूल्य विनिमय प्रोटोकॉल में नहीं मिलता है। संभवतया अंतिम कुतरना (या शायद एक हिस्सा) भी सीआरसी है, लेकिन मैं अभी तक एल्गोरिथ्म की गणना करने में सक्षम नहीं हूं (इसमें संदेह है कि कुतरने वाली पंक्तियां और स्तंभ गणना में शामिल हैं)। यदि कोई इस पहेली को हल कर सकता है, तो कृपया हमें गणना एल्गोरिथ्म बताएं।
उन लोगों के लिए जो अपने दिमाग को रैक करना चाहते हैं, लेकिन ऐसा थर्मामीटर नहीं है, मैं स्वीकृत आंकड़ों की एक तालिका देता हूं।

तालिका
 1001 0110 0101 1011 1000 0110 1000 0010 0001 1111 Key:0 Ch:2 H:40%, T:25.2 C 1001 1001 0000 1101 1010 0100 0101 0101 0000 0110 Key:0 Ch:1 H:85%, T:-1.2 C 1001 0110 0101 1100 1000 0110 1010 0010 0001 0100 Key:0 Ch:2 H:42%, T:25.3 C 1001 0110 1001 0110 0111 0110 1101 0001 0010 1111 Key:0 Ch:2 H:29%, T:24.1 C 1001 0110 1001 0000 0111 0110 1101 0001 0010 1000 Key:0 Ch:2 H:29%, T:23.7 C 1001 0110 1001 0010 0101 0110 1110 0001 0010 1111 Key:0 Ch:2 H:30%, T:22.1 C 1001 0110 1001 1001 0011 0110 1110 0001 0010 1100 Key:0 Ch:2 H:30%, T:20.7 C 1001 0110 1001 1111 0001 0110 1111 0001 0010 1010 Key:0 Ch:2 H:31%, T:19.2 C 1001 0110 0101 1001 0000 0110 0001 0010 0010 1000 Key:0 Ch:2 H:33%, T:18.0 C 1001 0110 0101 0010 1111 0101 0010 0010 0010 0111 Key:0 Ch:2 H:34%, T:16.7 C 1001 0110 0101 0100 1110 0101 0010 0010 0010 0010 Key:0 Ch:2 H:34%, T:16.0 C 1001 0110 0101 0100 1101 0101 0011 0010 0010 0001 Key:0 Ch:2 H:35%, T:15.1 C 1001 0110 0101 1100 1100 0101 0100 0010 0010 1110 Key:0 Ch:2 H:36%, T:14.6 C 1001 0110 0101 1111 1011 0101 0101 0010 0010 1111 Key:0 Ch:2 H:37%, T:13.9 C 1001 0110 0101 0011 1011 0101 0101 0010 0010 0001 Key:0 Ch:2 H:37%, T:13.2 C 1001 0110 0101 1001 1010 0101 0110 0010 0010 0101 Key:0 Ch:2 H:38%, T:12.7 C 1001 0110 0101 0100 1010 0101 0111 0010 0010 1000 Key:0 Ch:2 H:39%, T:12.4 C 1001 0110 0101 1011 1001 0101 0111 0010 0010 1010 Key:0 Ch:2 H:39%, T:11.9 C 1001 0110 0101 0011 1001 0101 1000 0010 0010 1001 Key:0 Ch:2 H:40%, T:11.5 C 1001 0110 0101 1011 1000 0101 1000 0010 0010 1110 Key:0 Ch:2 H:40%, T:11.0 C 1001 0110 0101 0111 1000 0101 1001 0010 0010 0101 Key:0 Ch:2 H:41%, T:10.8 C 1001 0110 0101 1111 0111 0101 1001 0010 0010 1101 Key:0 Ch:2 H:41%, T:10.3 C 1001 0110 0101 0111 0111 0101 1010 0010 0010 0111 Key:0 Ch:2 H:42%, T:9.9 C 1001 0110 0101 0001 0111 0101 1011 0010 0010 0101 Key:0 Ch:2 H:43%, T:9.6 C 1001 0110 0101 1011 0110 0101 1100 0010 0010 0110 Key:0 Ch:2 H:44%, T:9.2 C 1001 0110 0101 1000 0110 0101 1100 0010 0010 1100 Key:0 Ch:2 H:44%, T:9.1 C 1001 0110 0101 0011 0110 0101 1101 0010 0010 0110 Key:0 Ch:2 H:45%, T:8.8 C 1001 0110 0101 1001 0101 0101 1110 0010 0010 0110 Key:0 Ch:2 H:46%, T:8.2 C 1001 0110 0101 0101 0101 0101 1111 0010 0010 1101 Key:0 Ch:2 H:47%, T:8.0 C 1001 0110 0101 0010 0101 0101 1111 0010 0010 1100 Key:0 Ch:2 H:47%, T:7.8 C 1001 0110 0101 1110 0100 0101 1111 0010 0010 0000 Key:0 Ch:2 H:47%, T:7.6 C 1001 0110 0101 1100 0100 0101 1111 0010 0010 1100 Key:0 Ch:2 H:47%, T:7.5 C 

Source: https://habr.com/ru/post/hi432704/


All Articles