diff --git a/Oregon_NR.cpp b/Oregon_NR.cpp index 52ca4c5..0c77029 100644 --- a/Oregon_NR.cpp +++ b/Oregon_NR.cpp @@ -1,7 +1,7 @@ #include "Oregon_NR.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// This Arduino code is for receive and transmit data using Oregon Scientific RF protocol version 2.1 and 3.0. +// This Arduino code is for receive and transmit data using Oregon Scientific RF protocol version 2.1 and 3.0. // // Last updated: 14 October 2019 // @@ -10,11 +10,12 @@ // Receive and transmit: // THGN132N (THGR122N, THGN123N), // RTGN318, +// RTGN130, // THGR810. // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -24,7 +25,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2019 Sergey Zawislak +// Copyright (c) 2019 Sergey Zawislak // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -33,76 +34,77 @@ // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Oregon Scientific v2.1 v3.0 +// Данная библиотека Ардуино предназначена для приема и передачи данных в формате беспроводного протокола Oregon Scientific v2.1 и v3.0 // -// 14 2019 +// Последнее обновление 14 Октября 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, +// RTGN130, // THGR810. -// : +// Тольок приём: // THN132N, -// WGR800, +// WGR800, // UVN800. // -// ( ) +// Также поддерживаются датчики собственной разработки (за дополнительной документацей обращаться к автору) // -// - OREGON_NR +// Этот файл - часть библиотеки OREGON_NR ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2019 +// Copyright (c) 2019 Сергей Зависляк // -// , -// ( ), , -// , , , , , , -// / , , , : +// Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации +// (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, +// включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование +// и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: // -// . +// Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. // -// ܻ, - , , -// , , . -// - , , , , , -// - . +// ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ +// ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ +// НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, +// ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//, ///////////////////////////////////// +//Всё, что относится к прерыванию///////////////////////////////////// #ifndef Oregon_NR_int #define Oregon_NR_int static volatile unsigned long pm; -static volatile unsigned long pl, timer_mark; +static volatile unsigned long pl, timer_mark; #if defined ( ESP8266 ) -void ICACHE_RAM_ATTR receiver_interruption(void) { +void ICACHE_RAM_ATTR receiver_interruption(void) { #elif defined ( ESP32 ) -void ICACHE_RAM_ATTR receiver_interruption(void) { +void ICACHE_RAM_ATTR receiver_interruption(void) { #else -void receiver_interruption(void) { +void receiver_interruption(void) { #endif if(digitalRead(RECEIVER_PIN)){ - // + //Начало импульса pl = 0; - pm = micros(); + pm = micros(); } else{ - // - // - pl = micros() - pm; + //Конец импульса + //Вычисляется время окончания и длина + pl = micros() - pm; //pm += pl; } //yield(); -} +} #endif ////////////////////////////////////////////////////////////////////// @@ -110,7 +112,7 @@ Oregon_NR::Oregon_NR(byte MHZ, byte MHZ_INT) { INT_NO = MHZ_INT; RECEIVER_PIN = MHZ; - pinMode(MHZ, INPUT); // , + pinMode(MHZ, INPUT); // Вывод, на который подключён приёмник } Oregon_NR::Oregon_NR(byte MHZ, byte MHZ_INT, byte led, bool pull_up) @@ -119,8 +121,8 @@ Oregon_NR::Oregon_NR(byte MHZ, byte MHZ_INT, byte led, bool pull_up) LED = led; PULL_UP = pull_up; RECEIVER_PIN = MHZ; - pinMode(MHZ, INPUT); // , - pinMode(LED, OUTPUT); // + pinMode(MHZ, INPUT); // Вывод, на который подключён приёмник + pinMode(LED, OUTPUT); // Вывод светодиода } ////////////////////////////////////////////////////////////////////// @@ -131,21 +133,21 @@ void Oregon_NR::start() start_pulse_cnt = 0; receive_status = FIND_PACKET; led_light(false); - attachInterrupt(INT_NO, receiver_interruption, CHANGE); + attachInterrupt(INT_NO, receiver_interruption, CHANGE); } ////////////////////////////////////////////////////////////////////// void Oregon_NR::stop() { - detachInterrupt(INT_NO); + detachInterrupt(INT_NO); } ////////////////////////////////////////////////////////////////////// -// -//DEBUG_INFO - Serial +//Захват и анализ пакета +//DEBUG_INFO - в Serial выводится информация о захвате данных ////////////////////////////////////////////////////////////////////// void Oregon_NR::capture(bool DEBUG_INFO) { //////////////////////////////////////////////////////// - // + // Возвращаемся к исходному состоянию //maybe_packet = 0; packets_received = 0; sens_type = 0; @@ -154,9 +156,9 @@ void Oregon_NR::capture(bool DEBUG_INFO) data_val = 0; data_val2 = 0; - + //////////////////////////////////////////////////////// - // + //Чтение данных с приёмника noInterrupts(); pulse_length = pl; pl = 0; @@ -164,15 +166,15 @@ void Oregon_NR::capture(bool DEBUG_INFO) interrupts(); //////////////////////////////////////////////////////// - // - if (pulse_length != 0 && receive_status == FIND_PACKET){ - // , + //Пришёл импульс + if (pulse_length != 0 && receive_status == FIND_PACKET){ + //Если импульс пришёл слишком поздно для конкретной версии протокола, то это первый импульс if (pulse_marker - pre_marker > (PER_LENGTH2 * 2 + LENGTH_TOLERANCE) && ver == 2) start_pulse_cnt = 0; if (pulse_marker - pre_marker > (PER_LENGTH3 * 2 + LENGTH_TOLERANCE) && ver == 3) start_pulse_cnt = 0; if (start_pulse_cnt == 0){ //////////////////////////////////////////////////////// - // "" - + //Найдена первый "правильный" импульс - определяем тип протокола if (pulse_length < (MAX_LENGTH2 + LENGTH_TOLERANCE) && pulse_length > (MIN_LENGTH2 - LENGTH_TOLERANCE) && catch2 ) { start_pulse_cnt++; pre_marker = pulse_marker; @@ -189,10 +191,10 @@ void Oregon_NR::capture(bool DEBUG_INFO) } else{ /////////////////////////////////////////////////////////// - // "" + //Найдена следующий "правильный" импульс if (pulse_length <= (MAX_LENGTH2 + LENGTH_TOLERANCE) && pulse_length >= (MIN_LENGTH2 - LENGTH_TOLERANCE) && catch2) { /////////////////////////////////////////////////////////// - // , + //Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов if(pulse_marker - pre_marker > (PER_LENGTH2*2-LENGTH_TOLERANCE) && pulse_marker - pre_marker < (PER_LENGTH2 * 2 + LENGTH_TOLERANCE) && ver == 2) { start_pulse_cnt++; @@ -200,8 +202,8 @@ void Oregon_NR::capture(bool DEBUG_INFO) pulse_length = 0; } /////////////////////////////////////////////////////////// - // - // + //Следующий импульс находится в неправильном месте + //Назначаем его первым else { start_pulse_cnt = 1; @@ -213,7 +215,7 @@ void Oregon_NR::capture(bool DEBUG_INFO) if (pulse_length <= (MAX_LENGTH3 + LENGTH_TOLERANCE) && pulse_length >= (MIN_LENGTH3 - LENGTH_TOLERANCE) && catch3) { /////////////////////////////////////////////////////////// - // , + //Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов if(pulse_marker - pre_marker > (PER_LENGTH3*2-LENGTH_TOLERANCE) && pulse_marker - pre_marker < (PER_LENGTH3 * 2 + LENGTH_TOLERANCE) && ver == 3) { start_pulse_cnt++; @@ -221,8 +223,8 @@ void Oregon_NR::capture(bool DEBUG_INFO) pulse_length = 0; } /////////////////////////////////////////////////////////// - // - // + //Следующий импульс находится в неправильном месте + //Назначаем его первым else { start_pulse_cnt = 1; @@ -235,18 +237,18 @@ void Oregon_NR::capture(bool DEBUG_INFO) } //************************************************************************************* ///////////////////////////////////////////////////////////////////// - // - // , - // + // Если найден первый пакет и вышло вермя ожидания второго + // Не ждём второго, а переходм в режим анализа + // тАКЖЕ не ждём второго пакета если отключён режим сращивания пакетов if (packet_number == 1 && (millis() - first_packet_end) > 200) receive_status = ANALIZE_PACKETS; if (packet_number == 1 && (!IS_ASSEMBLE || ver == 3 )) receive_status = ANALIZE_PACKETS; - + ////////////////////////////////////////////////////////////////////// - // , . + //Если Найдено нужное количество правильных импульсов в нужных местах, то возможно это пакет. Начинаем СБОР ДАННЫХ if (start_pulse_cnt == CATCH_PULSES && receive_status == FIND_PACKET) { - + start_pulse_cnt = 0; if (packet_number == 0) @@ -263,27 +265,27 @@ void Oregon_NR::capture(bool DEBUG_INFO) } } ////////////////////////////////////////////////////////////////////// - // //////////////////////////////////////////////////////// - if (receive_status == ANALIZE_PACKETS) { + // Анализ данных//////////////////////////////////////////////////////// + if (receive_status == ANALIZE_PACKETS) { ////////////////////////////////////////////////////////////////////// - // , - if ((ver ==2 && read_tacts < 136 && read_tacts2 < 136) || (ver ==3 && read_tacts < 80)) + //Если пришёл тольок кусок посылки, то не стоит и обрабатывать + if ((ver ==2 && read_tacts < 136 && read_tacts2 < 136) || (ver ==3 && read_tacts < 80)) { receive_status = FIND_PACKET; - start_pulse_cnt = 0; + start_pulse_cnt = 0; packet_number = 0; return; } - // , + //Отключаем прерывание, чтобы сократить время обработки detachInterrupt(INT_NO); - + led_light(true); restore_sign = 0; - work_time = millis(); // - // - // - // v2 - 87 07 86 06, .. 883 395 - // v3 - 86 06 87 07 .. 838 350 + work_time = millis(); //Расчёт времени обработки пакета + //Дамп собранных данных + //ДЛя посылки без помех значения имурльсов олжны быть примерно + // v2 - 87 07 и изредка 86 06, т.к. длина импульса 883мс и 395мс + // v3 - 86 06 и изредка 87 07 т.к. длина импульса 838 и 350мс if (DEBUG_INFO && receiver_dump){ Serial.println(" "); Serial.print("SCOPE1 "); @@ -308,8 +310,8 @@ void Oregon_NR::capture(bool DEBUG_INFO) ////////////////////////////////////////////// - // - // . decode_tacts[] + //Обработка первой записи + //Расшифровываем запись. Данные сохраянем в decode_tacts[] get_tacts(collect_data, read_tacts); bool halfshift; @@ -322,10 +324,10 @@ void Oregon_NR::capture(bool DEBUG_INFO) halfshift = 1; } ////////////////////////////////////////////// - // + //Ищем позицию синхронибла synchro_pos = get_synchro_pos(collect_data); ////////////////////////////////////////////// - // + //Выводим посылку if (DEBUG_INFO){ if (packet_number == 2) Serial.print("1) "); if (packet_number == 1) Serial.print("RESULT "); @@ -351,7 +353,7 @@ void Oregon_NR::capture(bool DEBUG_INFO) Serial.println (millis() / 1000); } ////////////////////////////////////////////// - // + //Аналогично обрабатываем вторую запись if (packet_number == 2){ get_tacts(collect_data2, read_tacts2); @@ -391,16 +393,16 @@ void Oregon_NR::capture(bool DEBUG_INFO) } byte* result_data, result_data_start, aux_data; int correlation; - + ////////////////////////////////////////////// - // - // , - if (packet_number == 1) result_data = collect_data; + //СОПОСТАВЛЕНИЕ ПАКЕТОВ + //Если пакет один, то и сопоставлять не из чего + if (packet_number == 1) result_data = collect_data; ////////////////////////////////////////////// - // , - // "" + //А вот если два, то нужна СБОРКА ПАКЕТА + //вычисляем оптимальное "смещение" пакетов друг относительно друга if (packet_number == 2) { correlation = correlate_data(collect_data, collect_data2); if (DEBUG_INFO){ @@ -408,7 +410,7 @@ void Oregon_NR::capture(bool DEBUG_INFO) Serial.println(correlation); } ////////////////////////////////////////////// - // , + //Собираем данные в пакет, где синхронибл найден раньше ////////////////////////////////////////////// if (synchro_pos >= synchro_pos2) @@ -426,7 +428,7 @@ void Oregon_NR::capture(bool DEBUG_INFO) } } ////////////////////////////////////////////// - // + //Вывод готовой посылки if (DEBUG_INFO && packet_number == 2){ Serial.print("RESULT "); byte* rdt = result_data; @@ -448,31 +450,31 @@ void Oregon_NR::capture(bool DEBUG_INFO) - //, - - . , + //Проверяем, дало ли что-нибудь сращивание - отключил. Это даёт всего лишь флаг, но занимает много времени ////////////////////////////////////////////// // if (get_data(halfshift, ver, result_data) > data_val && get_data(halfshift, ver, result_data) > data_val2 && ver == 2) // restore_sign ^= 8; ////////////////////////////////////////////// - // + //Извлекаем из тактовой последовательности биты sens_type = 0; if (get_info_data(result_data, packet, valid_p)) { - sens_type = get_sensor(packet); // - restore_data(packet, sens_type); // - crc_c = check_CRC(packet, sens_type); // CRC, , - // , , + sens_type = get_sensor(packet); //Определяем тип пакета по типу датчика + restore_data(packet, sens_type); // Восстанавливаем данные по типу датчика + crc_c = check_CRC(packet, sens_type); // Проверяем CRC, если оно верно, то все сомнительные биты делаем уверенными + //Если не все байты определены уверенно, нельзя считать, что пакет корректный byte secresingV; if (sens_type == THGN132 || (sens_type & 0xFF00) == GAS) secresingV = PACKET_LENGTH - 4; if (sens_type == THN132) secresingV = PACKET_LENGTH - 6; for (byte www = 0; www < (PACKET_LENGTH - secresingV + 2); www++) if (valid_p[www] < 0x0f) crc_c = false; - // , ( ) - // - + //Захват пакета происходит тольок в случае, если найдена стартовая последовательность (нибл синхронизации) + //Если не было синхрониблов - то не о чем вообще разговаривать if ( synchro_pos != 255 && packet_number == 1) captured = 1; if ( (synchro_pos2 != 255 || synchro_pos2 != 255) && packet_number == 2) captured = 1; - // + //Захват куска посылки не считается if ((ver ==2 && read_tacts < 136) || (ver ==3 && read_tacts < 80)) captured = 0; } // else if (data_val >=64 || data_val2 >=64) maybe_packet = 1; @@ -502,17 +504,17 @@ void Oregon_NR::capture(bool DEBUG_INFO) sens_max_ws = 0; sens_wdir = 0; -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - if ((sens_type == THGN132 || sens_type == THN132 || (sens_type & 0x0FFF)== RTGN318 || sens_type == THGR810) && crc_c){ +//////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка датчиков Орегон +//////////////////////////////////////////////////////////////////////////////////////////////////// + if ((sens_type == THGN132 || sens_type == THN132 || (sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810) && crc_c){ sens_id = get_id(packet); sens_chnl = get_channel(packet); sens_battery = get_battery(packet); sens_tmp = get_temperature(packet); - if (sens_type == THGN132 || (sens_type & 0x0FFF)== RTGN318 || sens_type == THGR810) - sens_hmdty = get_humidity(packet); + if (sens_type == THGN132 || (sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810) + sens_hmdty = get_humidity(packet); else sens_hmdty = 0; } @@ -522,7 +524,7 @@ void Oregon_NR::capture(bool DEBUG_INFO) sens_avg_ws = get_avg_windspeed(packet); sens_max_ws = get_max_windspeed(packet); sens_wdir = get_winddirection(packet); - } + } if (sens_type == UVN800 && crc_c){ sens_id = get_id(packet); @@ -535,9 +537,9 @@ void Oregon_NR::capture(bool DEBUG_INFO) #if ADD_SENS_SUPPORT == 1 -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка комплексных газовых датчиков +//////////////////////////////////////////////////////////////////////////////////////////////////// if ((sens_type & 0xFF00) == GAS && crc_c){ sens_id = 0; sens_battery = 0; @@ -550,21 +552,21 @@ void Oregon_NR::capture(bool DEBUG_INFO) sens_CO = get_gas_CO(packet); sens_CH = get_gas_CH(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка датчиков пожарной сигнализации +//////////////////////////////////////////////////////////////////////////////////////////////////// if ((sens_type & 0xFF00) == FIRE && crc_c){ sens_id = 0; sens_battery = 0; - + sens_chnl = get_gas_channel(packet); sens_ip22 = get_fire_ip22(packet); sens_ip72 = get_fire_ip72(packet); sens_lockalarm = get_fire_lockalarm(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// THP -//////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка датчиков THP +//////////////////////////////////////////////////////////////////////////////////////////////////// if ((sens_type & 0xFF00) == THP && crc_c){ sens_chnl = get_gas_channel(packet); sens_voltage = get_thp_voltage(packet); @@ -573,99 +575,99 @@ void Oregon_NR::capture(bool DEBUG_INFO) sens_pressure = get_thp_pressure(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка датчиков тока и напряжения +//////////////////////////////////////////////////////////////////////////////////////////////////// if ((sens_type & 0xFF00) == CURRENT && crc_c){ sens_id = 0; sens_battery = 0; - + sens_chnl = get_gas_channel(packet); sens_current = get_current(packet); sens_voltage = get_voltage(packet); sens_pump_count = get_pump_count(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// +//Расшифровка датчиков осадков емкостного типа +//////////////////////////////////////////////////////////////////////////////////////////////////// if ((sens_type & 0xFF00) == CAPRAIN && crc_c){ sens_id = 0; sens_battery = 0; - - //sens_heater = + + //sens_heater = sens_drop_counter = get_dropcounter(packet); sens_capacitance = get_capacitance(packet); } - + #endif //////////////////////////////////////////////////////////////////////////////// -// -// +//Остальные вычисления +//Возвращаем всё в исходное состояние и включаем прослушивание приёмника work_time = millis() - work_time; packets_received = 0; if (data_val >= 64 && synchro_pos != 255) packets_received++; if (data_val2 >= 64 && synchro_pos2 != 255) packets_received++; receive_status = FIND_PACKET; - start_pulse_cnt = 0; + start_pulse_cnt = 0; packet_number = 0; led_light(false); //Serial.print("LED = "); //Serial.println(LED); - attachInterrupt(INT_NO, receiver_interruption, CHANGE); + attachInterrupt(INT_NO, receiver_interruption, CHANGE); } } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//: cdptr - -// decode_tacts +//Извлекает из записи тактовую последовательности +//Параметры: cdptr - указатель на записанную тактовую последовательность +//Результат пишется в массив decode_tacts //////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ - -// - for(int bt = 0 ; bt < bitsize; bt++) decode_tacts[bt] = 2; // -// - byte* cdp = cdptr; +//Сброс массивов + for(int bt = 0 ; bt < bitsize; bt++) decode_tacts[bt] = 2; //Изначально такт неизвестен + +//Расшифровка тактов + byte* cdp = cdptr; for(int bt = 0 ; bt < bitsize; bt++) { - if (ver == 2 && decode_method == 1) + if (ver == 2 && decode_method == 1) { if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x03) decode_tacts[bt] = 1; if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) decode_tacts[bt] = 0; if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 4; if ((*cdp & 0xf0) > 0x40 && (*cdp & 0x0f) < 0x02) decode_tacts[bt] = 3; } - if (ver == 2 && decode_method == 2) + if (ver == 2 && decode_method == 2) { - if (*cdp == 0x88 || *cdp == 0x87 || *cdp == 0x86 || *cdp == 0x85 || *cdp == 0x84 || *cdp == 0x83 || *cdp == 0x78 || *cdp == 0x77 || *cdp == 0x68 || *cdp == 0x58 ) decode_tacts[bt] = 1; // 11 ( 87, 3 58 84) - if (*cdp == 0x00 || *cdp == 0x01 || *cdp == 0x02 || *cdp == 0x03 || *cdp == 0x10 || *cdp == 0x20 || *cdp == 0x30) decode_tacts[bt] = 0; // 00 ( 00, 3 30 03) - if (*cdp == 0x05 || *cdp == 0x06 || *cdp == 0x07 || *cdp == 0x08 || *cdp == 0x15 || *cdp == 0x16 || *cdp == 0x17 || *cdp == 0x24 || *cdp == 0x25 || *cdp == 0x34 || *cdp == 0x35) decode_tacts[bt] = 4; // 01 ( 07, 3 34) - if (*cdp == 0x50 || *cdp == 0x60 || *cdp == 0x70 || *cdp == 0x80 || *cdp == 0x51 || *cdp == 0x61 || *cdp == 0x71 || *cdp == 0x42 || *cdp == 0x52 || *cdp == 0x43 || *cdp == 0x53) decode_tacts[bt] = 3; // 10 ( 70, 3 43) + if (*cdp == 0x88 || *cdp == 0x87 || *cdp == 0x86 || *cdp == 0x85 || *cdp == 0x84 || *cdp == 0x83 || *cdp == 0x78 || *cdp == 0x77 || *cdp == 0x68 || *cdp == 0x58 ) decode_tacts[bt] = 1; // Такт 11 (В ИДЕАЛЕ 87, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 58 А 84) + if (*cdp == 0x00 || *cdp == 0x01 || *cdp == 0x02 || *cdp == 0x03 || *cdp == 0x10 || *cdp == 0x20 || *cdp == 0x30) decode_tacts[bt] = 0; // Такт 00 (В ИДЕАЛЕ 00, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 30 ДА 03) + if (*cdp == 0x05 || *cdp == 0x06 || *cdp == 0x07 || *cdp == 0x08 || *cdp == 0x15 || *cdp == 0x16 || *cdp == 0x17 || *cdp == 0x24 || *cdp == 0x25 || *cdp == 0x34 || *cdp == 0x35) decode_tacts[bt] = 4; // Такт 01 (В ИДЕАЛЕ 07, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 34) + if (*cdp == 0x50 || *cdp == 0x60 || *cdp == 0x70 || *cdp == 0x80 || *cdp == 0x51 || *cdp == 0x61 || *cdp == 0x71 || *cdp == 0x42 || *cdp == 0x52 || *cdp == 0x43 || *cdp == 0x53) decode_tacts[bt] = 3; // Такт 10 (В ИДЕАЛЕ 70, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 43) } - if (ver == 3 && decode_method == 1) + if (ver == 3 && decode_method == 1) { if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 1; if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) decode_tacts[bt] = 0; if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x02) decode_tacts[bt] = 4; if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) < 0x02) decode_tacts[bt] = 3; } - if (ver == 3 && decode_method == 2) + if (ver == 3 && decode_method == 2) { - if (*cdp == 0x87 || *cdp == 0x86 || *cdp == 0x85 || *cdp == 0x84 || *cdp == 0x83 || *cdp == 0x82 || *cdp == 0x78 || *cdp == 0x77 || *cdp == 0x76 || *cdp == 0x68 || *cdp == 0x67 ) decode_tacts[bt] = 1; // 11 ( 87, 3 58 84) - if (*cdp == 0x00 || *cdp == 0x01 || *cdp == 0x02 || *cdp == 0x03 || *cdp == 0x10 || *cdp == 0x20 || *cdp == 0x30) decode_tacts[bt] = 0; // 00 ( 00, 3 30 03) - if (*cdp == 0x05 || *cdp == 0x06 || *cdp == 0x07 || *cdp == 0x08 || *cdp == 0x15 || *cdp == 0x16 || *cdp == 0x17 || *cdp == 0x24 || *cdp == 0x25 || *cdp == 0x34 || *cdp == 0x35) decode_tacts[bt] = 4; // 01 ( 07, 3 34) - if (*cdp == 0x50 || *cdp == 0x60 || *cdp == 0x70 || *cdp == 0x80 || *cdp == 0x51 || *cdp == 0x61 || *cdp == 0x71 || *cdp == 0x42 || *cdp == 0x52 || *cdp == 0x43 || *cdp == 0x53) decode_tacts[bt] = 3; // 10 ( 70, 3 43) + if (*cdp == 0x87 || *cdp == 0x86 || *cdp == 0x85 || *cdp == 0x84 || *cdp == 0x83 || *cdp == 0x82 || *cdp == 0x78 || *cdp == 0x77 || *cdp == 0x76 || *cdp == 0x68 || *cdp == 0x67 ) decode_tacts[bt] = 1; // Такт 11 (В ИДЕАЛЕ 87, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 58 А 84) + if (*cdp == 0x00 || *cdp == 0x01 || *cdp == 0x02 || *cdp == 0x03 || *cdp == 0x10 || *cdp == 0x20 || *cdp == 0x30) decode_tacts[bt] = 0; // Такт 00 (В ИДЕАЛЕ 00, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 30 ДА 03) + if (*cdp == 0x05 || *cdp == 0x06 || *cdp == 0x07 || *cdp == 0x08 || *cdp == 0x15 || *cdp == 0x16 || *cdp == 0x17 || *cdp == 0x24 || *cdp == 0x25 || *cdp == 0x34 || *cdp == 0x35) decode_tacts[bt] = 4; // Такт 01 (В ИДЕАЛЕ 07, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 34) + if (*cdp == 0x50 || *cdp == 0x60 || *cdp == 0x70 || *cdp == 0x80 || *cdp == 0x51 || *cdp == 0x61 || *cdp == 0x71 || *cdp == 0x42 || *cdp == 0x52 || *cdp == 0x43 || *cdp == 0x53) decode_tacts[bt] = 3; // Такт 10 (В ИДЕАЛЕ 70, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 43) } - if (decode_method == 3) + if (decode_method == 3) { if ((((*cdp) >> 4) + (*cdp & 0x0F)) < 5) decode_tacts[bt] = 0; if (((((*cdp) >> 4) + (*cdp & 0x0F)) > 4) && ((((*cdp) >> 4) + (*cdp & 0x0F)) < 10)) { - if (((*cdp) >> 4) > (*cdp & 0x0f)) decode_tacts[bt] = 3; - if (((*cdp) >> 4) < (*cdp & 0x0f)) decode_tacts[bt] = 4; - if (((*cdp) >> 4) == (*cdp & 0x0f) && (*(cdp - 1) & 0x0F) < 4 ) decode_tacts[bt] = 4; - if (((*cdp) >> 4) == (*cdp & 0x0f) && (*(cdp - 1) & 0x0F) > 4 ) decode_tacts[bt] = 3; + if (((*cdp) >> 4) > (*cdp & 0x0f)) decode_tacts[bt] = 3; + if (((*cdp) >> 4) < (*cdp & 0x0f)) decode_tacts[bt] = 4; + if (((*cdp) >> 4) == (*cdp & 0x0f) && (*(cdp - 1) & 0x0F) < 4 ) decode_tacts[bt] = 4; + if (((*cdp) >> 4) == (*cdp & 0x0f) && (*(cdp - 1) & 0x0F) > 4 ) decode_tacts[bt] = 3; } if ((((*cdp) >> 4) + (*cdp & 0x0F)) > 10) decode_tacts[bt] = 1; @@ -673,10 +675,10 @@ void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ *cdp++; } -// +// Печать расшифорвки if (receiver_dump) { - byte* cdp = cdptr; + byte* cdp = cdptr; Serial.print("BEFORE "); @@ -684,57 +686,57 @@ void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ { - if (decode_tacts[bt] == 1) Serial.print("II"); - if (decode_tacts[bt] == 0) Serial.print("OO"); - if (decode_tacts[bt] == 2) Serial.print("__"); - if (decode_tacts[bt] == 3) Serial.print("IO"); - if (decode_tacts[bt] == 4) Serial.print("OI"); - Serial.print(" "); + if (decode_tacts[bt] == 1) Serial.print("II"); + if (decode_tacts[bt] == 0) Serial.print("OO"); + if (decode_tacts[bt] == 2) Serial.print("__"); + if (decode_tacts[bt] == 3) Serial.print("IO"); + if (decode_tacts[bt] == 4) Serial.print("OI"); + Serial.print(" "); *cdp++; } Serial.println(); } -// , -// +// Расшифровали всё, что смогли с ходу +//Проверяем допустима ли тактовая последовательность for(int bt = 1; bt < bitsize; bt++) { // if (decode_tacts[bt] == 2) { - //0 0X - + //Х0 0X - недопустима if ((decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3) && (decode_tacts[bt] == 0 || decode_tacts[bt] == 4)) decode_tacts[bt] = 2; - //1 1X - + //Х1 1X - недопустима if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt] == 1 || decode_tacts[bt] == 3)) decode_tacts[bt] = 2; } } -// +//Восстановление одиночных тактов for(int bt = 1; bt < (bitsize - 1); bt++) { if (decode_tacts[bt] == 2) { - //0 __ 0 - //0 11 0 + //Х0 __ 0Х + //Х0 11 0Х if ((decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3) && (decode_tacts[bt + 1] == 0 || decode_tacts[bt + 1] == 4)) { decode_tacts[bt] = 1; restore_sign ^= 2; } - //0 __ 1 - //0 10 1 + //Х0 __ 1Х + //Х0 10 1Х if ((decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3) && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ decode_tacts[bt] = 3; restore_sign ^= 2; } - //1 __ 0 - //1 01 0 + //Х1 __ 0Х + //Х1 01 0Х if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt + 1] == 0 || decode_tacts[bt + 1] == 4)){ decode_tacts[bt] = 4; restore_sign ^= 2; } - //1 __ 1 - //1 00 1 + //Х1 __ 1Х + //Х1 00 1Х if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ decode_tacts[bt] = 0; restore_sign ^= 2; @@ -742,56 +744,56 @@ void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ } } - // - cdp = cdptr; + //восстановление потерянных полутактов + cdp = cdptr; for(int bt = 1 ; bt < (bitsize - 1); bt++) { if (decode_tacts[bt] == 2) { - //0 _0 - //0 10 + //Х0 _0 + //Х0 10 if ((*cdp & 0x0f) < 0x05 && (decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3)){ - decode_tacts[bt] = 3; + decode_tacts[bt] = 3; restore_sign ^= 1; } - //1 _1 - //1 01 + //Х1 _1 + //Х1 01 if ((*cdp & 0x0f) > 0x04 && (decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4)){ - decode_tacts[bt] = 4; + decode_tacts[bt] = 4; restore_sign ^= 1; } //0_ 0X //01 0X if ((*cdp & 0xF0) < 0x50 && (decode_tacts[bt + 1] == 0 || decode_tacts[bt + 1] == 4)){ - decode_tacts[bt] = 4; + decode_tacts[bt] = 4; restore_sign ^= 1; } //1_ 1X //10 1X if ((*cdp & 0xF0) > 0x40 && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ - decode_tacts[bt] = 3; + decode_tacts[bt] = 3; restore_sign ^= 1; } } *cdp++; } - // , - :) + //Снова проверяем допустима ли тактовая последовательность, а то что мы там воссановили - неизвестно :) for(int bt = 1; bt < bitsize; bt++) { { - //0 0X - + //Х0 0X - недопустима if ((decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3) && (decode_tacts[bt] == 0 || decode_tacts[bt] == 4)) decode_tacts[bt] = 2; - //1 1X - + //Х1 1X - недопустима if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt] == 1 || decode_tacts[bt] == 3)) decode_tacts[bt] = 2; } *cdp++; } - -// -// , + +//Определение версии пакета по преамбуле +//Если преамбула распознана на несколько тактов уверенно, то можно судить о версии пакета //001100110011 -> v2 if (/*decode_tacts[0] == 0 && decode_tacts[1] == 1 &&*/ decode_tacts[2] == 0 && decode_tacts[3] == 1 && decode_tacts[4] == 0 && decode_tacts[5] == 1 && ver == 3){ @@ -814,19 +816,19 @@ void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ restore_sign ^=4; } -// +// Печать расшифорвки if (receiver_dump) { - byte* cdp = cdptr; + byte* cdp = cdptr; Serial.print("AFTER "); for(int bt = 0 ; bt < bitsize; bt++) { - if (decode_tacts[bt] == 1) Serial.print("II"); - if (decode_tacts[bt] == 0) Serial.print("OO"); - if (decode_tacts[bt] == 2) Serial.print("__"); - if (decode_tacts[bt] == 3) Serial.print("IO"); - if (decode_tacts[bt] == 4) Serial.print("OI"); - Serial.print(" "); + if (decode_tacts[bt] == 1) Serial.print("II"); + if (decode_tacts[bt] == 0) Serial.print("OO"); + if (decode_tacts[bt] == 2) Serial.print("__"); + if (decode_tacts[bt] == 3) Serial.print("IO"); + if (decode_tacts[bt] == 4) Serial.print("OI"); + Serial.print(" "); *cdp++; } Serial.println(); @@ -836,203 +838,203 @@ void Oregon_NR::get_tacts(byte* cdptr, byte bitsize){ return; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//: cdptr - -// btt - . , -// "" - . -// btt=0 btt=1 +//Извлекает из тактовой последовательности битовую +//Параметры: cdptr - указатель на записанные данные +// btt - смещение в тактах. Смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало +// Функция вовзращает качество или "годность" расшифровки - количесвто уверенно узнаных тактов. +// Сравнивая годность с btt=0 и btt=1 выбираем лучшую //////////////////////////////////////////////////////////////////////////////////////////////////// -int Oregon_NR::get_data(int btt, byte p_ver, byte* cdptr){ //btt - , - +int Oregon_NR::get_data(int btt, byte p_ver, byte* cdptr){ //btt - смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало + byte* cdp = cdptr; -// +//Чистим массив for(int bt=0 ; bt(129)) packet_validity += *cdp - 128; if (*cdp<(127)) packet_validity += 128 - *cdp; cdp++; } - return packet_validity; // - + return packet_validity; //возвращаем кол-во достоверных байтов } if (p_ver == 3){ for(int bt = 1 ; bt < READ_BITS; bt++){ - - if (*(cdp - 1) > 128) // 1 + + if (*(cdp - 1) > 128) // если до этого была 1 { - if (decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 1) *cdp -= 2; // 00 11 - 0 - if (decode_tacts[bt - btt] == 3 || decode_tacts[bt - btt] == 4) *cdp += 2; // 01 10 - 1 + if (decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 1) *cdp -= 2; // Если 00 или 11 - то здесь 0 + if (decode_tacts[bt - btt] == 3 || decode_tacts[bt - btt] == 4) *cdp += 2; // Если 01 или 10 - то здесь 1 } - if (*(cdp - 1) < 128) // 0 + if (*(cdp - 1) < 128) // если до этого была 0 { - if (decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 1) *cdp += 2; // 00 11 - 1 - if (decode_tacts[bt - btt] == 3 || decode_tacts[bt - btt] == 4) *cdp -= 2; // 01 10 - 0 + if (decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 1) *cdp += 2; // Если 00 или 11 - то здесь 1 + if (decode_tacts[bt - btt] == 3 || decode_tacts[bt - btt] == 4) *cdp -= 2; // Если 01 или 10 - то здесь 0 } - // , . + // если до этого непонятно что, то скорее всего не удалось восстановить целых два такта. смотрим на несколько бит назад - // - if (*(cdp - 1) == 128 && *(cdp - 2) == 128) + //Восстановление очерёдности при пропуске дух битов к ряду + if (*(cdp - 1) == 128 && *(cdp - 2) == 128) { - //0 __ __ 0 - + //0 __ __ 0 - не меняется if ((decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 3) && (decode_tacts[bt - btt - 2] == 0 || decode_tacts[bt - btt - 2] == 4)) { if (*(cdp - 2) > 128) *cdp += 1; if (*(cdp - 2) < 128) *cdp -= 1; } - else + else { - //1 __ __ 0 0 __ __ 1- + //1 __ __ 0 или 0 __ __ 1- меняется if (*(cdp - 2) > 128) *cdp -= 1; if (*(cdp - 2) < 128) *cdp += 1; } } - // - if (*(cdp - 1) == 128 && *(cdp - 2) == 128 && *(cdp - 3) == 128) + //Восстановление очерёдности при пропуске трёх битов к ряду + if (*(cdp - 1) == 128 && *(cdp - 2) == 128 && *(cdp - 3) == 128) { - //0 __ __ 0 - + //0 __ __ 0 - не меняется if ((decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 3) && (decode_tacts[bt - btt - 3] == 0 || decode_tacts[bt - btt - 3] == 4)) { if (*(cdp - 2) > 128) *cdp += 1; if (*(cdp - 2) < 128) *cdp -= 1; } - else + else { - //1 __ __ 0 0 __ __ 1- + //1 __ __ 0 или 0 __ __ 1- меняется if (*(cdp - 2) > 128) *cdp -= 1; if (*(cdp - 2) < 128) *cdp += 1; } } - // - if (*(cdp - 1) == 128 && *(cdp - 2) == 128 && *(cdp - 3) == 128 && *(cdp - 4) == 128) + //Восстановление очерёдности при пропуске четырёх битов к ряду + if (*(cdp - 1) == 128 && *(cdp - 2) == 128 && *(cdp - 3) == 128 && *(cdp - 4) == 128) { - //0 __ __ 0 - + //0 __ __ 0 - не меняется if ((decode_tacts[bt - btt] == 0 || decode_tacts[bt - btt] == 3) && (decode_tacts[bt - btt - 4] == 0 || decode_tacts[bt - btt - 4] == 4)) { if (*(cdp - 2) > 128) *cdp += 1; if (*(cdp - 2) < 128) *cdp -= 1; } - else + else { - //1 __ __ 0 0 __ __ 1- + //1 __ __ 0 или 0 __ __ 1- меняется if (*(cdp - 2) > 128) *cdp -= 1; if (*(cdp - 2) < 128) *cdp += 1; } } - // . + //Больше нибла с помощью контрольной суммы всё равно не восстановить. - // - + //Подсчитываем кол-во достоверных бит в пакете if (*cdp>(129)) packet_validity += *cdp - 128; if (*cdp<(127)) packet_validity += 128 - *cdp; cdp++; } - return packet_validity; // - + return packet_validity; //возвращаем кол-во достоверных байтов } } //////////////////////////////////////////////////////////////////////////////////////////////////// -// 16384 -//.. 61 -// . . 8 . -// 1 . - 0x00. 088. -//cdptr - , -//dtl - +//Прослушивание канала с частотой дискретизации 16384Гц +//т.е. запись раз в 61мкс +//Каждому такт соответствует байт. Такт делится на два полутакта. В каждом полутакте проводится 8 измерений. +//При наличии сигнала при измерении добавляется 1 к соответствующему ниблу. Отсутствие сигнала - 0x00. Наличие сигнала в такте 0х88. +//cdptr - указатель на область памяти, куда записываются сигнал +//dtl - указатель на количество считанных тактов //////////////////////////////////////////////////////////////////////////////////////////////////// int Oregon_NR::collect(byte* cdptr){ - + bool cdp_prev_null; byte* cdp = cdptr; byte nulls_found = 0; byte bt2 = 0; ////////////////////////////////////////////////////// - // ( + 1/16 ) - if (ver == 2) + //Запись начинаем с этого момента (конец последнего импулься зацепки + 1/16 такта) + if (ver == 2) { - pre_marker += 946; // - *cdp = 0x87; // - 11. ! + pre_marker += 946; //два такта + *cdp = 0x87; //Первые два такта известны - 11. Мы же поймали импульс! cdp++; } if (ver == 3) { - pre_marker += 1434; // - *cdp = 0x07; // - 0101. ! - *(cdp + 1) = 0x07; + pre_marker += 1434; //три такта + *cdp = 0x07; //Первые четыре такта известны - 0101. Мы же поймали импульс! + *(cdp + 1) = 0x07; cdp += 2; } ////////////////////////////////////////////////////// - // - // v3 - 104, THN132 - 76 + 3 111, + //Начинаем читать данные в память + // Максимальная длина поасылка для v3 - 104БИТА, THN132 - 76 бИТ + как минимум 3 бита 111, которые мы уже нашли byte bt; - for (bt = 0 ; bt < READ_BITS2; bt++) { + for (bt = 0 ; bt < READ_BITS2; bt++) { *cdp = 0; - for (byte ckl = 0; ckl < 8; ckl++) { // 8 + for (byte ckl = 0; ckl < 8; ckl++) { // Читаем 8 раз за полутакт pre_marker += 61; while (micros() < pre_marker); - if (digitalRead(RECEIVER_PIN)) *cdp += 0x10; // + if (digitalRead(RECEIVER_PIN)) *cdp += 0x10; // Измерения запиываем в старший полубайт } for (byte ckl = 0; ckl < 8; ckl++) { pre_marker += 61; while (micros() < pre_marker); - if (digitalRead(RECEIVER_PIN)) *cdp += 1; // . . + if (digitalRead(RECEIVER_PIN)) *cdp += 1; // В следующий полутакт измерения запиываем в младший полубайт. Это экономит память. } bt2++; - // 976.5625 - // 7 4 976 976.5714 + 0.009% - if (bt2 == 7) - { + // Идеальный период 976.5625 + // Каждые 7 тактов добавлять 4мкс для выравнивания периода с 976мкс до 976.5714мкс + 0.009% + if (bt2 == 7) + { pre_marker += (4 + timing_correction) ; bt2 = 0; } ///////////////////////////////////////////// - // - // , - // , , + //Есть время до прихода следующего полутакта + //Можно проверить, а не закончилась ли посылка + //Если в канале последнее время пустота или слабые помехи, то это добавляет уверенности, что наблюдаем окончание пакета yield(); if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) nulls_found++; else nulls_found = 0; cdp++; ///////////////////////////////////////////// - // empty_space , - // . - //empty_space - , - // , - // , + //Если более empty_space пустых полей в записи, то + //это вероятнее всего конец посылки. Дальше читать нет смысла + //empty_space - число эмпирическое, зависит от типа приёмника и уровня сигнала + //Если уменьшить, возможно спутать с повреждением пакета + //Если увеличить, то можно не прекратить чтение и начать записывать помехи if (nulls_found > empty_space ) return bt; @@ -1045,20 +1047,20 @@ int Oregon_NR::collect(byte* cdptr){ ///////////////////////////////////////////// - // + //Ждём прихода времени следующего полутакта - while (micros() < pre_marker); + while (micros() < pre_marker); } return bt; -} +} //////////////////////////////////////////////////////////////////////////////////////////////////// -// -// -// -// >0 - , <0 - +//Определение смещения пакетов друг относительно друга +//В качестве параметров передаются указатели на массивы данных +// Возваращаяется смещение +// >0 - второй пакет начался раньше, <0 - Первый пакет начался раньше //////////////////////////////////////////////////////////////////////////////////////////////////// int Oregon_NR::correlate_data(byte* ser1, byte* ser2){ - + byte best_correl = 0; int best_shift = 0; byte best_correl_back = 0; @@ -1067,7 +1069,7 @@ int Oregon_NR::correlate_data(byte* ser1, byte* ser2){ byte* s1; byte* s2; byte* s2t = ser2; - // + //смещаем первый пакет относительно второго for (byte sht = 0; sht < READ_BITS; sht++){ s1 = ser1; s2 = s2t; @@ -1087,16 +1089,16 @@ int Oregon_NR::correlate_data(byte* ser1, byte* ser2){ best_shift = i; } } - -// - - + +//Теперь наоборот -втрой пакет относительно первого + byte* s1t = ser1; for (byte sht = 0; sht < READ_BITS; sht++){ s2 = ser2; s1 = s1t; shift_score[sht] = 0; for (byte sp = 0; sp < READ_BITS-sht; sp++){ - + if ((*s1 > (128+1) && *s2 > (128+1))||(*s1 < (128-1) && *s2 < (128-1)) ) shift_score[sht]++; s2++; s1++; @@ -1104,27 +1106,27 @@ int Oregon_NR::correlate_data(byte* ser1, byte* ser2){ yield(); s1t++; } -// - +// Ищем наилучшее совпадение для обоих вариантов + for (int i = 0; i < READ_BITS; i++){ - + if (shift_score[i] > best_correl_back){ best_correl_back = shift_score[i]; best_shift_back = i; } } - // + //И возвращаем самое лучшее из двух if (best_correl_back > best_correl) return -best_shift_back; else return best_shift; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -// -// , .. . -//shift - +//Сборка из двух пакетов +//В качестве параметров передаются указатели на массивы данных +// Причём первым должен идти результирующий пакет, т.е. тот который имеет более длинную преамбулу. +//shift - смещение втрого пакета относительного первого //////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_NR::assemble_data(byte* s1, byte* s2, int shift){ - + if (shift >= 0) { for (int g = 0; g < shift; g++) s2++; for (int i = 0; i < READ_BITS - shift; i++){ @@ -1147,13 +1149,13 @@ void Oregon_NR::assemble_data(byte* s1, byte* s2, int shift){ } } //////////////////////////////////////////////////////////////////////////////////////////////////// -// . 0xFF - -// -//code - -//result - +//Возвращает позицию синхронибла в посылке. 0xFF - нет синхронибла +// +//code - указатель на расшифрованную битовую последовательность +//result - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// int Oregon_NR::get_synchro_pos(byte* code){ - + bool syn_found = false; byte* cp = code; int i = 0; @@ -1167,31 +1169,31 @@ int Oregon_NR::get_synchro_pos(byte* code){ syn_found = true; break; } - + cp++; } if (!syn_found) return 0xFF; - // , , , . . - // ! - - // 16-3 = 13 . 10!!! - + //Последовательность нашли, но надо убедиться, что перед этим идёт перамбула, т. е. уверенные единицы + // В преамбуле не может быть нулей! - это главное + //Преамбулу надо просматривать на 16-3 = 13 битов назад. Ну хотя бы на 10!!! + for (byte g = i; i - g < 10 && g > 0; g --){ cp --; - if (*cp < 127) return 0xFF; // . ! + if (*cp < 127) return 0xFF; // Перед синхрониблом в преамбуле не может быть уверенного нуля. Нет тут синхронибла! } return (byte) i; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//code - -//result - -//valid - +//Создаёт кодовую посылку +//code - указатель на расшифрованную битовую последовательность +//result - указатель на кодовую посылку +//valid - указатель на карту достоверности кодовой посылки //////////////////////////////////////////////////////////////////////////////////////////////////// int Oregon_NR::get_info_data(byte* code, byte* result, byte* valid){ byte* rd = result; byte* vd = valid; - // + //Чистим массивы for (int l = 0; l < PACKET_LENGTH; l++){ *vd = 0; *rd = 0; @@ -1200,23 +1202,23 @@ int Oregon_NR::get_info_data(byte* code, byte* result, byte* valid){ } rd = result; vd = valid; - + int csm; for (csm = 0; csm < 30; csm++){ - if ( !consist_synchro && (*code < 128 && *(code + 1) > 128 && *(code + 2) < 128 && *(code + 3) > 128)) break; // 0101 - if ( consist_synchro && (*code < 127 && *(code + 1) > 129 && *(code + 2) < 127 && *(code + 3) > 129)) break; + if ( !consist_synchro && (*code < 128 && *(code + 1) > 128 && *(code + 2) < 128 && *(code + 3) > 128)) break; //Найдена последовательность 0101 + if ( consist_synchro && (*code < 127 && *(code + 1) > 129 && *(code + 2) < 127 && *(code + 3) > 129)) break; code++; } - // 20 , ! - if (ver == 2 & csm > 22) return 0; - // - if (ver == 3 & csm > 30) return 0; - // + // Синхронибл в первых 20 битах не найден, такой пакет не расшифруешь во второй версии протокола! + if (ver == 2 & csm > 22) return 0; + // ДЛя третьей версии протокола цифра иная + if (ver == 3 & csm > 30) return 0; + //Переходим на начало считывания code += 4; int ii = 0; - for (int i = 0; i < READ_BITS - csm; i++) + for (int i = 0; i < READ_BITS - csm; i++) { - // + // Чтобы не выйти за пределы if (i >= PACKET_LENGTH * 4) break; byte multipl; switch (ii){ @@ -1243,107 +1245,112 @@ int Oregon_NR::get_info_data(byte* code, byte* result, byte* valid){ } // //////////////////////////////////////////////////////////////////////////////////////////////////// -// +//Функции расшифровки данных с датчиков //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает значение температуры +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// float Oregon_NR::get_temperature(byte* oregon_data){ - if (((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132) && crc_c) - { - float tmprt; - oregon_data += 8; - // : - for (int g=0;g < 4; g++) if (*(oregon_data + g) > 9) *(oregon_data + g) = *(oregon_data + g) - 8; - tmprt += *(oregon_data) * 0.1; - tmprt += *(oregon_data + 1); - tmprt += *(oregon_data + 2) * 10; - return (*(oregon_data + 3)) ? -tmprt : tmprt; + if (((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132) && crc_c) + { + float tmprt; + oregon_data += 8; + //исправляем возможные ошибки: + for (int g = 0; g < 4; g++) + if (*(oregon_data + g) > 9) + *(oregon_data + g) = *(oregon_data + g) - 8; + tmprt += *(oregon_data)*0.1; + tmprt += *(oregon_data + 1); + tmprt += *(oregon_data + 2) * 10; + return (*(oregon_data + 3)) ? -tmprt : tmprt; } // else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// . -//oregon_data - +//Возвращает тип сенсора. +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// word Oregon_NR::get_sensor(byte* oregon_data){ return (word)(*(oregon_data))*0x1000 + (*(oregon_data+1))*0x0100 + (*(oregon_data+2))*0x10 + *(oregon_data+3); } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает значение канала +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_channel(byte* oregon_data){ if (crc_c) { - byte channel = 0; + byte channel = 0; // word sens_type = get_sensor(oregon_data); if (sens_type == THGN132 || sens_type == THN132 ) { - switch (*(oregon_data + 4)) - { - case 1: - channel = 1; - break; - case 2: - channel = 2; - break; - case 4: - channel = 3; - break; - } + switch (*(oregon_data + 4)) + { + case 1: + channel = 1; + break; + case 2: + channel = 2; + break; + case 4: + channel = 3; + break; + } } - if ((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 ) - channel = *(oregon_data + 4); - return channel; + if ((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810) + channel = *(oregon_data + 4); + return channel; } else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_battery(byte* oregon_data){ - if (((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132 || sens_type == WGR800 || sens_type == UVN800) && crc_c) - return (*(oregon_data+7) & 0x4) ? 0 : 1; - else return 0; + if (((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132 || sens_type == WGR800 || sens_type == UVN800) && crc_c) + return (*(oregon_data + 7) & 0x4) ? 0 : 1; + else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает значение влажности +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// float Oregon_NR::get_humidity(byte* oregon_data){ - if (((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 || sens_type == THGN132) && crc_c ){ - byte tmprt = 0; - oregon_data += 12; - // : - for (int g=0; g < 2; g++) if (*(oregon_data + g) > 9) *(oregon_data + g) = *(oregon_data + g) - 8; - tmprt = *(oregon_data); - tmprt += *(oregon_data + 1) * 10; - return (float)tmprt; + if (((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810 || sens_type == THGN132) && crc_c) + { + byte tmprt = 0; + oregon_data += 12; + //исправляем возможные ошибки: + for (int g = 0; g < 2; g++) + if (*(oregon_data + g) > 9) + *(oregon_data + g) = *(oregon_data + g) - 8; + tmprt = *(oregon_data); + tmprt += *(oregon_data + 1) * 10; + return (float)tmprt; } else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// id -//oregon_data - +//Возвращает id датчика +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_id(byte* oregon_data){ - if (((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132 || sens_type == WGR800 || sens_type == UVN800) && crc_c) - { - byte tmprt; - oregon_data += 5; - tmprt = *(oregon_data) * 0x10; - tmprt += *(oregon_data + 1); - return tmprt; + if (((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130 || sens_type == THGR810 || sens_type == THGN132 || sens_type == THN132 || sens_type == WGR800 || sens_type == UVN800) && crc_c) + { + byte tmprt; + oregon_data += 5; + tmprt = *(oregon_data)*0x10; + tmprt += *(oregon_data + 1); + return tmprt; } else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// /c -//oregon_data - +//Возвращает среднее значение ветра в м/c +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// float Oregon_NR::get_avg_windspeed(byte* oregon_data) { @@ -1357,8 +1364,8 @@ float Oregon_NR::get_avg_windspeed(byte* oregon_data) } //////////////////////////////////////////////////////////////////////////////////////////////////// -// /c -//oregon_data - +//Возвращает начение максимального порыва ветра в м/c +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// float Oregon_NR::get_max_windspeed(byte* oregon_data) { @@ -1372,22 +1379,22 @@ float Oregon_NR::get_max_windspeed(byte* oregon_data) } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает направление ветра в квадрантах +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_winddirection(byte* oregon_data) { if (sens_type == WGR800 && crc_c){ byte tmprt; return *(oregon_data + 8) & 0x0F; - // 0-N, 1-NNE, 2-NE, 3-ENE, 4-E, 5-ESE, 6-SE, 7-SSE, 8-S, 9-SSW, A-SW, B-WSW, C-W, D-WNW, E-NW,F-NNW + //Квадранты 0-N, 1-NNE, 2-NE, 3-ENE, 4-E, 5-ESE, 6-SE, 7-SSE, 8-S, 9-SSW, A-SW, B-WSW, C-W, D-WNW, E-NW,F-NNW } else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// UV- -//oregon_data - +//Возвращает UV-индекс +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_UV(byte* oregon_data) { @@ -1401,8 +1408,8 @@ byte Oregon_NR::get_UV(byte* oregon_data) } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает освещённость в условных единицах +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_light(byte* oregon_data) { @@ -1418,8 +1425,8 @@ byte Oregon_NR::get_light(byte* oregon_data) //////////////////////////////////////////////////////////////////////////////////////////////////// -// CRC -//oregon_data - +//Проверка CRC +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ @@ -1427,22 +1434,22 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ byte crc, resived_crc, truecrc, resived_truecrc, i; crc=0; byte CCIT_POLY = 0x07; - + if (sens_type==THGN132){ - //CHKSUM 1...15 + //CHKSUM 1...15 //CRC 1...5,8...15 STARTSUM = 3Ch, POLY = 07h truecrc = 0x3C; for(int x=0; x < 15; x++){ crc += *pp; if ( x != 5 && x != 6){ truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; } - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1452,21 +1459,21 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; } - if ((sens_type & 0x0FFF) == RTGN318){ - //CHKSUM 1...15 + if ((sens_type & 0x0FFF) == RTGN318 || (sens_type & 0x0FFF) == RTGN130){ + //CHKSUM 1...15 //CRC 1...5,8...15 STARTSUM = 00h, POLY = 07h truecrc = 0x0; for(int x=0; x<15; x++){ crc += *pp; if ( x != 5 && x != 6){ truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; } - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1477,21 +1484,21 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ } if (sens_type == THGR810){ - //CHKSUM 1...15 + //CHKSUM 1...15 //CRC 00h,1...15 STARTSUM = 00h, POLY = 07h truecrc = 0x0; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; for(int x=0; x<15; x++){ crc += *pp; truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1502,21 +1509,21 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ } if (sens_type == UVN800 ){ - //CHKSUM 1...13 + //CHKSUM 1...13 //CRC 00h,1...13 STARTSUM = 00h, POLY = 07h truecrc = 0x0; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; for(int x=0; x<13; x++){ crc += *pp; truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1529,9 +1536,9 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ if (sens_type == WGR800){ //CHKSUM 1...17 - for(int x=0; x < 17; x++){ + for(int x=0; x < 17; x++){ crc += *pp; - pp++; + pp++; } resived_crc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; @@ -1540,20 +1547,20 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ if (sens_type==THN132){ - //CHKSUM 1...12 + //CHKSUM 1...12 //CRC 1...5,8...12 STARTSUM = D6h, POLY = 07h truecrc = 0xD6; for(int x=0; x<12; x++){ crc += *pp; if ( x != 5 && x != 6){ truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; } - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1570,12 +1577,12 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ for(int x=0; x<15; x++){ crc += *pp; truecrc ^= *pp; - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; - pp++; + pp++; } - for(i = 0; i<4; i++) + for(i = 0; i<4; i++) if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; else truecrc <<= 1; @@ -1590,23 +1597,23 @@ bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// +//Востановление данных по типу датчика //////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_NR::restore_data(byte* oregon_data, word sens_type){ - + byte* pp=oregon_data; if (sens_type==THGN132){ pp+=8; for(int x=0; x<6; x++){ if(*pp>9 && x!=3) *pp-=8; - pp++; + pp++; } } if (sens_type==THN132){ pp+=8; for(int x=0; x<3; x++){ if(*pp>9) *pp-=8; - pp++; + pp++; } } return; @@ -1615,7 +1622,7 @@ void Oregon_NR::restore_data(byte* oregon_data, word sens_type){ //////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_NR::led_light(bool led_on) { - if (LED != 0xFF) { + if (LED != 0xFF) { if (PULL_UP && led_on) digitalWrite(LED, LOW); if (PULL_UP && !led_on) digitalWrite(LED, HIGH); if (!PULL_UP && led_on) digitalWrite(LED, HIGH); @@ -1628,8 +1635,8 @@ void Oregon_NR::led_light(bool led_on) { // #if ADD_SENS_SUPPORT == 1 //////////////////////////////////////////////////////////////////////////////////////////////////// -// GAS -//gas_data - +//Функции расшифровки данных датчиков GAS +//gas_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// byte Oregon_NR::get_gas_channel(byte* gas_data){ diff --git a/Oregon_NR.h b/Oregon_NR.h index b866329..fe1d3e4 100644 --- a/Oregon_NR.h +++ b/Oregon_NR.h @@ -3,7 +3,7 @@ #define Oregon_NR_h ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// This Arduino code is for receive and transmit data using Oregon Scientific RF protocol version 2.1 and 3.0. +// This Arduino code is for receive and transmit data using Oregon Scientific RF protocol version 2.1 and 3.0. // // Last updated: 14 October 2019 // @@ -12,11 +12,12 @@ // Receive and transmit: // THGN132N (THGR122N, THGN123N), // RTGN318, +// RTGN130, // THGR810. // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -26,7 +27,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2019 Sergey Zawislak +// Copyright (c) 2019 Sergey Zawislak // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -35,94 +36,96 @@ // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Oregon Scientific v2.1 v3.0 +// Данная библиотека Ардуино предназначена для приема и передачи данных в формате беспроводного протокола Oregon Scientific v2.1 и v3.0 // -// 14 2019 +// Последнее обновление 14 Октября 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, +// RTGN130, // THGR810. -// : +// Тольок приём: // THN132N, -// WGR800, +// WGR800, // UVN800. // -// ( ) +// Также поддерживаются датчики собственной разработки (за дополнительной документацей обращаться к автору) // -// - OREGON_NR +// Этот файл - часть библиотеки OREGON_NR ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2019 +// Copyright (c) 2019 Сергей Зависляк // -// , -// ( ), , -// , , , , , , -// / , , , : +// Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации +// (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, +// включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование +// и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: // -// . +// Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. // -// ܻ, - , , -// , , . -// - , , , , , -// - . +// ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ +// ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ +// НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, +// ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Oregon Scientific: +// Распознавание пакетов от следующих датчиков Oregon Scientific: // -#define THGN132 0x1D20 // , , 3 , -#define THN132 0xEC40 // , 3 , -#define RTGN318 0xDCC3 // , , 5 , -#define THGR810 0xF824 // , , 10 , -#define WGR800 0x1984 // -#define UVN800 0xD874 // -, ( XOR ) +#define THGN132 0x1D20 // Температура, влажность, 3 канала, +#define THN132 0xEC40 // Температура, 3 канала, +#define RTGN318 0xDCC3 // Температура, влажность, 5 каналов, +#define RTGN130 0x0CC3 // Температура, влажность, 5 каналов, +#define THGR810 0xF824 // Температура, влажность, 10 каналов, +#define WGR800 0x1984 // Направление и скорость ветра +#define UVN800 0xD874 // УФ-индекс, освещённость (спасибо XOR за предоставленные данные) // -// : -#define THP 0x5500 // , , , 8 , 3- , -#define GAS 0xAA00 // , , CH4, 8 , -#define FIRE 0xBB00 // 22 72 -#define CURRENT 0xEE00 // , , 8 , -#define CAPRAIN 0x8800 // +// Датчики собственной разработки: +#define THP 0x5500 // Температура, влажность, атм давление, 8 каналов, работа от 3-ех батарей АА, +#define GAS 0xAA00 // Температура, влажность, концентрация СО и CH4, 8 каналов, +#define FIRE 0xBB00 // Контроль сигналов пожарных линий датчиков ИП22 и ИП72 +#define CURRENT 0xEE00 // Ток, напряжение, 8 каналов, +#define CAPRAIN 0x8800 // Емкостной всепогодный датчик осадков // -// -#define ADD_SENS_SUPPORT 1 // - -#define IS_ASSEMBLE 1 // ( v2) - ! +//Этими параметрами можно поиграть для экономии ресурсов +#define ADD_SENS_SUPPORT 1 // ПОддежка дополнительных типов датчиков собственной разработки - отключение незначительно экономит ОЗУ +#define IS_ASSEMBLE 1 // Пытаться ли собрать из двух повреждённых пакетов один целый (для v2) - отключение сильно экономит ОЗУ! // -// +// Этими параметрами можно поиграть для настройки наилучшего приёма -#define MAX_LENGTH2 976 // v2 - , -#define MIN_LENGTH2 883 // ( v2 93), .. 883, - -#define MAX_LENGTH3 488 // v3 - , -#define MIN_LENGTH3 330 // ( v2 138), .. 350, +#define MAX_LENGTH2 976 // Максимальная длина импульса преамбулы v2 - не меньше периода, чтобы ловился сигнал от разных эмуляторов +#define MIN_LENGTH2 883 // Минимальная длина импульса при захвате (для v2 импульсы укорочены на 93мкс), т.е. должна быть не больше 883мкс, -#define LENGTH_TOLERANCE 64 // . - // " " +#define MAX_LENGTH3 488 // Максимальная длина импульса преамбулы v3 - не меньше полупериода, чтобы ловился сигнал от разных эмуляторов +#define MIN_LENGTH3 330 // Минимальная длина импульса при захвате (для v2 импульсы укорочены на 138мкс), т.е. должна быть не больше 350мкс, -#define CATCH_PULSES 3 // . 2 - 4. - // - - // - , +#define LENGTH_TOLERANCE 64 // Допустимое отклонение для длины импульса. Зависит от приёмника + // В зависимости от уровня сигнала может "плавать длина импульсов" -// ! +#define CATCH_PULSES 3 // Сколько искать правильных импульсов для начала захвата. Рекомендовано 2 - 4. + // Больше - можно не поймать пакет в условиях сильных шумов + // Меньше - можно пропустить пакет, сильно отвлекаясь на анализ шумов -#define FIND_PACKET 1 +//Эти параметры трогать не надо! + +#define FIND_PACKET 1 #define ANALIZE_PACKETS 2 -#define PER_LENGTH2 976 // . v2 v3 976,56 (1024) +#define PER_LENGTH2 976 // Период передачи данных. Для v2 и v3 976,56мкс (1024Гц) #define PER_LENGTH3 488 -#define READ_BITS 105 // -#define READ_BITS2 210 // * 2 -#define PACKET_LENGTH 20 // ( ) +#define READ_BITS 105 // Максимальная длина пакета в тактах +#define READ_BITS2 210 // Максимальная длина пакета в тактах * 2 +#define PACKET_LENGTH 20 // Длина пакета в ниблах без учёта преамбулы (с синхрониблом) static int RECEIVER_PIN; @@ -130,7 +133,7 @@ class Oregon_NR { public: - // + //Данные датчика word sens_type; //Sensor type @@ -143,34 +146,34 @@ class Oregon_NR byte ver = 0; //Protocol version - bool crc_c = 0; //CRC check result. . . - bool captured = 0; //Capture data flag. , . + bool crc_c = 0; //CRC check result. Сбрасывается при захвате. Выставляется при приёме корректного пакета. + bool captured = 0; //Capture data flag. Выставляется, если были считаны данные в память. unsigned long work_time; //Capture time byte packet[PACKET_LENGTH]; //Result packet - byte valid_p[PACKET_LENGTH]; //Validity mask - + byte valid_p[PACKET_LENGTH]; //Validity mask - маска уверенного распознавания битов byte packets_received = 0; //Number of received packets in block (0...2) - byte received_CRC; //Calculated RC - - Oregon_NR(byte, byte); //. : - Oregon_NR(byte, byte, byte, bool); //( , , , pull up) + byte received_CRC; //Calculated СRC + + Oregon_NR(byte, byte); //Конструктор. Параметры: + Oregon_NR(byte, byte, byte, bool); //(вывод приёмника, номер прерывания, вывод светодиода, pull up) void start(); //Star listening receiver - void stop(); //Stop listening receiver. , + void stop(); //Stop listening receiver. Чтобы не занимал процессор, когда не нужен void capture(bool); //Capture packet. if parameter is true function dumps capture data to Serial. - bool consist_synchro = false; // ? - - byte empty_space = 3; // "" ? - // . - // , . - // 5 - bool catch2 = 1, catch3 = 1; // - int timing_correction = 0; // ( -10 +10) - byte decode_method = 3; // - //1 - - //3 - - - // + bool consist_synchro = false; //При поиске синхронибла опираться подтверждённые или сомнительные данные? + + byte empty_space = 3; //Какое количество "пустых" тактов нужно для определения конца посылки? + //Параметр определяется уровнем сигнала и скоростью АРУ приёмника. + //Чем они лучше, тем меньше число. НО меньше двух не рекомендуется + //В сатрой версии было 5 + bool catch2 = 1, catch3 = 1; //какие версии протокола принимать + int timing_correction = 0; //Коррекция частоты приёма (от -10 до +10) + byte decode_method = 3; // Метод декодирования тактов + //1 - традиционный + //3 - при девиации частоты + + //Ветрометр float sens_avg_ws, sens_max_ws; byte sens_wdir; float get_avg_windspeed(byte*); @@ -181,72 +184,72 @@ class Oregon_NR byte get_UV(byte*); byte get_light(byte*); - byte restore_sign; // , + byte restore_sign; //Битовое поле, инормирующее об успешных способах реставрации пакета - //0 - - //1 - - //2 - - //3 - (v2) - + //0 - восстановлены одиночные такты + //1 - восстановлены двойные такты + //2 - исправление версии протокола при разборке пакета + //3 - восстановлено методом сращивания (v2) - отключено для экономии ресурсов - bool receiver_dump = 0; // Serial. capture(true) - // - // + bool receiver_dump = 0; //Сбрасывать ли дамп канала в Serial. работает тольок если capture(true) + // фактически это осциллограмма огибающей сигнала с приёмника + // Также выводятся тактовые последовательности до и после восстановления #if ADD_SENS_SUPPORT == 1 float sens_pressure, //Pressure - sens_voltage, // (for CURRENT THP sensors) + sens_voltage, // напряжение в В (for CURRENT и THP sensors) sens_tmp2; //Temperature2 (for GASv2 sensor) byte sens_CO, //CO (ppm*10) (for GASv2 sensor) sens_CH; //CH4 (ppm*100)(ppm) byte sens_ip22, //IP22 channel data (for FIRE sensor) - sens_ip72, //IP72 channel data (for FIRE sensor) + sens_ip72, //IP72 channel data (for FIRE sensor) sens_lockalarm; //LOCK_ALARM channel data (for FIRE sensor) - float sens_current; // (for CURRENT sensor) - - word sens_pump_count; // - unsigned long sens_drop_counter;// (for CAPRAIN sensor) - int sens_capacitance; // (for CAPRAIN sensor) -#endif + float sens_current; // ток в А (for CURRENT sensor) + + word sens_pump_count; // счётчик насоса + unsigned long sens_drop_counter;// счётчик капель (for CAPRAIN sensor) + int sens_capacitance; //Емкость сенсора (for CAPRAIN sensor) +#endif private: - + byte read_tacts, read_tacts2, result_size; - byte LED = 0xFF; // , - bool PULL_UP; // - byte packet_number = 0; // - int INT_NO; // - //bool reciever_ctrl = true; // ( , ) - - // - byte decode_tacts[READ_BITS2]; // . - // 0= - // 1= - // 2= - // 3=+ - // 4=- - - byte collect_data[READ_BITS2], // + byte LED = 0xFF; //вывод светодиода, который мигает при приёме + bool PULL_UP; //куда подключён светодиод + byte packet_number = 0; //Количесвто принятых пакетов в посылке + int INT_NO; //Номер прерывания приёмника + //bool reciever_ctrl = true; //Флаг контроля ресивера (выставляется при приходе импулься, сбрасывается в таймере) + + //Массивы данных для записи данных с канала и полученных битов + byte decode_tacts[READ_BITS2]; //Массив тактов. значения + // 0=ноль + // 1=единица + // 2=неизвестен + // 3=переход+ + // 4=переход- + + byte collect_data[READ_BITS2], //Память для сбора данных с приёмника #if IS_ASSEMBLE collect_data2[READ_BITS2]; #else collect_data2[1]; #endif - // , : - // 128 - - // >128 - - // <128 - + //А когда становится массивом полученных битов, то значения такие: + // 128 - неизвестен + // >128 - единица + // <128 - ноль byte receive_status = FIND_PACKET; byte start_pulse_cnt = 0; - unsigned long pulse_length, timer_marklong; + unsigned long pulse_length, timer_marklong; unsigned long pulse_marker, right_pulse_marker; - unsigned long pre_marker; // + unsigned long pre_marker; // Для хранения временных меток преамбулы при захвате пакета unsigned long first_packet_end; - byte data_val, data_val2; // - byte synchro_pos, synchro_pos2; // - + byte data_val, data_val2; // Качество пакетов + byte synchro_pos, synchro_pos2; // Позиции синхрониблов в записи + byte get_gas_CH(byte* gas_data); byte get_gas_CO(byte* gas_data); byte get_gas_hmdty(byte* gas_data); @@ -283,7 +286,7 @@ class Oregon_NR float get_thp_temperature(byte* oregon_data); float get_thp_pressure(byte* oregon_data); float get_thp_voltage(byte* oregon_data); -#endif +#endif };