From 84e46c1d17bbb22250afea8394ca292fcdde3133 Mon Sep 17 00:00:00 2001 From: Kirill Kuznetsov Date: Sat, 3 Aug 2019 19:57:08 +0300 Subject: [PATCH] Reformat --- Oregon_NR.cpp | 2061 ++++++++++++++++++++++++++++--------------------- Oregon_NR.h | 399 +++++----- Oregon_TM.cpp | 742 +++++++++--------- Oregon_TM.h | 153 ++-- README.md | 42 +- 5 files changed, 1854 insertions(+), 1543 deletions(-) diff --git a/Oregon_NR.cpp b/Oregon_NR.cpp index 3c8be18..77ab9d7 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: 29 June 2019 // @@ -14,7 +14,7 @@ // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -24,7 +24,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,68 +33,70 @@ // 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 // -// 29 2019 +// Последнее обновление 29 июня 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, // 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; -void receiver_interruption(void) { - if(digitalRead(RECEIVER_PIN)){ - // +static volatile unsigned long pl, timer_mark; +void receiver_interruption(void) +{ + if (digitalRead(RECEIVER_PIN)) + { + //Начало импульса pl = 0; - pm = micros(); + pm = micros(); } - else{ - // - // - pl = micros() - pm; + else + { + //Конец импульса + //Вычисляется время окончания и длина + pl = micros() - pm; //pm += pl; } //yield(); -} +} #endif ////////////////////////////////////////////////////////////////////// @@ -102,7 +104,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) @@ -111,8 +113,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); // Вывод светодиода } ////////////////////////////////////////////////////////////////////// @@ -123,21 +125,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; @@ -146,9 +148,8 @@ void Oregon_NR::capture(bool DEBUG_INFO) data_val = 0; data_val2 = 0; - //////////////////////////////////////////////////////// - // + //Чтение данных с приёмника noInterrupts(); pulse_length = pl; pl = 0; @@ -156,46 +157,54 @@ 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 (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 (start_pulse_cnt == 0) + { //////////////////////////////////////////////////////// - // "" - - if (pulse_length < (MAX_LENGTH2 + LENGTH_TOLERANCE) && pulse_length > (MIN_LENGTH2 - LENGTH_TOLERANCE) && catch2 ) { + //Найдена первый "правильный" импульс - определяем тип протокола + if (pulse_length < (MAX_LENGTH2 + LENGTH_TOLERANCE) && pulse_length > (MIN_LENGTH2 - LENGTH_TOLERANCE) && catch2) + { start_pulse_cnt++; pre_marker = pulse_marker; pulse_length = 0; - ver = 2; + ver = 2; } - if (pulse_length < (MAX_LENGTH3 + LENGTH_TOLERANCE) && pulse_length > (MIN_LENGTH3 - LENGTH_TOLERANCE) && catch3 ) { + if (pulse_length < (MAX_LENGTH3 + LENGTH_TOLERANCE) && pulse_length > (MIN_LENGTH3 - LENGTH_TOLERANCE) && catch3) + { start_pulse_cnt++; pre_marker = pulse_marker; pulse_length = 0; - ver = 3; + ver = 3; } } - else{ + else + { /////////////////////////////////////////////////////////// - // "" - if (pulse_length <= (MAX_LENGTH2 + LENGTH_TOLERANCE) && pulse_length >= (MIN_LENGTH2 - LENGTH_TOLERANCE) && catch2) { + //Найдена следующий "правильный" импульс + 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) - { + //Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов + if (pulse_marker - pre_marker > (PER_LENGTH2 * 2 - LENGTH_TOLERANCE) && pulse_marker - pre_marker < (PER_LENGTH2 * 2 + LENGTH_TOLERANCE) && ver == 2) + { start_pulse_cnt++; pre_marker = pulse_marker; pulse_length = 0; } /////////////////////////////////////////////////////////// - // - // + //Следующий импульс находится в неправильном месте + //Назначаем его первым else - { + { start_pulse_cnt = 1; pre_marker = pulse_marker; pulse_length = 0; @@ -203,20 +212,21 @@ void Oregon_NR::capture(bool DEBUG_INFO) } } - if (pulse_length <= (MAX_LENGTH3 + LENGTH_TOLERANCE) && pulse_length >= (MIN_LENGTH3 - LENGTH_TOLERANCE) && catch3) { + 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) - { + //Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов + if (pulse_marker - pre_marker > (PER_LENGTH3 * 2 - LENGTH_TOLERANCE) && pulse_marker - pre_marker < (PER_LENGTH3 * 2 + LENGTH_TOLERANCE) && ver == 3) + { start_pulse_cnt++; pre_marker = pulse_marker; pulse_length = 0; } /////////////////////////////////////////////////////////// - // - // + //Следующий импульс находится в неправильном месте + //Назначаем его первым else - { + { start_pulse_cnt = 1; pre_marker = pulse_marker; pulse_length = 0; @@ -225,20 +235,22 @@ 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 (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) + { - if (start_pulse_cnt == CATCH_PULSES && receive_status == FIND_PACKET) { - work_time = millis(); start_pulse_cnt = 0; if (packet_number == 0) @@ -255,230 +267,276 @@ 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; + return; } - // , + //Отключаем прерывание, чтобы сократить время обработки detachInterrupt(INT_NO); - + led_light(true); restore_sign = 0; - - // - // - // v2 - 87 07 86 06, .. 883 395 - // v3 - 86 06 87 07 .. 838 350 - if (DEBUG_INFO && receiver_dump){ - Serial.println(" "); - Serial.print("SCOPE1 "); - for(int bt = 0; bt < read_tacts; bt++){ - Serial.print((collect_data[bt] & 0xF0) >> 4, HEX); - Serial.print(collect_data[bt] & 0x0F, HEX); - Serial.print(' '); - } - Serial.println(" "); - if ( packet_number == 2) - { - Serial.print("SCOPE2 "); - for(int bt = 0; bt < read_tacts2; bt++){ - Serial.print((collect_data2[bt] & 0xF0) >> 4, HEX); - Serial.print(collect_data2[bt] & 0x0F, HEX); - Serial.print(' '); - } - Serial.println(" "); - } + //Дамп собранных данных + //ДЛя посылки без помех значения имурльсов олжны быть примерно + // v2 - 87 07 и изредка 86 06, т.к. длина импульса 883мс и 395мс + // v3 - 86 06 и изредка 87 07 т.к. длина импульса 838 и 350мс + if (DEBUG_INFO && receiver_dump) + { + Serial.println(" "); + Serial.print("SCOPE1 "); + for (int bt = 0; bt < read_tacts; bt++) + { + Serial.print((collect_data[bt] & 0xF0) >> 4, HEX); + Serial.print(collect_data[bt] & 0x0F, HEX); + Serial.print(' '); + } + Serial.println(" "); + if (packet_number == 2) + { + Serial.print("SCOPE2 "); + for (int bt = 0; bt < read_tacts2; bt++) + { + Serial.print((collect_data2[bt] & 0xF0) >> 4, HEX); + Serial.print(collect_data2[bt] & 0x0F, HEX); + Serial.print(' '); } - + Serial.println(" "); + } + } ////////////////////////////////////////////// - // - // . decode_tacts[] + //Обработка первой записи + //Расшифровываем запись. Данные сохраянем в decode_tacts[] get_tacts(collect_data, read_tacts); bool halfshift; - if (get_data(0, ver, collect_data) > get_data(1, ver, collect_data)){ + if (get_data(0, ver, collect_data) > get_data(1, ver, collect_data)) + { data_val = get_data(0, ver, collect_data); halfshift = 0; } - else { + else + { data_val = get_data(1, ver, collect_data); 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 "); - for(int bt = 0; bt < READ_BITS; bt++) { - if ((ver == 3 && bt <= read_tacts) || (ver == 2 && bt <= read_tacts / 2)){ - if (collect_data[bt] > 128 + 1) Serial.print('I'); - if (collect_data[bt] < 128 - 1) Serial.print('O'); - if (collect_data[bt] == 128 + 1) Serial.print('i'); - if (collect_data[bt] == 128 - 1) Serial.print('o'); - if (collect_data[bt] == 128) Serial.print('.'); - if (receiver_dump) Serial.print(" "); + //Выводим посылку + if (DEBUG_INFO) + { + if (packet_number == 2) + Serial.print("1) "); + if (packet_number == 1) + Serial.print("RESULT "); + for (int bt = 0; bt < READ_BITS; bt++) + { + if ((ver == 3 && bt <= read_tacts) || (ver == 2 && bt <= read_tacts / 2)) + { + if (collect_data[bt] > 128 + 1) + Serial.print('I'); + if (collect_data[bt] < 128 - 1) + Serial.print('O'); + if (collect_data[bt] == 128 + 1) + Serial.print('i'); + if (collect_data[bt] == 128 - 1) + Serial.print('o'); + if (collect_data[bt] == 128) + Serial.print('.'); + if (receiver_dump) + Serial.print(" "); } - else Serial.print(' '); + else + Serial.print(' '); } - Serial.print(" OSV:"); - Serial.print(ver); - Serial.print(" SYN:"); - if (synchro_pos < 255) + Serial.print(" OSV:"); + Serial.print(ver); + Serial.print(" SYN:"); + if (synchro_pos < 255) Serial.print(synchro_pos); - else Serial.print("NO"); - Serial.print(" TIME:"); - Serial.println (millis() / 1000); + else + Serial.print("NO"); + Serial.print(" TIME:"); + Serial.println(millis() / 1000); } ////////////////////////////////////////////// - // - if (packet_number == 2){ + //Аналогично обрабатываем вторую запись + if (packet_number == 2) + { get_tacts(collect_data2, read_tacts2); - if (get_data(0, ver, collect_data2) > get_data(1, ver, collect_data2)) { + if (get_data(0, ver, collect_data2) > get_data(1, ver, collect_data2)) + { data_val2 = get_data(0, ver, collect_data2); halfshift = 0; } - else { + else + { data_val2 = get_data(1, ver, collect_data2); halfshift = 1; } synchro_pos2 = get_synchro_pos(collect_data2); - if (DEBUG_INFO){ + if (DEBUG_INFO) + { Serial.print("2) "); - for(int bt = 0; bt < READ_BITS; bt++) { - if (bt <= read_tacts2 / 2){ - if (collect_data2[bt] > 128 + 1) Serial.print('I'); - if (collect_data2[bt] < 128 - 1) Serial.print('O'); - if (collect_data2[bt] == 128 + 1) Serial.print('i'); - if (collect_data2[bt] == 128 - 1) Serial.print('o'); - if (collect_data2[bt] == 128) Serial.print('.'); - if (receiver_dump) Serial.print(" "); + for (int bt = 0; bt < READ_BITS; bt++) + { + if (bt <= read_tacts2 / 2) + { + if (collect_data2[bt] > 128 + 1) + Serial.print('I'); + if (collect_data2[bt] < 128 - 1) + Serial.print('O'); + if (collect_data2[bt] == 128 + 1) + Serial.print('i'); + if (collect_data2[bt] == 128 - 1) + Serial.print('o'); + if (collect_data2[bt] == 128) + Serial.print('.'); + if (receiver_dump) + Serial.print(" "); + } + else + Serial.print(' '); } - else Serial.print(' '); - } Serial.print(" OSV:"); Serial.print(ver); Serial.print(" SYN:"); - if (synchro_pos2 < 255) + if (synchro_pos2 < 255) Serial.print(synchro_pos2); else - Serial.print("NO");; - } + Serial.print("NO"); + ; } - byte* result_data, result_data_start, aux_data; - int correlation; - - + } + byte *result_data, result_data_start, aux_data; + int correlation; + ////////////////////////////////////////////// + //СОПОСТАВЛЕНИЕ ПАКЕТОВ + //Если пакет один, то и сопоставлять не из чего + if (packet_number == 1) + result_data = collect_data; + ////////////////////////////////////////////// + //А вот если два, то нужна СБОРКА ПАКЕТА + //вычисляем оптимальное "смещение" пакетов друг относительно друга + if (packet_number == 2) + { + correlation = correlate_data(collect_data, collect_data2); + if (DEBUG_INFO) + { + Serial.print(" COR: "); + Serial.println(correlation); + } + ////////////////////////////////////////////// + //Собираем данные в пакет, где синхронибл найден раньше ////////////////////////////////////////////// - // - // , - if (packet_number == 1) result_data = collect_data; - ////////////////////////////////////////////// - // , - // "" - if (packet_number == 2) { - correlation = correlate_data(collect_data, collect_data2); - if (DEBUG_INFO){ - Serial.print(" COR: "); - Serial.println(correlation); - } - ////////////////////////////////////////////// - // , - ////////////////////////////////////////////// - if (synchro_pos >= synchro_pos2) - { - result_size = read_tacts2; - result_data = collect_data2; - correlation = -correlation; - assemble_data(collect_data2, collect_data, correlation); - } - else - { - result_size = read_tacts; - result_data = collect_data; - assemble_data(collect_data, collect_data2, correlation); - } + if (synchro_pos >= synchro_pos2) + { + result_size = read_tacts2; + result_data = collect_data2; + correlation = -correlation; + assemble_data(collect_data2, collect_data, correlation); + } + else + { + result_size = read_tacts; + result_data = collect_data; + assemble_data(collect_data, collect_data2, correlation); } + } ////////////////////////////////////////////// - // - if (DEBUG_INFO && packet_number == 2){ + //Вывод готовой посылки + if (DEBUG_INFO && packet_number == 2) + { Serial.print("RESULT "); - byte* rdt = result_data; - for(int bt = 0; bt < READ_BITS; bt++){ - if (bt <= result_size / 2){ - if (*rdt > 128 + 1) Serial.print('I'); - if (*rdt < 128 - 1) Serial.print('O'); - if (*rdt == 128 + 1) Serial.print('i'); - if (*rdt == 128 - 1) Serial.print('o'); - if (*rdt == 128) Serial.print('.'); - if (receiver_dump) Serial.print(" "); + byte *rdt = result_data; + for (int bt = 0; bt < READ_BITS; bt++) + { + if (bt <= result_size / 2) + { + if (*rdt > 128 + 1) + Serial.print('I'); + if (*rdt < 128 - 1) + Serial.print('O'); + if (*rdt == 128 + 1) + Serial.print('i'); + if (*rdt == 128 - 1) + Serial.print('o'); + if (*rdt == 128) + Serial.print('.'); + if (receiver_dump) + Serial.print(" "); } - else Serial.print(' '); - rdt++; + else + Serial.print(' '); + rdt++; } Serial.println(" "); } - - - //, - - . , + //Проверяем, дало ли что-нибудь сращивание - отключил. Это даёт всего лишь флаг, но занимает много времени ////////////////////////////////////////////// - // if (get_data(halfshift, ver, result_data) > data_val && get_data(halfshift, ver, result_data) > data_val2 && ver == 2) -// restore_sign ^= 8; + // 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; + 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; + 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; #if ADD_SENS_SUPPORT == 1 - sens_tmp2 = 404; - sens_CO = 255; - sens_CH = 255; - sens_pressure = 0; - sens_voltage = 0; - sens_current = 0; - sens_ip22 = 0; - sens_ip72 = 0; - sens_lockalarm = 0; - sens_pump_count = 0; - sens_capacitance = 0; - sens_drop_counter = 0; + sens_tmp2 = 404; + sens_CO = 255; + sens_CH = 255; + sens_pressure = 0; + sens_voltage = 0; + sens_current = 0; + sens_ip22 = 0; + sens_ip72 = 0; + sens_lockalarm = 0; + sens_pump_count = 0; + sens_capacitance = 0; + sens_drop_counter = 0; #endif sens_id = 0; sens_chnl = 0; @@ -491,70 +549,76 @@ 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 == 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) + if (sens_type == THGN132 || (sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810) sens_hmdty = get_humidity(packet); - else sens_hmdty = 0; + else + sens_hmdty = 0; } - if (sens_type == WGR800 && crc_c){ + if (sens_type == WGR800 && crc_c) + { sens_id = get_id(packet); sens_battery = get_battery(packet); 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){ + if (sens_type == UVN800 && crc_c) + { sens_id = get_id(packet); sens_battery = get_battery(packet); UV_index = get_UV(packet); lightness = get_light(packet); -} - - - + } #if ADD_SENS_SUPPORT == 1 -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - if ((sens_type & 0xFF00) == GAS && crc_c){ + ////////////////////////////////////////////////////////////////////////////////////////////////// + //Расшифровка комплексных газовых датчиков + //////////////////////////////////////////////////////////////////////////////////////////////////// + if ((sens_type & 0xFF00) == GAS && crc_c) + { sens_id = 0; sens_battery = 0; sens_chnl = get_gas_channel(packet); sens_tmp = get_gas_temperature_out(packet); - if (packet[9] == 0x0F) sens_tmp = 404; + if (packet[9] == 0x0F) + sens_tmp = 404; sens_tmp2 = get_gas_temperature_in(packet); - if (packet[12] == 0x0F) sens_tmp2 = 404; + if (packet[12] == 0x0F) + sens_tmp2 = 404; sens_hmdty = get_gas_hmdty(packet); sens_CO = get_gas_CO(packet); sens_CH = get_gas_CH(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - if ((sens_type & 0xFF00) == FIRE && crc_c){ + ////////////////////////////////////////////////////////////////////////////////////////////////// + //Расшифровка датчиков пожарной сигнализации + //////////////////////////////////////////////////////////////////////////////////////////////////// + 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 -//////////////////////////////////////////////////////////////////////////////////////////////////// - if ((sens_type & 0xFF00) == THP && crc_c){ + ////////////////////////////////////////////////////////////////////////////////////////////////// + //Расшифровка датчиков THP + //////////////////////////////////////////////////////////////////////////////////////////////////// + if ((sens_type & 0xFF00) == THP && crc_c) + { sens_chnl = get_gas_channel(packet); sens_voltage = get_thp_voltage(packet); sens_tmp = get_thp_temperature(packet); @@ -562,539 +626,641 @@ void Oregon_NR::capture(bool DEBUG_INFO) sens_pressure = get_thp_pressure(packet); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - if ((sens_type & 0xFF00) == CURRENT && crc_c){ + ////////////////////////////////////////////////////////////////////////////////////////////////// + //Расшифровка датчиков тока и напряжения + //////////////////////////////////////////////////////////////////////////////////////////////////// + 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){ + ////////////////////////////////////////////////////////////////////////////////////////////////// + //Расшифровка датчиков осадков емкостного типа + //////////////////////////////////////////////////////////////////////////////////////////////////// + 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++; + 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 - +//Извлекает из записи тактовую последовательности +//Параметры: cdptr - указатель на записанную тактовую последовательность //////////////////////////////////////////////////////////////////////////////////////////////////// -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++) +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++) { - if (ver == 2) + if (ver == 2) { - if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x03) decode_tacts[bt] = 1; // 11 ( 87, 3 58 84) - if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) decode_tacts[bt] = 0; // 00 ( 00, 3 30 03) - if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 4; // 01 ( 07, 3 34) - if ((*cdp & 0xf0) > 0x40 && (*cdp & 0x0f) < 0x02) decode_tacts[bt] = 3; // 10 ( 70, 3 43) - // if ((*cdp & 0xf0) > 0x50 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 1; // 11 ( 87, 3 58 84) - // if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x03) decode_tacts[bt] = 0; // 00 ( 00, 3 30 03) - // if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 4; // 01 ( 07, 3 34) - // if ((*cdp & 0xf0) > 0x40 && (*cdp & 0x0f) < 0x03) decode_tacts[bt] = 3; // 10 ( 70, 3 43) + if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x03) + decode_tacts[bt] = 1; // Такт 11 (В ИДЕАЛЕ 87, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 58 ДА 84) + if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) + decode_tacts[bt] = 0; // Такт 00 (В ИДЕАЛЕ 00, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 30 ДА 03) + if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x04) + decode_tacts[bt] = 4; // Такт 01 (В ИДЕАЛЕ 07, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 34) + if ((*cdp & 0xf0) > 0x40 && (*cdp & 0x0f) < 0x02) + decode_tacts[bt] = 3; // Такт 10 (В ИДЕАЛЕ 70, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 43) + // if ((*cdp & 0xf0) > 0x50 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 1; // Такт 11 (В ИДЕАЛЕ 87, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 58 А 84) + // if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x03) decode_tacts[bt] = 0; // Такт 00 (В ИДЕАЛЕ 00, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 30 ДА 03) + // if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 4; // Такт 01 (В ИДЕАЛЕ 07, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 34) + // if ((*cdp & 0xf0) > 0x40 && (*cdp & 0x0f) < 0x03) decode_tacts[bt] = 3; // Такт 10 (В ИДЕАЛЕ 70, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 43) } - if (ver == 3) + if (ver == 3) { - if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x04) decode_tacts[bt] = 1; // 11 ( 87, 3 58 84) - if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) decode_tacts[bt] = 0; // 00 ( 00, 3 30 03) - if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x02) decode_tacts[bt] = 4; // 01 ( 07, 3 34) - if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) < 0x02) decode_tacts[bt] = 3; // 10 ( 70, 3 43) + if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) > 0x04) + decode_tacts[bt] = 1; // Такт 11 (В ИДЕАЛЕ 87, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 58 ДА 84) + if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) + decode_tacts[bt] = 0; // Такт 00 (В ИДЕАЛЕ 00, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ОТ 30 ДА 03) + if ((*cdp & 0xf0) < 0x20 && (*cdp & 0x0f) > 0x02) + decode_tacts[bt] = 4; // Такт 01 (В ИДЕАЛЕ 07, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 34) + if ((*cdp & 0xf0) > 0x20 && (*cdp & 0x0f) < 0x02) + decode_tacts[bt] = 3; // Такт 10 (В ИДЕАЛЕ 70, НО ИЗ ЗА СДВИГА НА 3 ТАКТА МОЖЕТ БЫТЬ ДО 43) } - *cdp++; + *cdp++; } -// - if (receiver_dump) - { - byte* cdp = cdptr; - Serial.print("BEFORE "); - + // Печать расшифорвки + if (receiver_dump) + { + byte *cdp = cdptr; + Serial.print("BEFORE "); - for(int bt = 0 ; bt < bitsize; bt++) + 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(" "); - *cdp++; + 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(); } - Serial.println(); - } + // Расшифровали всё, что смогли с ходу + //Проверяем допустима ли тактовая последовательность -// , -// - - for(int bt = 1; bt < bitsize; bt++) + for (int bt = 1; bt < bitsize; bt++) { -// if (decode_tacts[bt] == 2) + // if (decode_tacts[bt] == 2) { - //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 - - if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt] == 1 || decode_tacts[bt] == 3)) decode_tacts[bt] = 2; + //Х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 - недопустима + 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++) + //Восстановление одиночных тактов + for (int bt = 1; bt < (bitsize - 1); bt++) { if (decode_tacts[bt] == 2) { - //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)) { + //Х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 - if ((decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3) && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ + //Х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 - if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt + 1] == 0 || decode_tacts[bt + 1] == 4)){ + } + //Х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 - if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ + //Х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; } } } - // - cdp = cdptr; - for(int bt = 1 ; bt < (bitsize - 1); bt++) - { - if (decode_tacts[bt] == 2) - { - //0 _0 - //0 10 - if ((*cdp & 0x0f) < 0x05 && (decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3)){ - decode_tacts[bt] = 3; + //восстановление потерянных полутактов + cdp = cdptr; + for (int bt = 1; bt < (bitsize - 1); bt++) + { + if (decode_tacts[bt] == 2) + { + //Х0 _0 + //Х0 10 + if ((*cdp & 0x0f) < 0x05 && (decode_tacts[bt - 1] == 0 || decode_tacts[bt - 1] == 3)) + { + decode_tacts[bt] = 3; restore_sign ^= 1; - } - //1 _1 - //1 01 - if ((*cdp & 0x0f) > 0x04 && (decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4)){ - decode_tacts[bt] = 4; + } + //Х1 _1 + //Х1 01 + if ((*cdp & 0x0f) > 0x04 && (decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 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; + if ((*cdp & 0xF0) < 0x50 && (decode_tacts[bt + 1] == 0 || decode_tacts[bt + 1] == 4)) + { + decode_tacts[bt] = 4; restore_sign ^= 1; - } - //1_ 1X + } + //1_ 1X //10 1X - if ((*cdp & 0xF0) > 0x40 && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)){ - decode_tacts[bt] = 3; + if ((*cdp & 0xF0) > 0x40 && (decode_tacts[bt + 1] == 1 || decode_tacts[bt + 1] == 3)) + { + decode_tacts[bt] = 3; restore_sign ^= 1; - } + } } - *cdp++; + *cdp++; } - // , - :) + //Снова проверяем допустима ли тактовая последовательность, а то что мы там воссановили - неизвестно :) - for(int bt = 1; bt < bitsize; bt++) + for (int bt = 1; bt < bitsize; bt++) { { - //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 - - if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt] == 1 || decode_tacts[bt] == 3)) decode_tacts[bt] = 2; + //Х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 - недопустима + if ((decode_tacts[bt - 1] == 1 || decode_tacts[bt - 1] == 4) && (decode_tacts[bt] == 1 || decode_tacts[bt] == 3)) + decode_tacts[bt] = 2; } - *cdp++; + *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){ - ver = 2; - restore_sign ^=4; + 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) + { + ver = 2; + restore_sign ^= 4; } //110011001100 -> v2 - if (decode_tacts[0] == 1 && decode_tacts[1] == 0 && decode_tacts[2] == 1 && decode_tacts[3] == 0 && decode_tacts[4] == 1 && decode_tacts[5] == 0 && ver == 3){ - ver = 2; - restore_sign ^=4; + if (decode_tacts[0] == 1 && decode_tacts[1] == 0 && decode_tacts[2] == 1 && decode_tacts[3] == 0 && decode_tacts[4] == 1 && decode_tacts[5] == 0 && ver == 3) + { + ver = 2; + restore_sign ^= 4; } //010101010101 -> v3 - if (decode_tacts[0] == 4 && decode_tacts[1] == 4 && decode_tacts[2] == 4 && decode_tacts[3] == 4 && decode_tacts[4] == 4 && decode_tacts[5] == 4 && ver == 2){ - ver = 3; - restore_sign ^=4; + if (decode_tacts[0] == 4 && decode_tacts[1] == 4 && decode_tacts[2] == 4 && decode_tacts[3] == 4 && decode_tacts[4] == 4 && decode_tacts[5] == 4 && ver == 2) + { + ver = 3; + restore_sign ^= 4; } //101010101010 -> v3 - if (decode_tacts[0] == 3 && decode_tacts[1] == 3 && decode_tacts[2] == 3 && decode_tacts[3] == 3 && decode_tacts[4] == 3 && decode_tacts[5] == 3 && ver == 2){ - ver = 3; - restore_sign ^=4; + if (decode_tacts[0] == 3 && decode_tacts[1] == 3 && decode_tacts[2] == 3 && decode_tacts[3] == 3 && decode_tacts[4] == 3 && decode_tacts[5] == 3 && ver == 2) + { + ver = 3; + restore_sign ^= 4; } -// - if (receiver_dump) - { - 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(" "); - *cdp++; + // Печать расшифорвки + if (receiver_dump) + { + 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(" "); + *cdp++; + } + Serial.println(); } - Serial.println(); - } - 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 - , - - byte* cdp = cdptr; -// - for(int bt=0 ; bt(129)) packet_validity += *cdp - 128; - if (*cdp<(127)) packet_validity += 128 - *cdp; + if (p_ver == 2) + { + for (int bt = 1; bt < READ_BITS; bt++) + { + + if (decode_tacts[bt * 2 - btt] == 0) + *cdp -= 1; // Если 00 - то возможно здесь 0 + //if(decode_tacts[bt*2-btt]==0) *cdp-=1; // начальный вес 1 отбрасывает датчики со сбитой синхронизацией. 2 - ловит с ними + if (decode_tacts[bt * 2 - btt] == 1) + *cdp += 1; // Если 11 - то предположительно здесь 1 + if (decode_tacts[bt * 2 - 2 - btt] == 1 && decode_tacts[bt * 2 - 1 - btt] == 4) + *cdp -= 1; //Если до этого было уверенно 1101 - то это добавляет уверенности, что здесь 0 + if (decode_tacts[bt * 2 - 2 - btt] == 0 && decode_tacts[bt * 2 - 1 - btt] == 3) + *cdp += 1; + if (decode_tacts[bt * 2 - 2 - btt] == 0 && decode_tacts[bt * 2 - 1 - btt] == 1) + *cdp -= 1; + if (decode_tacts[bt * 2 - 2 - btt] == 1 && decode_tacts[bt * 2 - 1 - btt] == 0) + *cdp += 1; + + if (decode_tacts[bt * 2 + 2 - btt] == 1 && decode_tacts[bt * 2 + 1 - btt] == 3) + *cdp -= 1; // Если после этого идёт 1011 - то это добавляет уверенности, что здесь 0 + if (decode_tacts[bt * 2 + 2 - btt] == 0 && decode_tacts[bt * 2 + 1 - btt] == 4) + *cdp += 1; + if (decode_tacts[bt * 2 + 2 - btt] == 0 && decode_tacts[bt * 2 + 1 - btt] == 1) + *cdp -= 1; + if (decode_tacts[bt * 2 + 2 - btt] == 1 && decode_tacts[bt * 2 + 1 - btt] == 0) + *cdp += 1; + + //Подсчитываем кол-во достоверных бит в пакете + if (*cdp > (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 (p_ver == 3) + { + for (int bt = 1; bt < READ_BITS; bt++) + { + + 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 - { - //1 __ __ 0 0 __ __ 1- - if (*(cdp - 2) > 128) *cdp -= 1; - if (*(cdp - 2) < 128) *cdp += 1; - } + { + if (*(cdp - 2) > 128) + *cdp += 1; + if (*(cdp - 2) < 128) + *cdp -= 1; + } + else + { + //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 - { - //1 __ __ 0 0 __ __ 1- - if (*(cdp - 2) > 128) *cdp -= 1; - if (*(cdp - 2) < 128) *cdp += 1; - } + { + if (*(cdp - 2) > 128) + *cdp += 1; + if (*(cdp - 2) < 128) + *cdp -= 1; + } + else + { + //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 - { - //1 __ __ 0 0 __ __ 1- - if (*(cdp - 2) > 128) *cdp -= 1; - if (*(cdp - 2) < 128) *cdp += 1; - } + { + if (*(cdp - 2) > 128) + *cdp += 1; + if (*(cdp - 2) < 128) + *cdp -= 1; + } + else + { + //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; + //Подсчитываем кол-во достоверных бит в пакете + 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){ - +int Oregon_NR::collect(byte *cdptr) +{ + bool cdp_prev_null; - byte* cdp = cdptr; + 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; // + while (micros() < pre_marker) + ; + if (digitalRead(RECEIVER_PIN)) + *cdp += 0x10; // Измерения запиываем в старший полубайт } - for (byte ckl = 0; ckl < 8; ckl++) { + for (byte ckl = 0; ckl < 8; ckl++) + { pre_marker += 61; - while (micros() < pre_marker); - if (digitalRead(RECEIVER_PIN)) *cdp += 1; // . . - + while (micros() < pre_marker) + ; + if (digitalRead(RECEIVER_PIN)) + *cdp += 1; // В следующий полутакт измерения запиываем в младший полубайт. Это экономит память. } bt2++; - // 976.5625 - // 7 4 976 976.5714 + 0.009% - if (bt2 == 7) - { - pre_marker += (4 + timing_correction) ; + // Идеальный период 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; + if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05) + nulls_found++; + else + nulls_found = 0; cdp++; ///////////////////////////////////////////// - // empty_space , - // . - //empty_space - , - // , - // , - if (nulls_found > empty_space ) return bt; + //Если более empty_space пустых полей в записи, то + //это вероятнее всего конец посылки. Дальше читать нет смысла + //empty_space - число эмпирическое, зависит от типа приёмника и уровня сигнала + //Если уменьшить, возможно спутать с повреждением пакета + //Если увеличить, то можно не прекратить чтение и начать записывать помехи + if (nulls_found > empty_space) + return bt; ///////////////////////////////////////////// - // - while (micros() < pre_marker); + //Ждём прихода времени следующего полутакта + while (micros() < pre_marker) + ; } return bt; -} +} //////////////////////////////////////////////////////////////////////////////////////////////////// -// -// -// -// >0 - , <0 - +//Определение смещения пакетов друг относительно друга +//В качестве параметров передаются указатели на массивы данных +// Возваращаяется смещение +// >0 - второй пакет начался раньше, <0 - Первый пакет начался раньше //////////////////////////////////////////////////////////////////////////////////////////////////// -int Oregon_NR::correlate_data(byte* ser1, byte* ser2){ - +int Oregon_NR::correlate_data(byte *ser1, byte *ser2) +{ + byte best_correl = 0; int best_shift = 0; byte best_correl_back = 0; int best_shift_back = 0; byte shift_score[READ_BITS]; - byte* s1; - byte* s2; - byte* s2t = ser2; - // - for (byte sht = 0; sht < READ_BITS; sht++){ + byte *s1; + byte *s2; + byte *s2t = ser2; + //смещаем первый пакет относительно второго + for (byte sht = 0; sht < READ_BITS; sht++) + { s1 = ser1; s2 = s2t; 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]++; + 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++; } yield(); s2t++; } - for (int i = 0; i < READ_BITS; i++){ + for (int i = 0; i < READ_BITS; i++) + { - if (shift_score[i] > best_correl){ + if (shift_score[i] > best_correl) + { best_correl = shift_score[i]; best_shift = i; } } - -// - - - byte* s1t = ser1; - for (byte sht = 0; sht < READ_BITS; sht++){ + + //Теперь наоборот -втрой пакет относительно первого + + 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]++; + 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++; } yield(); s1t++; } -// - - for (int i = 0; i < READ_BITS; i++){ - - if (shift_score[i] > best_correl_back){ + // Ищем наилучшее совпадение для обоих вариантов + + 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; + //И возвращаем самое лучшее из двух + 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++){ - if(*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) { - *s1 = *s2; +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++) + { + if (*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) + { + *s1 = *s2; } s1++; s2++; } } - else { - for (int g = 0; g < -shift; g++) s1++; - for (int i = 0; i < READ_BITS + shift; i++){ - if(*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) { - *s1 = *s2; + else + { + for (int g = 0; g < -shift; g++) + s1++; + for (int i = 0; i < READ_BITS + shift; i++) + { + if (*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) + { + *s1 = *s2; } s1++; s2++; @@ -1102,52 +1268,61 @@ 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){ - +int Oregon_NR::get_synchro_pos(byte *code) +{ + bool syn_found = false; - byte* cp = code; + byte *cp = code; int i = 0; - for (i = 0; i < READ_BITS - 8; i++){ - if (!consist_synchro && (*cp < 128 && *(cp + 1) > 128 && *(cp + 2) < 128 && *(cp + 3) > 128)) { + for (i = 0; i < READ_BITS - 8; i++) + { + if (!consist_synchro && (*cp < 128 && *(cp + 1) > 128 && *(cp + 2) < 128 && *(cp + 3) > 128)) + { syn_found = true; break; } - if (consist_synchro && (*cp < 127 && *(cp + 1) > 129 && *(cp + 2) < 127 && *(cp + 3) > 129)) { + if (consist_synchro && (*cp < 127 && *(cp + 1) > 129 && *(cp + 2) < 127 && *(cp + 3) > 129)) + { syn_found = true; break; } - + cp++; } - if (!syn_found) return 0xFF; - // , , , . . - // ! - - // 16-3 = 13 . 10!!! - - for (byte g = i; i - g < 10 && g > 0; g --){ - cp --; - if (*cp < 127) return 0xFF; // . ! + if (!syn_found) + return 0xFF; + //Последовательность нашли, но надо убедиться, что перед этим идёт перамбула, т. е. уверенные единицы + // В преамбуле не может быть нулей! - это главное + //Преамбулу надо просматривать на 16-3 = 13 битов назад. Ну хотя бы на 10!!! + + for (byte g = i; i - g < 10 && g > 0; g--) + { + cp--; + if (*cp < 127) + return 0xFF; // Перед синхрониблом в преамбуле не может быть уверенного нуля. Нет тут синхронибла! } - return (byte) i; + return (byte)i; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//code - -//result - -//valid - +//Создаёт кодовую посылку +//code - указатель на расшифрованную битовую последовательность +//result - указатель на кодовую посылку +//valid - указатель на карту достоверности кодовой посылки //////////////////////////////////////////////////////////////////////////////////////////////////// -int Oregon_NR::get_info_data(byte* code, byte* result, byte* 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++){ + byte *rd = result; + byte *vd = valid; + //Чистим массивы + for (int l = 0; l < PACKET_LENGTH; l++) + { *vd = 0; *rd = 0; vd++; @@ -1155,40 +1330,66 @@ 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; + 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; 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; + // Чтобы не выйти за пределы + if (i >= PACKET_LENGTH * 4) + break; byte multipl; - switch (ii){ - case 0: {multipl = 0x01; break;} - case 1: {multipl = 0x02; break;} - case 2: {multipl = 0x04; break;} - case 3: {multipl = 0x08; break;} + switch (ii) + { + case 0: + { + multipl = 0x01; + break; + } + case 1: + { + multipl = 0x02; + break; + } + case 2: + { + multipl = 0x04; + break; + } + case 3: + { + multipl = 0x08; + break; + } } - if (*code > 128 ) { + if (*code > 128) + { *rd += multipl; *vd += multipl; } - if (*code < 128 ) *vd += multipl; - code ++; - ii ++; - if (ii == 4) { + if (*code < 128) + *vd += multipl; + code++; + ii++; + if (ii == 4) + { ii = 0; vd++; rd++; @@ -1198,383 +1399,463 @@ int Oregon_NR::get_info_data(byte* code, byte* result, byte* valid){ } // //////////////////////////////////////////////////////////////////////////////////////////////////// -// +//Функции расшифровки данных с датчиков //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает значение температуры +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_temperature(byte* 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; + //исправляем возможные ошибки: + 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; + // else return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// . -//oregon_data - +//Возвращает тип сенсора. +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -word Oregon_NR::get_sensor(byte* 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); + 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){ +byte Oregon_NR::get_channel(byte *oregon_data) +{ if (crc_c) { - byte channel = 0; -// word sens_type = get_sensor(oregon_data); - if (sens_type == THGN132 || sens_type == THN132 ) + 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 == THGR810) + channel = *(oregon_data + 4); + return channel; } - else return 0; + 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; +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; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает значение влажности +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_humidity(byte* oregon_data){ +float Oregon_NR::get_humidity(byte *oregon_data) +{ - if (((sens_type & 0x0FFF) == RTGN318 || sens_type == THGR810 || sens_type == THGN132) && crc_c ){ + 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; + //исправляем возможные ошибки: + 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; + 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 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)*0x10; tmprt += *(oregon_data + 1); return tmprt; } - else return 0; + else + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// /c -//oregon_data - +//Возвращает среднее значение ветра в м/c +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_avg_windspeed(byte* oregon_data) +float Oregon_NR::get_avg_windspeed(byte *oregon_data) { - if (sens_type == WGR800 && crc_c){ + if (sens_type == WGR800 && crc_c) + { float tmprt; tmprt = *(oregon_data + 15) * 0x10; tmprt += *(oregon_data + 14); return tmprt / 10; } - else return 0; + else + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// /c -//oregon_data - +//Возвращает начение максимального порыва ветра в м/c +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_max_windspeed(byte* oregon_data) +float Oregon_NR::get_max_windspeed(byte *oregon_data) { - if (sens_type == WGR800 && crc_c){ + if (sens_type == WGR800 && crc_c) + { float tmprt; tmprt = *(oregon_data + 12) * 0x10; tmprt += *(oregon_data + 11); return tmprt / 10; } - else return 0; + else + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает направление ветра в квадрантах +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_winddirection(byte* oregon_data) +byte Oregon_NR::get_winddirection(byte *oregon_data) { - if (sens_type == WGR800 && crc_c){ + 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; + else + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// UV- -//oregon_data - +//Возвращает UV-индекс +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_UV(byte* oregon_data) +byte Oregon_NR::get_UV(byte *oregon_data) { - if (sens_type == UVN800 && crc_c){ + if (sens_type == UVN800 && crc_c) + { byte tmprt; tmprt = *(oregon_data + 9) * 0x10; tmprt += *(oregon_data + 8); return tmprt; } - else return 0; + else + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// -// -//oregon_data - +//Возвращает освещённость в условных единицах +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_light(byte* oregon_data) +byte Oregon_NR::get_light(byte *oregon_data) { - if (sens_type == UVN800 && crc_c){ + if (sens_type == UVN800 && crc_c) + { byte tmprt; tmprt = *(oregon_data + 11) * 0x10; tmprt += *(oregon_data + 10); tmprt -= 0x6F; return tmprt; } - else return 0; + else + return 0; } - //////////////////////////////////////////////////////////////////////////////////////////////////// -// CRC -//oregon_data - +//Проверка CRC +//oregon_data - указатель на кодовую посылку //////////////////////////////////////////////////////////////////////////////////////////////////// -bool Oregon_NR::check_CRC(byte* oregon_data, word sens_type){ +bool Oregon_NR::check_CRC(byte *oregon_data, word sens_type) +{ - byte* pp=oregon_data; + byte *pp = oregon_data; byte crc, resived_crc, truecrc, resived_truecrc, i; - crc=0; + crc = 0; byte CCIT_POLY = 0x07; - - if (sens_type==THGN132){ - //CHKSUM 1...15 - //CRC 1...5,8...15 STARTSUM = 3Ch, POLY = 07h + + if (sens_type == THGN132) + { + //CHKSUM 1...15 + //CRC 1...5,8...15 STARTSUM = 3Ch, POLY = 07h truecrc = 0x3C; - for(int x=0; x < 15; x++){ + for (int x = 0; x < 15; x++) + { crc += *pp; - if ( x != 5 && x != 6){ + if (x != 5 && x != 6) + { truecrc ^= *pp; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; + 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++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+15))+(*(oregon_data+16))*0x10; - resived_truecrc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 15)) + (*(oregon_data + 16)) * 0x10; + resived_truecrc = (*(oregon_data + 17)) + (*(oregon_data + 18)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } - if ((sens_type & 0x0FFF) == RTGN318){ - //CHKSUM 1...15 - //CRC 1...5,8...15 STARTSUM = 00h, POLY = 07h + if ((sens_type & 0x0FFF) == RTGN318) + { + //CHKSUM 1...15 + //CRC 1...5,8...15 STARTSUM = 00h, POLY = 07h truecrc = 0x0; - for(int x=0; x<15; x++){ + for (int x = 0; x < 15; x++) + { crc += *pp; - if ( x != 5 && x != 6){ + if (x != 5 && x != 6) + { truecrc ^= *pp; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; + 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++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+15))+(*(oregon_data+16))*0x10; - resived_truecrc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 15)) + (*(oregon_data + 16)) * 0x10; + resived_truecrc = (*(oregon_data + 17)) + (*(oregon_data + 18)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } - if (sens_type == THGR810){ - //CHKSUM 1...15 - //CRC 00h,1...15 STARTSUM = 00h, POLY = 07h + if (sens_type == THGR810) + { + //CHKSUM 1...15 + //CRC 00h,1...15 STARTSUM = 00h, POLY = 07h truecrc = 0x0; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - for(int x=0; x<15; x++){ + 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++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - pp++; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + pp++; } - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+15))+(*(oregon_data+16))*0x10; - resived_truecrc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 15)) + (*(oregon_data + 16)) * 0x10; + resived_truecrc = (*(oregon_data + 17)) + (*(oregon_data + 18)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } - if (sens_type == UVN800 ){ - //CHKSUM 1...13 - //CRC 00h,1...13 STARTSUM = 00h, POLY = 07h + if (sens_type == UVN800) + { + //CHKSUM 1...13 + //CRC 00h,1...13 STARTSUM = 00h, POLY = 07h truecrc = 0x0; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - for(int x=0; x<13; x++){ + 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++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - pp++; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + pp++; } - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+13))+(*(oregon_data+14))*0x10; - resived_truecrc = (*(oregon_data+15))+(*(oregon_data+16))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 13)) + (*(oregon_data + 14)) * 0x10; + resived_truecrc = (*(oregon_data + 15)) + (*(oregon_data + 16)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } - - if (sens_type == WGR800){ - //CHKSUM 1...17 - for(int x=0; x < 17; x++){ + if (sens_type == WGR800) + { + //CHKSUM 1...17 + for (int x = 0; x < 17; x++) + { crc += *pp; - pp++; + pp++; } - resived_crc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; - return (resived_crc == crc)? 1 : 0; + resived_crc = (*(oregon_data + 17)) + (*(oregon_data + 18)) * 0x10; + return (resived_crc == crc) ? 1 : 0; } - if (sens_type==THN132){ + if (sens_type == THN132) + { - //CHKSUM 1...12 - //CRC 1...5,8...12 STARTSUM = D6h, POLY = 07h + //CHKSUM 1...12 + //CRC 1...5,8...12 STARTSUM = D6h, POLY = 07h truecrc = 0xD6; - for(int x=0; x<12; x++){ + for (int x = 0; x < 12; x++) + { crc += *pp; - if ( x != 5 && x != 6){ + if (x != 5 && x != 6) + { truecrc ^= *pp; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; + 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++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+12))+(*(oregon_data+13))*0x10; - resived_truecrc = (*(oregon_data+14))+(*(oregon_data+15))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 12)) + (*(oregon_data + 13)) * 0x10; + resived_truecrc = (*(oregon_data + 14)) + (*(oregon_data + 15)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } #ifdef ADD_SENS_SUPPORT == 1 - if ((sens_type & 0xFF00) == GAS || (sens_type & 0xFF00) == THP || (sens_type & 0xFF00) == FIRE || (sens_type & 0xFF00) == CURRENT || (sens_type & 0xFF00) == CAPRAIN){ + if ((sens_type & 0xFF00) == GAS || (sens_type & 0xFF00) == THP || (sens_type & 0xFF00) == FIRE || (sens_type & 0xFF00) == CURRENT || (sens_type & 0xFF00) == CAPRAIN) + { truecrc = 0x00; - for(int x=0; x<15; x++){ + for (int x = 0; x < 15; x++) + { crc += *pp; truecrc ^= *pp; - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - pp++; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + pp++; } - for(i = 0; i<4; i++) - if(truecrc & 0x80) truecrc = (truecrc << 1) ^ CCIT_POLY; - else truecrc <<= 1; - - resived_crc = (*(oregon_data+15))+(*(oregon_data+16))*0x10; - resived_truecrc = (*(oregon_data+17))+(*(oregon_data+18))*0x10; + for (i = 0; i < 4; i++) + if (truecrc & 0x80) + truecrc = (truecrc << 1) ^ CCIT_POLY; + else + truecrc <<= 1; + + resived_crc = (*(oregon_data + 15)) + (*(oregon_data + 16)) * 0x10; + resived_truecrc = (*(oregon_data + 17)) + (*(oregon_data + 18)) * 0x10; received_CRC = truecrc; - return (resived_crc == crc && resived_truecrc == truecrc)? 1 : 0; - + return (resived_crc == crc && resived_truecrc == truecrc) ? 1 : 0; } #endif 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++; +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++; } } - if (sens_type==THN132){ - pp+=8; - for(int x=0; x<3; x++){ - if(*pp>9) *pp-=8; - pp++; + if (sens_type == THN132) + { + pp += 8; + for (int x = 0; x < 3; x++) + { + if (*pp > 9) + *pp -= 8; + pp++; } } return; } - //////////////////////////////////////////////////////////////////////////////////////////////////// -void Oregon_NR::led_light(bool led_on) { - 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); - if (!PULL_UP && !led_on) digitalWrite(LED, LOW); +void Oregon_NR::led_light(bool led_on) +{ + 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); + if (!PULL_UP && !led_on) + digitalWrite(LED, LOW); } } @@ -1583,106 +1864,120 @@ 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){ +byte Oregon_NR::get_gas_channel(byte *gas_data) +{ return gas_data[2]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_gas_temperature_out(byte* gas_data){ +float Oregon_NR::get_gas_temperature_out(byte *gas_data) +{ int temperat = gas_data[9] * 0x0100 + gas_data[8] * 0x0010 + gas_data[7]; return ((float)(-1000 + temperat)) / 10; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_gas_temperature_in(byte* gas_data){ +float Oregon_NR::get_gas_temperature_in(byte *gas_data) +{ int temperat = gas_data[12] * 0x0100 + gas_data[11] * 0x0010 + gas_data[10]; return ((float)(-1000 + temperat)) / 10; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_gas_hmdty(byte* gas_data){ +byte Oregon_NR::get_gas_hmdty(byte *gas_data) +{ return gas_data[14] * 0x10 + gas_data[13]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_gas_CO(byte* gas_data){ +byte Oregon_NR::get_gas_CO(byte *gas_data) +{ return gas_data[6] * 0x10 + gas_data[5]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_gas_CH(byte* gas_data){ +byte Oregon_NR::get_gas_CH(byte *gas_data) +{ return gas_data[4] * 0x10 + gas_data[3]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_fire_ip22(byte* fire_data){ +byte Oregon_NR::get_fire_ip22(byte *fire_data) +{ return fire_data[4] * 0x10 + fire_data[5]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_fire_ip72(byte* fire_data){ +byte Oregon_NR::get_fire_ip72(byte *fire_data) +{ return fire_data[6] * 0x10 + fire_data[7]; } //////////////////////////////////////////////////////////////////////////////////////////////////// -byte Oregon_NR::get_fire_lockalarm(byte* fire_data){ +byte Oregon_NR::get_fire_lockalarm(byte *fire_data) +{ return fire_data[8] * 0x10 + fire_data[9]; } - //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_current(byte* current_data){ +float Oregon_NR::get_current(byte *current_data) +{ - return ((float)(current_data[4] * 0x1000 + current_data[5] * 0x0100 + current_data[6] * 0x0010 + current_data[7])) / 1000; + return ((float)(current_data[4] * 0x1000 + current_data[5] * 0x0100 + current_data[6] * 0x0010 + current_data[7])) / 1000; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_voltage(byte* voltage_data){ +float Oregon_NR::get_voltage(byte *voltage_data) +{ - return ((float)(voltage_data[8] * 0x1000 + voltage_data[9] * 0x0100 + voltage_data[10] * 0x0010 + voltage_data[11])) / 10; + return ((float)(voltage_data[8] * 0x1000 + voltage_data[9] * 0x0100 + voltage_data[10] * 0x0010 + voltage_data[11])) / 10; } -word Oregon_NR::get_pump_count(byte* voltage_data){ +word Oregon_NR::get_pump_count(byte *voltage_data) +{ - return (voltage_data[12] * 0x0100 + voltage_data[13] * 0x0010 + voltage_data[14]); + return (voltage_data[12] * 0x0100 + voltage_data[13] * 0x0010 + voltage_data[14]); } -unsigned long Oregon_NR::get_dropcounter(byte* packetdata){ +unsigned long Oregon_NR::get_dropcounter(byte *packetdata) +{ - return (packetdata[10] * 0x10000 + packetdata[11] * 0x1000 + packetdata[12] * 0x100 + packetdata[13] * 0x10 + packetdata[14]); + return (packetdata[10] * 0x10000 + packetdata[11] * 0x1000 + packetdata[12] * 0x100 + packetdata[13] * 0x10 + packetdata[14]); } //////////////////////////////////////////////////////////////////////////////////////////////////// -int Oregon_NR::get_capacitance(byte* packetdata){ +int Oregon_NR::get_capacitance(byte *packetdata) +{ - return (packetdata[6] * 0x1000 + packetdata[7] * 0x100 + packetdata[8] * 0x10 + packetdata[9]); + return (packetdata[6] * 0x1000 + packetdata[7] * 0x100 + packetdata[8] * 0x10 + packetdata[9]); } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_thp_temperature(byte* current_data){ +float Oregon_NR::get_thp_temperature(byte *current_data) +{ - return (float)(current_data[3] * 0x0100 + current_data[4] * 0x0010 + current_data[5] * 0x0001) / 10 - 100; + return (float)(current_data[3] * 0x0100 + current_data[4] * 0x0010 + current_data[5] * 0x0001) / 10 - 100; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_thp_pressure(byte* current_data){ +float Oregon_NR::get_thp_pressure(byte *current_data) +{ - return (float)(current_data[9] * 0x0100 + current_data[10] * 0x0010 + current_data[11] * 0x0001) / 10 + 500; + return (float)(current_data[9] * 0x0100 + current_data[10] * 0x0010 + current_data[11] * 0x0001) / 10 + 500; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_thp_voltage(byte* current_data){ +float Oregon_NR::get_thp_voltage(byte *current_data) +{ - return (float)(current_data[12] * 0x0100 + current_data[13] * 0x0010 + current_data[14] * 0x0001) * 0.01; + return (float)(current_data[12] * 0x0100 + current_data[13] * 0x0010 + current_data[14] * 0x0001) * 0.01; } //////////////////////////////////////////////////////////////////////////////////////////////////// -float Oregon_NR::get_thp_humidity(byte* current_data){ +float Oregon_NR::get_thp_humidity(byte *current_data) +{ - return (float)(current_data[6] * 0x0100 + current_data[7] * 0x0010 + current_data[8] * 0x0001) / 10; + return (float)(current_data[6] * 0x0100 + current_data[7] * 0x0010 + current_data[8] * 0x0001) / 10; } #endif - - - diff --git a/Oregon_NR.h b/Oregon_NR.h index e058034..980368b 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: 29 June 2019 // @@ -16,7 +16,7 @@ // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -26,7 +26,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,254 +35,247 @@ // 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 // -// 29 2019 +// Последнее обновление 29 июня 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, // 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 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; class Oregon_NR { - public: - - // - word sens_type; //Sensor type - - - float sens_tmp, //Temperature - sens_hmdty; //Humidity - - byte sens_chnl, //Channel number - sens_id, //ID - sens_battery; //Battery status - - byte ver = 0; //Protocol version - - 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 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) - void start(); //Star 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; - - // - float sens_avg_ws, sens_max_ws; - byte sens_wdir; - float get_avg_windspeed(byte*); - float get_max_windspeed(byte*); - byte get_winddirection(byte*); - //UV - byte UV_index, lightness; - byte get_UV(byte*); - byte get_light(byte*); - - byte restore_sign; // , - - //0 - - //1 - - //2 - - //3 - (v2) - - - bool receiver_dump = 0; // Serial. capture(true) - // - // +public: + //Данные датчика + word sens_type; //Sensor type + + float sens_tmp, //Temperature + sens_hmdty; //Humidity + + byte sens_chnl, //Channel number + sens_id, //ID + sens_battery; //Battery status + + byte ver = 0; //Protocol version + + 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 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) + void start(); //Star 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; + + //Ветрометр + float sens_avg_ws, sens_max_ws; + byte sens_wdir; + float get_avg_windspeed(byte *); + float get_max_windspeed(byte *); + byte get_winddirection(byte *); + //UV + byte UV_index, lightness; + byte get_UV(byte *); + byte get_light(byte *); + + byte restore_sign; //Битовое поле, инормирующее об успешных способах реставрации пакета + + //0 - восстановлены одиночные такты + //1 - восстановлены двойные такты + //2 - исправление версии протокола при разборке пакета + //3 - восстановлено методом сращивания (v2) - отключено для экономии ресурсов + + bool receiver_dump = 0; //Сбрасывать ли дамп канала в Serial. работает тольок если capture(true) + // фактически это осциллограмма огибающей сигнала с приёмника + // Также выводятся тактовые последовательности до и после восстановления #if ADD_SENS_SUPPORT == 1 - float sens_pressure, //Pressure - 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_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 - - - 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], // + float sens_pressure, //Pressure + 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_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 + +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], //Память для сбора данных с приёмника #if IS_ASSEMBLE - collect_data2[READ_BITS2]; + collect_data2[READ_BITS2]; #else - collect_data2[1]; + collect_data2[1]; #endif - // , : - // 128 - - // >128 - - // <128 - - - byte receive_status = FIND_PACKET; - byte start_pulse_cnt = 0; - unsigned long pulse_length, timer_marklong; - unsigned long pulse_marker, right_pulse_marker; - unsigned long pre_marker; // - unsigned long first_packet_end; - 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); - float get_gas_temperature_in(byte* gas_data); - float get_gas_temperature_out(byte* gas_data); - byte get_gas_channel(byte* gas_data); - void restore_data(byte* oregon_data, word sensor_type); - bool check_CRC(byte* oregon_data, word sensor_type); - byte get_id(byte* oregon_data); - float get_humidity(byte* oregon_data); - byte get_battery(byte* oregon_data); - byte get_channel(byte* oregon_data); - word get_sensor(byte* oregon_data); - float get_temperature(byte* oregon_data); - int get_info_data(byte* code, byte* result, byte* valid); - void assemble_data(byte* s1, byte* s2, int shift); - int correlate_data(byte* ser1, byte* ser2); - int collect(byte* cdptr); - int get_data(int btt, byte p_ver, byte* cdptr); - void get_tacts(byte*, byte); - int get_synchro_pos(byte* code); - void led_light(bool); + //А когда становится массивом полученных битов, то значения такие: + // 128 - неизвестен + // >128 - единица + // <128 - ноль + + byte receive_status = FIND_PACKET; + byte start_pulse_cnt = 0; + unsigned long pulse_length, timer_marklong; + unsigned long pulse_marker, right_pulse_marker; + unsigned long pre_marker; // Для хранения временных меток преамбулы при захвате пакета + unsigned long first_packet_end; + 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); + float get_gas_temperature_in(byte *gas_data); + float get_gas_temperature_out(byte *gas_data); + byte get_gas_channel(byte *gas_data); + void restore_data(byte *oregon_data, word sensor_type); + bool check_CRC(byte *oregon_data, word sensor_type); + byte get_id(byte *oregon_data); + float get_humidity(byte *oregon_data); + byte get_battery(byte *oregon_data); + byte get_channel(byte *oregon_data); + word get_sensor(byte *oregon_data); + float get_temperature(byte *oregon_data); + int get_info_data(byte *code, byte *result, byte *valid); + void assemble_data(byte *s1, byte *s2, int shift); + int correlate_data(byte *ser1, byte *ser2); + int collect(byte *cdptr); + int get_data(int btt, byte p_ver, byte *cdptr); + void get_tacts(byte *, byte); + int get_synchro_pos(byte *code); + void led_light(bool); #if ADD_SENS_SUPPORT == 1 - byte get_fire_ip22(byte* fire_data); - byte get_fire_ip72(byte* fire_data); - byte get_fire_lockalarm(byte* fire_data); - float get_current(byte* curent_data); - float get_voltage(byte* voltage_data); - word get_pump_count(byte* voltage_data); - unsigned long get_dropcounter(byte* packetdata); - int get_capacitance(byte* packetdata); - float get_thp_humidity(byte* oregon_data); - float get_thp_temperature(byte* oregon_data); - float get_thp_pressure(byte* oregon_data); - float get_thp_voltage(byte* oregon_data); -#endif - + byte get_fire_ip22(byte *fire_data); + byte get_fire_ip72(byte *fire_data); + byte get_fire_lockalarm(byte *fire_data); + float get_current(byte *curent_data); + float get_voltage(byte *voltage_data); + word get_pump_count(byte *voltage_data); + unsigned long get_dropcounter(byte *packetdata); + int get_capacitance(byte *packetdata); + float get_thp_humidity(byte *oregon_data); + float get_thp_temperature(byte *oregon_data); + float get_thp_pressure(byte *oregon_data); + float get_thp_voltage(byte *oregon_data); +#endif }; #endif - diff --git a/Oregon_TM.cpp b/Oregon_TM.cpp index 89d4139..96b0c56 100644 --- a/Oregon_TM.cpp +++ b/Oregon_TM.cpp @@ -1,7 +1,7 @@ #include "Oregon_TM.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: 29 June 2019 // @@ -14,7 +14,7 @@ // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -24,7 +24,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,74 +33,71 @@ // 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 // -// 29 2019 +// Последнее обновление 29 июня 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, // THGR810. -// : +// Тольок приём: // THN132N, -// WGR800, +// WGR800, // UVN800. // -// ( ) +// Также поддерживаются датчики собственной разработки (за дополнительной документацей обращаться к автору) // -// - OREGON_NR +// Этот файл - часть библиотеки OREGON_NR ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2019 +// Copyright (c) 2019 Сергей Зависляк // -// , -// ( ), , -// , , , , , , -// / , , , : +// Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации +// (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, +// включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование +// и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: // -// . +// Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. // -// ܻ, - , , -// , , . -// - , , , , , -// - . +// ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ +// ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ +// НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, +// ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -// +//Конструктор Oregon_TM::Oregon_TM(byte tr_pin) { TX_PIN = tr_pin; - pinMode(TX_PIN, OUTPUT); + pinMode(TX_PIN, OUTPUT); digitalWrite(TX_PIN, LOW); - } Oregon_TM::Oregon_TM(void) { - pinMode(TX_PIN, OUTPUT); + pinMode(TX_PIN, OUTPUT); digitalWrite(TX_PIN, LOW); } - /////////////////////////////////////////////////////////////////////////////////////////////////// -// //////////////////////////////////////////////////////////////////////////// +// Функции передатчика//////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::sendZero(void) { - if (protocol == 2){ - while (time_marker + TR_TIME * 4 >= micros()); + if (protocol == 2) + { + while (time_marker + TR_TIME * 4 >= micros()) + ; time_marker += TR_TIME * 4; digitalWrite(TX_PIN, HIGH); delayMicroseconds(TR_TIME - PULSE_SHORTEN_2); @@ -109,18 +106,22 @@ void Oregon_TM::sendZero(void) digitalWrite(TX_PIN, HIGH); } if (protocol == 3) - { - if (prevstate) while (time_marker + TWOTR_TIME - PULSE_SHORTEN_3 >= micros()); - else while (time_marker + TWOTR_TIME >= micros()); - + { + if (prevstate) + while (time_marker + TWOTR_TIME - PULSE_SHORTEN_3 >= micros()) + ; + else + while (time_marker + TWOTR_TIME >= micros()) + ; + time_marker += TWOTR_TIME; - + if (prevbit && prevstate) { digitalWrite(TX_PIN, LOW); prevstate = 0; prevbit = 0; - return; + return; } if (prevbit && !prevstate) { @@ -128,7 +129,7 @@ void Oregon_TM::sendZero(void) delayMicroseconds(TWOTR_TIME); prevstate = 1; prevbit = 0; - return; + return; } if (!prevbit && prevstate) { @@ -136,7 +137,7 @@ void Oregon_TM::sendZero(void) delayMicroseconds(TR_TIME); digitalWrite(TX_PIN, HIGH); prevbit = 0; - return; + return; } if (!prevbit && !prevstate) { @@ -144,7 +145,7 @@ void Oregon_TM::sendZero(void) delayMicroseconds(TR_TIME); digitalWrite(TX_PIN, LOW); prevbit = 0; - return; + return; } } } @@ -152,8 +153,10 @@ void Oregon_TM::sendZero(void) void Oregon_TM::sendOne(void) { - if (protocol == 2){ - while (time_marker + TR_TIME * 4 - PULSE_SHORTEN_2>= micros()); + if (protocol == 2) + { + while (time_marker + TR_TIME * 4 - PULSE_SHORTEN_2 >= micros()) + ; time_marker += TR_TIME * 4; digitalWrite(TX_PIN, LOW); delayMicroseconds(TR_TIME + PULSE_SHORTEN_2); @@ -161,13 +164,17 @@ void Oregon_TM::sendOne(void) delayMicroseconds(TWOTR_TIME - PULSE_SHORTEN_2); digitalWrite(TX_PIN, LOW); } - + if (protocol == 3) { - if (prevstate) while (time_marker + TWOTR_TIME - PULSE_SHORTEN_3 >= micros()); - else while (time_marker + TWOTR_TIME >= micros()); + if (prevstate) + while (time_marker + TWOTR_TIME - PULSE_SHORTEN_3 >= micros()) + ; + else + while (time_marker + TWOTR_TIME >= micros()) + ; time_marker += TWOTR_TIME; - + if (!prevbit && prevstate) { digitalWrite(TX_PIN, LOW); @@ -180,7 +187,7 @@ void Oregon_TM::sendOne(void) digitalWrite(TX_PIN, HIGH); prevstate = 1; prevbit = 1; - return; + return; } if (prevbit && prevstate) { @@ -188,7 +195,7 @@ void Oregon_TM::sendOne(void) delayMicroseconds(TR_TIME); digitalWrite(TX_PIN, HIGH); prevbit = 1; - return; + return; } if (prevbit && !prevstate) { @@ -196,9 +203,8 @@ void Oregon_TM::sendOne(void) delayMicroseconds(TR_TIME); digitalWrite(TX_PIN, LOW); prevbit = 1; - return; + return; } - } } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -209,58 +215,63 @@ void Oregon_TM::sendMSB(byte data) (bitRead(data, 5)) ? sendOne() : sendZero(); (bitRead(data, 6)) ? sendOne() : sendZero(); (bitRead(data, 7)) ? sendOne() : sendZero(); - if (protocol == 2) time_marker += 4; // 1024.07 1024.60 - if (protocol == 3) time_marker += 2; - - + if (protocol == 2) + time_marker += 4; //Поправка на разницу тактовых частот 1024.07Гц и 1024.60Гц + if (protocol == 3) + time_marker += 2; } /////////////////////////////////////////////////////////////////////////////////////////////////// - + void Oregon_TM::sendLSB(byte data) { (bitRead(data, 0)) ? sendOne() : sendZero(); (bitRead(data, 1)) ? sendOne() : sendZero(); (bitRead(data, 2)) ? sendOne() : sendZero(); (bitRead(data, 3)) ? sendOne() : sendZero(); - if (protocol == 2) time_marker += 4; // 1024.07 1024.60 - if (protocol == 3) time_marker += 2; + if (protocol == 2) + time_marker += 4; //Поправка на разницу тактовых частот 1024.07Гц и 1024.60Гц + if (protocol == 3) + time_marker += 2; } /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::sendData() { - for(byte i = 0; i < 10; ++i) + for (byte i = 0; i < 10; ++i) { sendMSB(SendBuffer[i]); if (i < 9) - sendLSB(SendBuffer[i]); - if (protocol == 2) time_marker += 4; // 1024.07 1024.60 - //if (protocol == 3) time_marker += 4; - // 1024.07 1024 + sendLSB(SendBuffer[i]); + if (protocol == 2) + time_marker += 4; //Поправка на разницу тактовых частот 1024.07Гц и 1024.60Гц + //if (protocol == 3) time_marker += 4; + //Поправка на разницу тактовых частот 1024.07Гц и 1024Гц } } /////////////////////////////////////////////////////////////////////////////////////////////////// - + void Oregon_TM::sendOregon() { - time_marker=micros(); - sendPreamble(); - sendLSB(0xA); - sendData(); + time_marker = micros(); + sendPreamble(); + sendLSB(0xA); + sendData(); } /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::sendPreamble(void) { - if (protocol == 2){ + if (protocol == 2) + { sendLSB(0xF); sendLSB(0xF); - time_marker += 9; + time_marker += 9; sendLSB(0xF); sendLSB(0xF); time_marker += 9; } - if (protocol == 3){ + if (protocol == 3) + { sendLSB(0xF); sendLSB(0xF); sendLSB(0xF); @@ -273,7 +284,7 @@ void Oregon_TM::sendPreamble(void) } /////////////////////////////////////////////////////////////////////////////////////////////////// - + void Oregon_TM::calculateAndSetChecksum132(void) { byte CCIT_POLY = 0x07; @@ -283,26 +294,30 @@ void Oregon_TM::calculateAndSetChecksum132(void) byte summ = 0x00; byte crc = 0x3C; byte cur_nible; - for(int i = 0; i<8; i++) + for (int i = 0; i < 8; i++) { cur_nible = (SendBuffer[i] & 0xF0) >> 4; summ += cur_nible; - if (i !=3) + if (i != 3) { crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - } + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + } cur_nible = SendBuffer[i] & 0x0F; summ += cur_nible; - if (i !=2) + if (i != 2) { crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - } + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + } } SendBuffer[7] += summ & 0x0F; SendBuffer[8] += summ & 0xF0; @@ -320,26 +335,30 @@ void Oregon_TM::calculateAndSetChecksum318() byte summ = 0x00; byte crc = 0x00; byte cur_nible; - for(int i = 0; i<8; i++) + for (int i = 0; i < 8; i++) { cur_nible = (SendBuffer[i] & 0xF0) >> 4; summ += cur_nible; - if (i !=3) + if (i != 3) { crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - } + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + } cur_nible = SendBuffer[i] & 0x0F; summ += cur_nible; - if (i !=2) + if (i != 2) { crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - } + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + } } SendBuffer[7] += summ & 0x0F; SendBuffer[8] += summ & 0xF0; @@ -357,28 +376,33 @@ void Oregon_TM::calculateAndSetChecksum810() byte summ = 0x00; byte crc = 0x00; byte cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - - for(int i = 0; i<8; i++) + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + + for (int i = 0; i < 8; i++) { cur_nible = (SendBuffer[i] & 0xF0) >> 4; summ += cur_nible; - - crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - + + crc ^= cur_nible; + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + cur_nible = SendBuffer[i] & 0x0F; summ += cur_nible; - - crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - + + crc ^= cur_nible; + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; } SendBuffer[7] += summ & 0x0F; SendBuffer[8] += summ & 0xF0; @@ -398,309 +422,314 @@ void Oregon_TM::SendPacket() if (sens_type == THP) calculateAndSetChecksumTHP(); - sendOregon(); digitalWrite(TX_PIN, LOW); - if (protocol == 2){ - delayMicroseconds(TWOTR_TIME*15); + if (protocol == 2) + { + delayMicroseconds(TWOTR_TIME * 15); sendOregon(); digitalWrite(TX_PIN, LOW); } } /////////////////////////////////////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////////// +// Функции кодирования данных////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setType(word type) +{ + sens_type = type; + if (type == THP) { - sens_type = type; - if (type == THP) - { - SendBuffer[0] = 0x55; - return; - } - SendBuffer[0] = (type & 0xFF00) >> 8; - SendBuffer[1] = type & 0x00FF; + SendBuffer[0] = 0x55; + return; } + SendBuffer[0] = (type & 0xFF00) >> 8; + SendBuffer[1] = type & 0x00FF; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setChannel(byte channel) +{ + byte channel_code; + if (sens_type == THGN132) { - byte channel_code; - if (sens_type == THGN132) + if (channel <= 1) + { + channel_code = 0x10; + setId(0xE3); + send_time = 39000; + } + if (channel == 2) + { + channel_code = 0x20; + setId(0xE3); + send_time = 41000; + } + if (channel == 3) { - if (channel <= 1) - { - channel_code = 0x10; - setId(0xE3); - send_time = 39000; - } - if (channel == 2) - { - channel_code = 0x20; - setId(0xE3); - send_time = 41000; - } - if (channel == 3) - { - channel_code = 0x40; - setId(0xBB); - send_time = 43000; - } - protocol = 2; + channel_code = 0x40; + setId(0xBB); + send_time = 43000; } + protocol = 2; + } - if (sens_type == RTGN318) + if (sens_type == RTGN318) + { + + if (channel <= 1) + { + channel_code = 0x10; + setId(0xF1); + send_time = 53000; + } + if (channel == 2) + { + channel_code = 0x20; + setId(0x92); + send_time = 59000; + } + if (channel == 3) { + channel_code = 0x30; + setId(0xAA); + send_time = 61000; + } - if (channel <= 1) - { - channel_code = 0x10; - setId(0xF1); - send_time = 53000; - } - if (channel == 2) - { - channel_code = 0x20; - setId(0x92); - send_time = 59000; - } - if (channel == 3) - { - channel_code = 0x30; - setId(0xAA); - send_time = 61000; - } - - if (channel == 4) - { - channel_code = 0x40; - setId(0x8A); - send_time = 67000; - } - - if (channel >= 5) - { - channel_code = 0x50; - setId(0xB1); - send_time = 71000; - } - protocol = 2; + if (channel == 4) + { + channel_code = 0x40; + setId(0x8A); + send_time = 67000; } -if (sens_type == THGR810) + if (channel >= 5) { - if (channel <= 1) - { - channel_code = 0x10; - setId(0xCB); - send_time = 53000; - } - if (channel == 2) - { - channel_code = 0x20; - setId(0x69); - send_time = 59000; - } - if (channel == 3) - { - channel_code = 0x30; - setId(0xAA); - send_time = 61000; - } - if (channel == 4) - { - channel_code = 0x40; - setId(0x8A); - send_time = 67000; - } - if (channel == 5) - { - channel_code = 0x50; - setId(0xB1); - send_time = 71000; - } - if (channel == 6) - { - channel_code = 0x60; - send_time = 79000; - } - if (channel == 7) - { - channel_code = 0x70; - send_time = 83000; - } - if (channel == 8) - { - channel_code = 0x80; - send_time = 87000; - } - if (channel == 9) - { - channel_code = 0x90; - send_time = 91000; - } - if (channel >= 10) - { - channel_code = 0xA0; - send_time = 93000; - } - protocol = 3; + channel_code = 0x50; + setId(0xB1); + send_time = 71000; } - SendBuffer[2]&= 0x0F; - SendBuffer[2] += channel_code & 0xF0; + protocol = 2; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -void Oregon_TM::setId(byte ID) + if (sens_type == THGR810) { - SendBuffer[2]&= 0xF0; - SendBuffer[2] += (ID & 0xF0) >> 4; - SendBuffer[3]&= 0x0F; - SendBuffer[3] += (ID & 0x0F) << 4; + if (channel <= 1) + { + channel_code = 0x10; + setId(0xCB); + send_time = 53000; + } + if (channel == 2) + { + channel_code = 0x20; + setId(0x69); + send_time = 59000; + } + if (channel == 3) + { + channel_code = 0x30; + setId(0xAA); + send_time = 61000; + } + if (channel == 4) + { + channel_code = 0x40; + setId(0x8A); + send_time = 67000; + } + if (channel == 5) + { + channel_code = 0x50; + setId(0xB1); + send_time = 71000; + } + if (channel == 6) + { + channel_code = 0x60; + send_time = 79000; + } + if (channel == 7) + { + channel_code = 0x70; + send_time = 83000; + } + if (channel == 8) + { + channel_code = 0x80; + send_time = 87000; + } + if (channel == 9) + { + channel_code = 0x90; + send_time = 91000; + } + if (channel >= 10) + { + channel_code = 0xA0; + send_time = 93000; + } + protocol = 3; } + SendBuffer[2] &= 0x0F; + SendBuffer[2] += channel_code & 0xF0; +} +/////////////////////////////////////////////////////////////////////////////////////////////////// + +void Oregon_TM::setId(byte ID) +{ + SendBuffer[2] &= 0xF0; + SendBuffer[2] += (ID & 0xF0) >> 4; + SendBuffer[3] &= 0x0F; + SendBuffer[3] += (ID & 0x0F) << 4; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setBatteryFlag(bool level) - { - SendBuffer[3] &= 0xFB; - if (level) SendBuffer[3] |= 0x04; - } +{ + SendBuffer[3] &= 0xFB; + if (level) + SendBuffer[3] |= 0x04; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setStartCount(byte startcount) - { - SendBuffer[3] &= 0xF4; - if (startcount == 8) SendBuffer[3] |= 0x08; - if (startcount == 2) SendBuffer[3] |= 0x02; - if (startcount == 1) SendBuffer[3] |= 0x01; - } +{ + SendBuffer[3] &= 0xF4; + if (startcount == 8) + SendBuffer[3] |= 0x08; + if (startcount == 2) + SendBuffer[3] |= 0x02; + if (startcount == 1) + SendBuffer[3] |= 0x01; +} /////////////////////////////////////////////////////////////////////////////////////////////////// - + void Oregon_TM::setTemperature(float temp) +{ + if (temp < 0) { - if(temp < 0) - { - SendBuffer[5] = 0x08; - temp *= -1; - } - else - { - SendBuffer[5] = 0x00; - } - byte tempInt = (byte) temp; - byte td = (tempInt / 10); - byte tf = tempInt - td * 10; - byte tempFloat = (temp - (float)tempInt) * 10; - - SendBuffer[5] += (td << 4); - SendBuffer[4] = tf; - SendBuffer[4] |= (tempFloat << 4); + SendBuffer[5] = 0x08; + temp *= -1; + } + else + { + SendBuffer[5] = 0x00; } + byte tempInt = (byte)temp; + byte td = (tempInt / 10); + byte tf = tempInt - td * 10; + byte tempFloat = (temp - (float)tempInt) * 10; + + SendBuffer[5] += (td << 4); + SendBuffer[4] = tf; + SendBuffer[4] |= (tempFloat << 4); +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setHumidity(byte hum) - { - SendBuffer[6] = (hum/10); - SendBuffer[6] += (hum - (SendBuffer[6] * 10)) << 4; - } +{ + SendBuffer[6] = (hum / 10); + SendBuffer[6] += (hum - (SendBuffer[6] * 10)) << 4; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setComfort(float temp, byte hum) +{ + if (hum > 70) { - if (hum > 70) - { - SendBuffer[7] = 0xC0; - return; - } - if (hum < 40) - { - SendBuffer[7] = 0x80; - return; - } - if (temp > 20 && temp < 25) - { - SendBuffer[7] = 0x40; - return; - } - else SendBuffer[7] = 0x00; - return; + SendBuffer[7] = 0xC0; + return; } + if (hum < 40) + { + SendBuffer[7] = 0x80; + return; + } + if (temp > 20 && temp < 25) + { + SendBuffer[7] = 0x40; + return; + } + else + SendBuffer[7] = 0x00; + return; +} /////////////////////////////////////////////////////////////////////////////////////////////////// bool Oregon_TM::transmit() { - if (millis() >= time_marker_send && send_time) + if (millis() >= time_marker_send && send_time) { SendPacket(); - time_marker_send = millis() + send_time; + time_marker_send = millis() + send_time; return true; } - else return false; + else + return false; } - - - - - /////////////////////////////////////////////////////////////////////////////////////////////////// -// THP +//Поддержка датчика THP /////////////////////////////////////////////////////////////////////////////////////////////////// - void Oregon_TM::setChannelTHP(byte channel) - { +{ SendBuffer[1] &= 0x0F; SendBuffer[1] += channel << 4; - } -/////////////////////////////////////////////////////////////////////////////////////////////////// -void Oregon_TM::setBatteryTHP( word bat_voltage) - { - SendBuffer[6] = (bat_voltage & 0x0FF0) >> 4; - SendBuffer[7] &= 0x0F; - SendBuffer[7] += (bat_voltage & 0x000F) << 4; - - } -/////////////////////////////////////////////////////////////////////////////////////////////////// +} +/////////////////////////////////////////////////////////////////////////////////////////////////// +void Oregon_TM::setBatteryTHP(word bat_voltage) +{ + SendBuffer[6] = (bat_voltage & 0x0FF0) >> 4; + SendBuffer[7] &= 0x0F; + SendBuffer[7] += (bat_voltage & 0x000F) << 4; +} +/////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setTemperatureTHP(float bme_temperature) - { - word temp_code; - if (bme_temperature < -100 || bme_temperature > 100) temp_code = 0x0FFF; - else temp_code = (word)((bme_temperature + 100) * 10); - SendBuffer[2] = temp_code & 0x00FF; - SendBuffer[1] &= 0xF0; - SendBuffer[1] += (temp_code & 0x0F00) >> 8; - } -/////////////////////////////////////////////////////////////////////////////////////////////////// +{ + word temp_code; + if (bme_temperature < -100 || bme_temperature > 100) + temp_code = 0x0FFF; + else + temp_code = (word)((bme_temperature + 100) * 10); + SendBuffer[2] = temp_code & 0x00FF; + SendBuffer[1] &= 0xF0; + SendBuffer[1] += (temp_code & 0x0F00) >> 8; +} +/////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setHumidityTHP(float bme_humidity) - { - word hum_code; - if (bme_humidity > 100) hum_code = 0x0FFF; - else hum_code = (word)(bme_humidity * 10); - SendBuffer[3] = (hum_code & 0x0FF0) >> 4; - SendBuffer[4] &= 0x0F; - SendBuffer[4] += (hum_code & 0x000F) << 4; - } +{ + word hum_code; + if (bme_humidity > 100) + hum_code = 0x0FFF; + else + hum_code = (word)(bme_humidity * 10); + SendBuffer[3] = (hum_code & 0x0FF0) >> 4; + SendBuffer[4] &= 0x0F; + SendBuffer[4] += (hum_code & 0x000F) << 4; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setPressureTHP(float bme_pressure) - { - word pres_code; - if (bme_pressure < 500) pres_code = 0x0000; - else pres_code = (word)((bme_pressure - 500) * 10); - SendBuffer[5] = pres_code & 0x00FF; - SendBuffer[4] &= 0xF0; - SendBuffer[4] += (pres_code & 0x0F00) >> 8; - } +{ + word pres_code; + if (bme_pressure < 500) + pres_code = 0x0000; + else + pres_code = (word)((bme_pressure - 500) * 10); + SendBuffer[5] = pres_code & 0x00FF; + SendBuffer[4] &= 0xF0; + SendBuffer[4] += (pres_code & 0x0F00) >> 8; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::setErrorTHP() - { - SendBuffer[1] |= 0x0F; - SendBuffer[2] = 0xFF; - SendBuffer[3] = 0xFF; - SendBuffer[4] = 0xFF; - SendBuffer[5] = 0xFF; - } +{ + SendBuffer[1] |= 0x0F; + SendBuffer[2] = 0xFF; + SendBuffer[3] = 0xFF; + SendBuffer[4] = 0xFF; + SendBuffer[5] = 0xFF; +} /////////////////////////////////////////////////////////////////////////////////////////////////// void Oregon_TM::calculateAndSetChecksumTHP() { @@ -711,25 +740,28 @@ void Oregon_TM::calculateAndSetChecksumTHP() byte summ = 0x00; byte crc = 0x00; byte cur_nible; - for(int i = 0; i<8; i++) + for (int i = 0; i < 8; i++) { cur_nible = (SendBuffer[i] & 0xF0) >> 4; summ += cur_nible; crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; - + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; + cur_nible = SendBuffer[i] & 0x0F; summ += cur_nible; crc ^= cur_nible; - for(int j = 0; j < 4; j++) - if (crc & 0x80) crc = (crc << 1) ^ CCIT_POLY; - else crc <<= 1; + for (int j = 0; j < 4; j++) + if (crc & 0x80) + crc = (crc << 1) ^ CCIT_POLY; + else + crc <<= 1; } SendBuffer[7] += summ & 0x0F; SendBuffer[8] += summ & 0xF0; SendBuffer[8] += crc & 0x0F; SendBuffer[9] += crc & 0xF0; } - diff --git a/Oregon_TM.h b/Oregon_TM.h index 586d070..02316cd 100644 --- a/Oregon_TM.h +++ b/Oregon_TM.h @@ -3,7 +3,7 @@ #define Oregon_TM_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: 29 June 2019 // @@ -16,7 +16,7 @@ // Receive only: // THN132N, -// WGR800, +// WGR800, // UVN800. // // Aslo supported self-developed sensors. Please contact author for additional infromation. @@ -26,7 +26,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,116 +35,107 @@ // 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 // -// 29 2019 +// Последнее обновление 29 июня 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, // THGR810. -// : +// Тольок приём: // THN132N, -// WGR800, +// WGR800, // UVN800. // -// ( ) +// Также поддерживаются датчики собственной разработки (за дополнительной документацей обращаться к автору) // -// - OREGON_NR +// Этот файл - часть библиотеки OREGON_NR ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2019 +// Copyright (c) 2019 Сергей Зависляк // -// , -// ( ), , -// , , , , , , -// / , , , : +// Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации +// (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, +// включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование +// и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: // -// . +// Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. // -// ܻ, - , , -// , , . -// - , , , , , -// - . +// ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ +// ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ +// НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, +// ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - #define TR_TIME 488 #define TWOTR_TIME 976 -#define PULSE_SHORTEN_2 80 -#define PULSE_SHORTEN_3 120 +#define PULSE_SHORTEN_2 80 +#define PULSE_SHORTEN_3 120 -#define THGN132 0x1D20 -#define THGR810 0xF824 -#define RTGN318 0xDCC3 -#define THP 0x5500 +#define THGN132 0x1D20 +#define THGR810 0xF824 +#define RTGN318 0xDCC3 +#define THP 0x5500 static byte TX_PIN = 4; static const int buffersize = 10; class Oregon_TM { - public: - - byte SendBuffer[buffersize]; - byte protocol = 2; - word sens_type = 0x0000; - - Oregon_TM(byte); - Oregon_TM(); - void setType(word); - void setChannel( byte); - void setId(byte); - void setBatteryFlag(bool); - void setStartCount(byte); - void setTemperature(float); - void setHumidity(byte); - void setComfort(float, byte); - bool transmit(); - void SendPacket(); - - void setErrorTHP(); - void setPressureTHP(float); - void setTemperatureTHP(float); - void setBatteryTHP(word); - void setChannelTHP(byte); - void setHumidityTHP(float); - - - - private: - - void sendZero(void); - void sendOne(void); - void sendMSB(const byte); - void sendLSB(const byte); - void sendData(); - void sendOregon(); - void sendPreamble(); - void calculateAndSetChecksum132(); - void calculateAndSetChecksum318(); - void calculateAndSetChecksum810(); - - - void calculateAndSetChecksumTHP(); - - unsigned long time_marker = 0; - unsigned long time_marker_send = 0; - unsigned long send_time = 0; - bool prevbit = 1; - bool prevstate = 1; - - +public: + byte SendBuffer[buffersize]; + byte protocol = 2; + word sens_type = 0x0000; + + Oregon_TM(byte); + Oregon_TM(); + void setType(word); + void setChannel(byte); + void setId(byte); + void setBatteryFlag(bool); + void setStartCount(byte); + void setTemperature(float); + void setHumidity(byte); + void setComfort(float, byte); + bool transmit(); + void SendPacket(); + + void setErrorTHP(); + void setPressureTHP(float); + void setTemperatureTHP(float); + void setBatteryTHP(word); + void setChannelTHP(byte); + void setHumidityTHP(float); + +private: + void sendZero(void); + void sendOne(void); + void sendMSB(const byte); + void sendLSB(const byte); + void sendData(); + void sendOregon(); + void sendPreamble(); + void calculateAndSetChecksum132(); + void calculateAndSetChecksum318(); + void calculateAndSetChecksum810(); + + void calculateAndSetChecksumTHP(); + + unsigned long time_marker = 0; + unsigned long time_marker_send = 0; + unsigned long send_time = 0; + bool prevbit = 1; + bool prevstate = 1; }; #endif - diff --git a/README.md b/README.md index e81e6d4..947c472 100644 --- a/README.md +++ b/README.md @@ -19,40 +19,40 @@ // Aslo supported self-developed sensors. Please contact author for additional infromation. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// Oregon Scientific v2.1 v3.0 +// Данная библиотека Ардуино предназначена для приема и передачи данных в формате беспроводного протокола Oregon Scientific v2.1 и v3.0 // -// 29 2019 +// Последнее обновление 29 июня 2019 // -// +// Поддерживается формат следующих датчиков // -// : +// Приём и передача: // THGN132N (THGR122N, THGN123N), // RTGN318, // THGR810. -// : +// Тольок приём: // THN132N, // WGR800, // UVN800. // -// ( ) +// Также поддерживаются датчики собственной разработки (за дополнительной документацей обращаться к автору) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// THGN132N, THN132N WGR800. +// Код приёмника протестирован на оригинальных датчиках THGN132N, THN132N и WGR800. // -// BAR206, BAR208 THGN132N -// : -// 2-98% -// -50...+70 -// " " , -// +-1. THGN132: -// 1 - 39 (38 - 40) c -// 2 - 41 (40 - 42) c -// 3 - 43 (42 - 44) c +// Код передатчика протетстирована на погодных станциях BAR206, BAR208 эмуляцией сигнала THGN132N +// Для успешного приёма погодной станцией сигнала необходимо соблюдать следующие условия при передаче данных: +// Влажность 2-98% +// Температура -50...+70С +// При создании энергосберегающих датчиков с режимом "глубокого сна" нужно учесть, что интервалы между пакетами для успешного приёма погодной станцией +// должны отличаться от номинальных не более чем на +-1сек. Например для THGN132: +// Канал 1 - 39 (38 - 40) c +// Канал 2 - 41 (40 - 42) c +// Канал 3 - 43 (42 - 44) c // -// CRC , , +3.0 0300, A200 -// ID . -// ID . +// Если пришёл пакет с корректной CRC и контрольной суммой, но значение температуры и влажности некорректные, например +3.0С переданы не как 0300, а A200 +// то датчик может быть заблокирован до смены ID или до сброса погодной станциии. +// Блокировка навсегда возможна и при неправильном сочетании номера канала и ID датчика. Этот вопрос пока до конца не изучен // -// RTGN318 THGR810 . -// \ No newline at end of file +// Передача сигналов в формате RTGN318 и THGR810 до конца не протестирована. Поэтому возможны проблемы с приёмом этих сигналов погодной станцией +// на отдельных каналах