Menggunakan Termometer Nirkabel Buro H999 Eksternal dengan Perangkat Buatan Rumah

Semua orang jago di stasiun cuaca Buro H146G dengan termometer nirkabel eksternal H999. Tetapi hanya untuk melihat pembacaan pada LCD pudarnya membutuhkan pencahayaan yang baik. Dan akan lebih baik bagi saya jika suhu dan kelembaban output di luar jendela ditampilkan pada indikator yang cukup cerah (misalnya, menggabungkan tampilan suhu dan kelembaban dengan jam pada indikator debit gas IN-12). Tidak sulit untuk membuat kerajinan seperti itu, tetapi Anda harus mengetahui protokol pertukaran dengan termometer nirkabel. Sudah ada artikel tentang penggunaan termometer stasiun cuaca nirkabel untuk mendapatkan suhu dan kelembaban di udara. Tetapi untuk stasiun Buro, protokol pertukaran belum dijelaskan. Jadi, kita perlu memperbaikinya: mungkin seseorang bisa berguna.

Di Internet, saya tidak menemukan deskripsi protokol untuk bertukar stasiun BURO. Dan ini berarti Anda harus membuka protokol pertukaran sensor nirkabel ini.

Termometer eksternal saya terlihat seperti ini:



Dengan menghubungkan receiver 433,92 MHz super-regeneratif Tiongkok ke osiloskop dan menekan tombol TEST pada termometer, terlihat jelas bagaimana pulsa transmisi bekerja. Nah, karena frekuensinya kecil, output penerima terhubung ke input kartu suara melalui pembagi resistif. Setelah memproses file suara yang direkam, pembanding menghasilkan gambar berikut:



Seperti stasiun cuaca lainnya, modulasi dilakukan dengan mengubah siklus tugas. Transmisi dimulai dari blok jam, kemudian ada sinyal jam lain, dan kemudian ada data, setelah itu sinyal jam terakhir berjalan. Dua nol setelah sinyal jam, tampaknya, adalah pengidentifikasi awal data - dalam hal apa pun, saya tidak pernah memperhatikan perubahannya. Data dengan jam mulai dan berakhir digandakan enam kali. Pertukaran data dilakukan oleh camilan.

Untuk decoding, saya memutuskan untuk mulai menerima pada jam pertama dan dua nol, dan selesai pada jam terakhir.

Untuk memecahkan kode sinyal seperti itu, cukup untuk menghitung durasi antara penurunan sinyal.

Untuk ini, saya menulis program pengujian sederhana untuk pengontrol Atmega8:

Program untuk 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);//  } 


Output penerima terhubung ke pin 13 (AIN1). Atmega terhubung melalui max232 ke port COM komputer (atau ke adaptor USB-COM). Kecepatan port 9600 baud.

Setelah decoding, kita mendapatkan aliran data berikut (saya membuang dua nol terkemuka):

// tanpa tombol, saluran 1
1100 1100 0000 1110 1000 0110 1100 0001 0000 1001 Kelembaban: 28% Suhu: 25,4
// tidak ada tombol, saluran 2
1100 1100 0001 1110 1000 0110 1101 0001 0000 0110 Kelembaban: 29% Suhu: 25,4

Total paket terlihat seperti ini:



I0-I7 - pengidentifikasi termometer. Setiap kali termometer dihidupkan, pengenal berubah.

C0-C1 - saluran (ada 3 kemungkinan total). Saluran diberi nomor dari awal.

H0-H7 - kelembaban. Kelembaban sebagai persentase dibaca apa adanya, tetapi suhu (T0-T11) karena alasan tertentu diatur dalam format yang tidak biasa untuk stasiun cuaca. Dilihat oleh deskripsi protokol pertukaran berbagai stasiun cuaca yang saya temukan, orang akan mengharapkan suhu dalam sepersepuluh derajat dan dengan pergeseran batas bawah termometer. Jadi tidak. Percobaan menunjukkan bahwa kode suhu stasiun cuaca ini diterjemahkan ke derajat Celcius sebagai (T-1220) / 18. Bagaimana angka ajaib ini hanya tahu orang Cina yang datang dengan protokol pertukaran ini.

Seperti yang disarankan oleh wolowizard dalam komentar, stasiun mentransfer suhu dalam sepersepuluh derajat Fahrenheit, sehingga terjemahan yang bermakna dalam derajat Celcius akan menjadi 0,1 * (T-320) * 5 / 9-500 = 0,1 * (T-1220) /1,8.

Bit K berhubungan dengan menekan tombol TEST.

Penugasan bidang yang tersisa tidak dapat ditetapkan, tetapi ternyata nilai sakelar Fahrenheit / Celsius pada termometer tidak masuk ke protokol pertukaran. Agaknya gigitan terakhir (atau mungkin bagian dari yang kedua dari belakang) juga CRC, tapi saya belum dapat menghitung algoritme (ada kecurigaan bahwa baris dan kolom yang menggigit terlibat dalam perhitungan). Jika ada yang bisa memecahkan teka-teki ini, beri tahu kami algoritma penghitungan.
Bagi mereka yang ingin memeras otak mereka, tetapi tidak memiliki termometer seperti itu, saya memberikan tabel data yang diterima.

Meja
 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/id432704/


All Articles