Погодная станция на датчиках Oregon Scientific v2.1

Porosenok
Offline
Зарегистрирован: 06.11.2016

Именно желание получить в доме ещё одну погодную станцию, понимающую датчики Oregon Scientific, и привело меня к Ардуино. Сразу хочу отметить, что я не программист. Си знаю плохо, пытаюсь объясняться с компьютером тем словарным запасом, которым владею. Поэтому код получается обычно весьма корявый, но понятный компилятору.

Итак, в наличии у меня было следующее:

1. Датчики Oregon THGN132 и THN132, в которых реализован протокол версии 2.1,

2. Arduino Uno, 

3. дисплей LCD2004 I2C,

4. модуль часов реального времени DS3231, 

5. Простейший приёмник 433Мгц RF-5V, 

6. Модуль барометра Oregon Scientific SR-BAR998HG.

Простого пути не получилось. Попытка использовать код, приведённый в теме  http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-scientific-433mhz ни к чему не привела. Максимальное расстояние, с которого были видны датчики - 7 метров. При этом стоящая рядом фирменная погодная станция уверенно видела датчик, висящий на хозблоке в 20-и метрах от дома. Разобрав эту станцию, и убедившись, что там установлен простенький приёмник, очень похожий на RF-5V, я понял, что проблема совсем не в приёмнике. 

Анализ вышеуказанного кода , подтвердил мои подозрения - код рассчитан на лабораторные условия. Не устроило меня в нём следующее:

1. любые помехи в коде воспринимаются как фатальная ошибка. Даже после короткого всплеска в 200мкс весь пакет данных считается испорченным.

2. Не используются возможности самовосстановления кода за счёт его избыточности,

3. Датчики передают два пакета подряд. Эта особенность практически игнорируется автором.

В итоге было принято решение написать всё с нуля. Анализа осциллограмм выхода приёмника в момент прихода пакетов дал представление о наиболее распространённых видах искажения сигнала:

1. Зажёвывание приёмником начала пакета из-за медленной АРУ, 

2. Дробление импульсов при слабом сигнале,

3. Помехи в момент прохождения "нулей".

Исходя из этого была выработана стратегия сбора данных:

- Чтобы начать читать пакет из эфира, надо за что-то зацепиться. Разумнее всего - за преамбулу: на фоне шума проще всего найти несколько импульсов правильной длины с правильными временными интервалами. 

- После удачного нахождения такой последовательности в память записывается сигнал с приёмника с частотой дискретизации около 16 384Гц. Это около 8 измерений на такт, что вполне достаточно, чтобы не обращать внимания на дробление импульсов. Продолжительность записи ограничивается либо предельной длиной ожидаемого пакета, либо молчанием канала в течение определённого времени.

- По возможности записываются обе кодовые посылки, идущие с интервалом в несколько миллисекунд.

- Теперь, когда данные собраны, можно неспешно их разобрать. Расшифровывая запись можно получить битовую последовательность. Если избыточность данных посылки позволяет подтвердить отдельные биты, им назначается статус уверенных. Иначе - биты сомнительные.

По причине возможных сбоев синхронизации при обнаружении преамбулы, проводится подсчёт уверенных и сомнительных битов с разными начальными временными смещениями, т.е. вычисляются веса вариантов расшифровки и выбирается лучший из них.

- Если получился пакет с сомнительными участками или записана только часть пакета, то недостающие данные по возможности ищутся во втором пакете. Иными словами, из двух неполных пакетов собирается один полный.

- Собранный пакет должен в обязательном порядке иметь хотя бы четыре последних бита преамбулы (т.н. нибл синхронизации), иначе не всегда можно понять, где начало данных. Если условие соблюдается - пакет считается целым.

- В пакете ещё могут оставаться сомнительные биты. Как их проверить? Конечно же с помощью контрольной суммы! Если она сошлась - пакет признан годным.

Основной недостаток такого подхода к анализу данных - большое количество необходимой для работы оперативной памяти.

Полевые испытания созданного кода весьма порадовали. Видимость датчика выросла практически до уровня фирменной погодной станции, чего, в общем, и добивался.

к коду самого приёмника была дописана сама "погодная станция" - вывод на четырёхстрочный дисплей данных с датчиков (температура, влажность, состояние батареи). Также на дисплее в виде т.н."ёлочки" отображается время прихода данных. Чем дольше программа не получает пакет, тем короче "ёлочка". Если данных не было достаточно долго, информация от такого датчика стирается с экрана.

Если пришёл повреждённый пакет с неправильной контрольной суммой - к "елочке" дорисовывается лишняя "ветка", но данные не обновляются. 

По нажатию на кнопку можно посмотреть экстремумы температуры за сегодня. Эта функция очень понравилась в фирменной погодной станции. 

В Serial выводится вся информация о ходе расшифровки данных.

Дисплей и модуль часов подключены Ардуино по I2C, кнопка c подтягивающим резистором - к D3, а  приемник - к D2. Данные барометра приходят на А0. 

Внутренняя температура берётся с модуля часов. Признаться честно, это плохое решение. Во-первых, модуль в процессе работы нагревается на полтора-два градуса. Во-вторых, внутренний термометр выдаёт температуру с точностью до четверти градуса.

Ещё хочется отметить важный момент - качество питания станции. Использование импульсного источника питания снижает радиус приёма примерно в полтора раза. Лучше использовать трансформаторный адаптер или аккумулятор как минимум для питания самого приёмника.  

Антенна приёмника - отрезок медного провода диаметром около 1мм и длиной 16см.

Модуль барометра Oregоn  SR-BAR998HG - аналоговый, основан на датчике MPXM2102A.

Используемые библиотеки:

LCD2004 I2C:  https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home#!downloading-and-installation

DS3231:  http://www.rinkydinkelectronics.com/library.php?id=73

Описание протокола Oregon: http://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf

Следующим шагом стало написание кода эмулятора датчика THGN132.

Код приведённый на форуме (http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-s...) с моей погодной станцией не работал. При внимательном рассмотрении оказалось, что он является достаточно вольной интерпретацией протокола Oregon. Но об этом чуть позже.
 
 
#include <DS3231.h>
#include <LiquidCrystal_I2C.h>

//Типы известных датчиков
#define THGN132 0x1D20
#define THN132  0xEC40

#define MHZ 2

#define FIND_PACKET   1
#define ANALIZE_PACKETS 3

//Времена отсутствия датчика, после которых изменять индикатор
#define LOST1 2
#define LOST2 4
#define LOST3 8

#define LOST4 32  // убрать строку с дисплея

#define RTC_PRESENT  1 //0 - если нет модуля RTC

#define PER_LENGTH 976      // Период в мкс
#define  THR_LENGTH 615     //Порог длины 0 или 1
#define LENGTH_TOLERANCE 20 //Допуск на период

#define READ_BITS 90        //Размер битовой посылки
#define READ_BITS2 180      //Двойной размер битовой посылки
#define PACKET_LENGTH 20    //Размер пакета данных
#define DEBUG_INFO 1        //Выводить ли диагностическую информацию

volatile byte DISPLAY_MODE = 1;
byte maxminshow = 0;
bool showdots = 0;
float bar_old = 0;
bool  reciever_ctrl = true; //Флаг контроля ресивера (выставляется при приходе импулься, сбрасывается в таймере)
bool  reciever_status = false; // Результат проверки состояния ресивера

//Для Хранения полученных данных:
float r_tmp[4];
float r_tmp_max[4];
float r_tmp_min[4];
byte  r_hmdty[4];
bool  r_bat[4];
bool  r_crc[4];
bool  r_isreceived[4];
word  r_type[4];

byte lcd_chnl;              //
unsigned long rcv_time[4]; // время прихода пакетов

     
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

byte Cels[8] = {  0b01100,  0b01100,  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b00000};

byte reciv1[8] = {  0b00000,  0b00000,  0b00000,  0b00000,  0b01000,  0b01001,  0b01001,  0b00000,};
byte reciv2[8] = {  0b00000,  0b00000,  0b01000,  0b01001,  0b01001,  0b01001,  0b01001,  0b00000,};
byte reciv3[8] = {  0b01000,  0b01001,  0b01001,  0b01001,  0b01001,  0b01001,  0b01001,  0b00000,};

byte batemp[8] = {  0b00100,  0b11111,  0b10001,  0b10001,  0b10001,  0b11111,  0b11111,  0b00000, };
byte crcerr[8] = {  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b00001,  0b00001,  0b00000, };
byte dot[8] = {  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b00100,  0b00000, };
byte dot2[8] = {  0b00000,  0b00100,  0b00000,  0b00000,  0b0000,  0b00100,  0b00000,  0b00000,};

#if RTC_PRESENT == 1
//Массив, содержащий время компиляции
char compileTime[] = __TIME__;
char compileDate[] = __DATE__;

DS3231 Clock(SDA, SCL);
Time RTC_Time;
#endif

int bt;

byte receive_status, packet_number;
byte start_pulse_cnt;

unsigned long pulse_length, work_time,  timer_marklong;  
unsigned long pulse_marker, right_pulse_marker, last_premarker;
unsigned long pre_marker[4]; // Для хранения временных меток преамбулы ()
unsigned long first_packet_end;

bool crc_c;             //Результат проверки CRC
word sens_type;         //Тип сенсора
bool pulse_type;        //Пустое

byte data_length, data_length2; //Длины пакетов
int data_val, data_val2; // Качестов пакетов
byte collect_data[READ_BITS2], collect_data2[READ_BITS2];//Массивы данных для чтения 
byte decode_tacts[READ_BITS2]; //Массив тактов. значения
//                          0=ноль
//                          1=единица
//                          2=неизвестен
//                          3=переход+
//                          4=переход-
//А когда становится массивом полученных битов, то значения такие:
//                          0 - неизвестен
//                          >0 - единица
//                          <0 - ноль

/////////    ПРЕРЫВАНИЕ   ///////////////////////////////////////////////////////////////////////////////////////////

volatile unsigned long pm;
volatile unsigned long pl, timer_mark;  

void int_0(void) {  
  if(digitalRead(MHZ)){
  //Начало импульса
    pl = 0;
    pm = micros();  
  }
  else{
    //Конец импульса
    //Вычисляется время окончания и длина
    pl = micros() - pm;  
    pm += pl;
  }
}  

void int_1(void) {  
  DISPLAY_MODE = 2;
  timer_mark += 1000;
}
//////////////// УСТАНОКВКИ  ///////////////////////////////////////
void setup ()
{

  //Иницализации///////////////
#if RTC_PRESENT == 1
  Clock.begin();
  // Записываем время в часы по времени компиляции
  //Clock.adjust(compileDate, compileTime);
  // Выставляем день недели
  //Clock.setDOW();
#endif 
  
  lcd.begin(20, 4);
  lcd.backlight();

  lcd.createChar (0, Cels);
  lcd.createChar (1, reciv1);
  lcd.createChar (2, reciv2);
  lcd.createChar (3, reciv3);
  lcd.createChar (4, batemp);
  lcd.createChar (5, crcerr);
  lcd.createChar (6, dot);
  lcd.createChar (7, dot2);
  
  //Настройки АЦП для датчика давления
  analogReference(DEFAULT)   ;
 
  Serial.begin(57600);
   
  //Прерывание по сигналу от приёмника
  pinMode(MHZ,INPUT);   
  attachInterrupt(1, int_1, FALLING);  
  attachInterrupt(0, int_0, CHANGE);  
  
  receive_status = FIND_PACKET;
  start_pulse_cnt = 0;
  packet_number = 0;
  for (int i = 0; i < 4; i++){
    r_tmp_max[i] = -110;
    r_tmp_min[i] = 110;
    rcv_time[i] = 7000000;
    r_isreceived[i] = 0;
  }
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}

//////////////// ГЛАВНЫЙ ЦИКЛ  ///////////////////////////////////////
void loop() 
{
  //Останавливаем прослушку приёмника для считывания данных
  noInterrupts();
  pulse_length = pl;
  pl = 0;
  pulse_marker = pm;
  interrupts();
//////////////////////////////////////////////////////////////////////
//Получен некий импульс,//////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
  if (pulse_length != 0 && receive_status == FIND_PACKET){  
    reciever_ctrl = 1;
    //Режим поиска пакета в эфире
    if (start_pulse_cnt == 0){
    //Найдена первый "правильный" импульс - длинная единица!
      if (pulse_length < (PER_LENGTH) && pulse_length > (THR_LENGTH) ) {
        start_pulse_cnt = 1;
        pre_marker[start_pulse_cnt] = pulse_marker;
        pulse_length = 0;
      }
    }
    //Ищем следующие импульсы
    else{
    //Найден импуль правильной длины
      if (pulse_length <= (PER_LENGTH) && pulse_length >= (THR_LENGTH)) {
        //Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов
        if(pulse_marker - pre_marker[start_pulse_cnt] > (PER_LENGTH*2-LENGTH_TOLERANCE) && pulse_marker - pre_marker[start_pulse_cnt] < (PER_LENGTH * 2 + LENGTH_TOLERANCE)){
          start_pulse_cnt++;
          pre_marker[start_pulse_cnt] = pulse_marker;
          pulse_length = 0;
        }
        ///...tсли  в неправильном месте то назначаем его первым
        else{
          start_pulse_cnt = 1;
          pre_marker[start_pulse_cnt] = pulse_marker;
          pulse_length = 0;
        }
      }
      else{
        //Если импульс неправильной длины, то стоит проверить, а не вышло ли время ожидания правильного импульса
        if(pulse_marker - pre_marker[start_pulse_cnt] < (PER_LENGTH * 2 + LENGTH_TOLERANCE)){
          //Время ещё не вышло, скорее всего это помеха. Пропускаем...
          pulse_length = 0;
        }
        else{
          //Время вышло, начинаем искать заново
            start_pulse_cnt = 0;
            pulse_length = 0;
          }
        }
      }
    }
    if(packet_number == 1 && (millis() - first_packet_end) > 200){ // Если найден первый пакет и вышло вермя ожидания второго
                                                               // Не ждём второго, а переходм в режим анализа
    receive_status = ANALIZE_PACKETS;
    }
//////////////////////////////////////////////////////////////////////
// Сбор данных////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

  //Если Найдены три длинных единицы и два длинных нуля. Возможно это начало посылки...
    if (start_pulse_cnt == 3 && receive_status == FIND_PACKET){
      work_time = millis();
      last_premarker = pre_marker[3];
      start_pulse_cnt = 0;
        if (packet_number == 0){
          collect(collect_data, &data_length);
          first_packet_end = millis();
          packet_number = 1;
        }
        else{
          collect(collect_data2, &data_length2);
          packet_number = 2;
          receive_status = ANALIZE_PACKETS;
        }
      }
      if  (receive_status == ANALIZE_PACKETS){     
        digitalWrite(13, HIGH);
  //////////////////////////////////////////////////////////////////////
  // Анализ данных////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////      
        bool halfshift;
/*        if (DEBUG_INFO){
          for(bt = 0; bt < 180; bt++){
            Serial.print(collect_data[bt], HEX);
            Serial.print(' ');
          }
          Serial.println(" ");

          for(bt = 0; bt < 180; bt++){
            Serial.print(collect_data2[bt],HEX);
            Serial.print(' ');
          }
          Serial.println(" ");
        }
*/
        
        get_bits(collect_data);
        if (get_data(0, collect_data) > get_data(1, collect_data)){
          data_val = get_data(0, collect_data);
          halfshift = 0;
        }
        else {
          data_val = get_data(1, collect_data);
         halfshift = 0;
        }
        if (DEBUG_INFO){
          Serial.print("1)     ");
          for(bt = 0; bt < READ_BITS; bt++){
            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('.');
          }
          Serial.print(" VAL:");
          Serial.print(data_val);
          Serial.print(" SIZE:");
          Serial.print(data_length);
          Serial.print(" SHIFT:");
          Serial.print(halfshift);
        }
        if (packet_number == 2){
          get_bits(collect_data2);
          if (get_data(0, collect_data2) > get_data(1, collect_data2)) {
            data_val2 = get_data(0, collect_data2);
            halfshift = 0;
          }
          else {
            data_val2 = get_data(1, collect_data2);
            halfshift = 1;
          }
          if (DEBUG_INFO){
          Serial.println(" ");  
          Serial.print("2)     ");
          for(bt = 0; bt < READ_BITS; bt++){
            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('.');
          }
          Serial.print(" VAL:");
          Serial.print(data_val2);
          Serial.print(" SIZE:");
          Serial.print(data_length2);
          Serial.print(" SHIFT:");
          Serial.print(halfshift);
        }
      }
      int correlation = correlate_data(collect_data, collect_data2);
        if (DEBUG_INFO){
          Serial.print(" COR: ");
          Serial.println(correlation);
        }
        byte* result_data, result_data_start, aux_data;
        if (packet_number == 1){
          result_data = collect_data;     
        }
        else{
          if (correlation > 0){
            result_data = collect_data2;
            assemble_data(collect_data2,collect_data, &correlation);
        }
        else{
          result_data = collect_data;
          correlation = -correlation;
          assemble_data(collect_data, collect_data2, &correlation);
        }
        //Вывод готовой посылки
      }
      if (DEBUG_INFO){
        Serial.print("RESULT ");
        byte* rdt = result_data;
        for(bt = 0; bt < READ_BITS; bt++){
          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('.');
          rdt++;
        }
        Serial.println(" ");
      }
        //Обработка посылки
      Serial.print("PERIOD: ");
      Serial.print(millis()/40000);
      Serial.print(" ");
      byte packet[PACKET_LENGTH], valid_p[PACKET_LENGTH];
      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, если оно верно, то все сомнительные биты делаем несомнительными
        
        if (crc_c) for (byte www = 0; www < PACKET_LENGTH; www++) valid_p[www] = 0x0f;
        Serial.print(" PACKET: ");
        for (int q = 0;q < PACKET_LENGTH; q++) Serial.print(packet[q], HEX);
        Serial.print(" VALIDITY: ");
          for (int q = 0; q < PACKET_LENGTH; q++) Serial.print(valid_p[q], HEX);
      }
      if (sens_type == THGN132 || sens_type == THN132){
        Serial.print(" TYPE: ");
        if (sens_type == THGN132) Serial.print("THGN132N ");
        if (sens_type == THN132) Serial.print("THN132N  ");
        Serial.print("ID: ");
        Serial.print(get_id(packet), HEX);
        Serial.print(" CHNL: ");
        lcd_chnl=get_channel(packet);
        r_crc[lcd_chnl] = crc_c;
        Serial.print(lcd_chnl);
        r_type[lcd_chnl] = sens_type;
        if (crc_c) r_isreceived[lcd_chnl] = 1;
        
        //......Если получен правильный пакет, сбрасываем таймер
        if(crc_c) rcv_time[lcd_chnl] = millis();  //         
        
        Serial.print(" BAT: ");
        if(crc_c) r_bat[lcd_chnl] = get_battery(packet);
        if (r_bat[lcd_chnl]) Serial.print("F "); else Serial.print("e ");
       
        Serial.print("TMP: ");
        if(get_temperature_mask(valid_p)){
          if(crc_c) r_tmp[lcd_chnl] = get_temperature(packet);
          //Запись максимальных и минимальных значений за сутки только из пакетов с правильной CRC
          if (r_tmp[lcd_chnl] >= r_tmp_max[lcd_chnl] && crc_c) r_tmp_max[lcd_chnl] = r_tmp[lcd_chnl];
          if (r_tmp[lcd_chnl] <= r_tmp_min[lcd_chnl] && crc_c) r_tmp_min[lcd_chnl] = r_tmp[lcd_chnl];
          Serial.print(r_tmp[lcd_chnl], 1);
        }
        else {
          //r_tmp[lcd_chnl] = 101;
          Serial.print("----");
        }
        Serial.print("C ");
        if (sens_type == THGN132) {
          Serial.print("HUM: ");
          if (get_humidity_mask(valid_p)) {
            if(crc_c) r_hmdty[lcd_chnl] = get_humidity(packet);
            Serial.print(r_hmdty[lcd_chnl], 1);
        }
        else{
          Serial.print("--");
          //r_hmdty[lcd_chnl] = 101;
        }
        Serial.print("%");
      }
      else Serial.print("        ");
      Serial.print(" CRC: ");
      if (crc_c) Serial.print("OK ");
      else Serial.print("-- ");
      
          
      Serial.print(" PROC. TIME: ");
      Serial.print(millis() - work_time);
      Serial.println("ms ");
    }
    else Serial.println(" WRONG  ");
    // Возвращаемся к исходному состоянию
    receive_status = FIND_PACKET;
    packet_number = 0;
    start_pulse_cnt = 0;
    sens_type = 0;
    lcd_chnl = 0;
    digitalWrite(13, LOW);
  }

//////////////////////////////////////////////////////////////////////      
//Здесь записываются ежесекундные процедуры
//////////////////////////////////////////////////////////////////////      
  if ((millis() - timer_mark) > 1000) {
        
    timer_mark = millis();
    showdots = !showdots;
        
    if ( DISPLAY_MODE == 2){
      maxminshow++;
      if (maxminshow > 10){
        maxminshow = 0;
        DISPLAY_MODE = 1;
      }
    }
        
    //Сброс максимумов и минимумов в полночь
     ///////////////////////////////////////
#if RTC_PRESENT == 1
    
    RTC_Time = Clock.getTime();
    if (RTC_Time.hour == 0 && RTC_Time.min == 0){
      for (int i = 0; i < 4; i++) {
        r_tmp_max[i] = r_tmp[i];
        r_tmp_min[i]=r_tmp[i];
      }
    }
    #endif
    {
      if (!reciever_status) Serial.println("RECEIVING...");
      lcd.setCursor(14, 0);
      lcd.print(' ');
#if RTC_PRESENT == 1
      lcd.print(Clock.getTimeStr(FORMAT_SHORT));
      lcd.setCursor(17, 0);
      if (showdots)  lcd.print(char(7)); else lcd.print(' ');
      lcd.setCursor(1, 0);
      lcd.print(Clock.getTemp() - 1.5);//На 1.5 градуса убавим - нагревается за счёт светодиода
      lcd.setCursor(5, 0);
      lcd.print(char(0));
      lcd.setCursor(3, 0);
      lcd.print(char(6));
      //Барометр////////
      
      //float bar=491 + analogRead(0) * 0.5833; //мБар
      float bar=387 + analogRead(0) * 0.4167; //ммртст
      if (bar_old == 0) bar_old = bar; //первое измерение
      
      if ((millis() - timer_marklong) > 10000000) {
        if (bar_old-bar > 5) {
          lcd.setCursor(12, 0);
          lcd.print("--");
        }
        if (bar_old-bar > 1) {
          lcd.setCursor(12, 0);
          lcd.print('-');
        }
        if (bar_old-bar < -1) {
          lcd.setCursor(12, 0);
          lcd.print('+');
        }
        if (bar_old-bar < -5) {
          lcd.setCursor(12, 0);
          lcd.print("++");
        }
        if (bar_old-bar < 2 && bar_old-bar > -2) {
          lcd.setCursor(12, 0);
          lcd.print("  ");
        }
        bar_old = bar;
        timer_marklong = millis();
      }
      
      lcd.setCursor(7, 0);
      lcd.print(bar, 0);
      lcd.print("mm");
      
      
#endif
      reciever_status = 1;
    }
    reciever_ctrl = 0;
      
        
//        
    if(DISPLAY_MODE == 1){
////////////////////////////////////////////////////////////////////////////////////
//Вывод на экран полученных данных//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
      for (int f = 1; f < 4; f++) {
        if (r_isreceived[f]) {
            
          if (true) {
          
            dysplay_tmp(0, f, r_tmp);
            lcd.print(" ");
            if (r_type[f]==THGN132) {
              lcd.print(r_hmdty[f]);
              lcd.print("% ");
            }
            else lcd.print("    ");

            if (!r_bat[f]) lcd.print(char(4)); else lcd.print(' ');
            lcd.print("     ");
            //lcd.setCursor(17, f);
            //lcd.print("   ");
            //lcd.setCursor(16, f);
            //lcd.print(" ");
              
            
          }
          if(!r_crc[f]){
            lcd.setCursor(16, f);
            lcd.print(char(5));
          }
            
        }

        //Запись на экран времени прихода пакетов/////////////////////
        for( int i=1; i < 4; i++ ){
          lcd.setCursor(17, i);
          unsigned long cdelay = (millis() - rcv_time[i]) / 60000;
          if (cdelay< LOST1) {
            lcd.print(char(3));
            lcd.print(char(2));
            lcd.print(char(1));
          }
          if (cdelay >= LOST1 && cdelay < LOST2) {
            lcd.print(' ');
            lcd.print(char(2));
            lcd.print(char(1));
          }
          if (cdelay >= LOST2 && cdelay < LOST3) {
            lcd.print(' ');
            lcd.print(' ');
            lcd.print(char(1));
          }
          if (cdelay >= LOST3) lcd.print("   ");
          if (cdelay > LOST4) {
            lcd.setCursor(0, i);
            for (byte zzz = 0; zzz < 19; zzz++)  lcd.print(' ');
            
          }
        }
      }
    }
    if(DISPLAY_MODE == 2){
      for (int f = 1; f < 4; f++) {
        if (r_isreceived[f]) {
          lcd.setCursor(0, f);
          lcd.print("Max");
          lcd.setCursor(10, f);
          lcd.print("Min");
          dysplay_tmp(3, f, r_tmp_max);
          dysplay_tmp(13, f, r_tmp_min);
        }
      }
    }
  }
//////////////////////////////////////////////////////////////////////      
//////////////////////////////////////////////////////////////////////      
//////////////////////////////////////////////////////////////////////      
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Извлекает из тактовой последовательности - битовую
//Параметры: cdptr - указатель на записанную тактовую последовательность
////////////////////////////////////////////////////////////////////////////////////////////////////
void get_bits(byte* cdptr){
  
//Сброс массивов
  byte* cdp=cdptr;
  for(bt=0 ; bt<READ_BITS*2; bt++) decode_tacts[bt]=2;
      
        
  for(bt=0 ; bt<READ_BITS*2; bt++){
        
    if ((*cdp&0xf0)>0x20 && (*cdp&0x0f)>0x04) decode_tacts[bt]=1;
    if ((*cdp&0xf0)<0x30 && (*cdp&0x0f)<0x05) decode_tacts[bt]=0;
    if ((*cdp&0xf0)<0x20 && (*cdp&0x0f)>0x04) decode_tacts[bt]=4;
    if ((*cdp&0xf0)>0x40 && (*cdp&0x0f)<0x02) decode_tacts[bt]=3;
    *cdp++;
  }
  return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Извлекает из записи канала тактовую последовательность
//Параметры: cdptr - указатель на записанные данные
// btt - смещение в тактах. Смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало
// Функция вовзращает качество или "годность" расшифровки - количесвто уверенно узнаных тактов.
// Сравнивая годность с btt=0 и btt=1 выбираем лучшую
////////////////////////////////////////////////////////////////////////////////////////////////////
int get_data(int btt, byte* cdptr){ //btt - смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало
  
  byte* cdp=cdptr;
  for(int bt=0 ; bt<READ_BITS; bt++){
    *cdp=128;
    cdp++;
  }
  cdp=cdptr;
  *cdp=(128+2);
  cdp++;
  int packet_validity=0;
  for(bt=1 ; bt<READ_BITS; bt++){
    if(decode_tacts[bt*2-btt]==0) *cdp-=1;
    if(decode_tacts[bt*2-btt]==1) *cdp+=1;
    if(decode_tacts[bt*2-2-btt]==1 && decode_tacts[bt*2-1-btt]==4) *cdp-=1;
    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;
    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>(128+1) )  packet_validity+=*cdp-128;
    if (*cdp<(128-1)) packet_validity+=128-*cdp;
    cdp++;
  }
  return packet_validity;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Прослушивание канала с частотой дискретизации 16384Гц
////////////////////////////////////////////////////////////////////////////////////////////////////
void collect(byte* cdptr, byte* dtl){
  
  // В функцию передаётся уазатель на область памяти, куда сливать данные.
  *dtl=0;
  bool cdp_prev_null;
  byte* cdp=cdptr;
  byte nulls_found=0;
  unsigned long tmp_marker=last_premarker+PER_LENGTH/32; //
  byte bt2=0;
  *cdp=0x88; //Первые два такта - единицы. Мы же поймали импульс!
  cdp++;
  //Ждём момента наступления первого считывания (конец последнего импулься зацепки + 1/16 такта)
  while (micros() <= tmp_marker);
  //Начинаем читать данные в память!
  for(bt=1 ; bt<READ_BITS*2; bt++){// чИТАЕМ максимум ПО 90 БИТ (ПОСЫЛКА thgn - 96БИТ, THN - 76 бИТ + как минимум 3 бита 111, которые мы уже нашли)
    *cdp=0;
    for(byte ckl=0; ckl<8; ckl++){      // Читаем 8 раз за полутакт
      if (digitalRead(MHZ)) *cdp+=0x10; // Измерения запиываем в старший полубайт
      tmp_marker+=PER_LENGTH/16;
      while (micros() < tmp_marker);
    }
    last_premarker+=PER_LENGTH/2;
    tmp_marker=last_premarker+PER_LENGTH/32;
    
    for(byte ckl=0; ckl<8; ckl++){
      if (digitalRead(MHZ)) *cdp+=1;    // В следующий полутакт измерения запиываем в младший  полубайт. Это экономит память.
      tmp_marker+=PER_LENGTH/16;
      while (micros() < tmp_marker);
    }
    last_premarker+=PER_LENGTH/2;
    bt2++;
    //  Каждые 8 тактов добавлять 5мкс для выравнивания периода с 976мкс до 976.56мкс
    if (bt2==8){ 
      last_premarker+=5;
      bt2=0;
    }
    tmp_marker=last_premarker+PER_LENGTH/32;

    while (micros() < last_premarker);//Ждём прихода времени следующего полутакта
    if (*cdp==0 && cdp_prev_null==1) nulls_found++;                    
    //if (*cdp==0 && (*(cdp-1)==0)) nulls_found++;
    else nulls_found=0;
    
    if (nulls_found>1) return; //Если найдено более 7 нулевых тактов подряд, значит либо жёсткая помеха, убившая пакет
                                  //Либо конец посылки. Дальше читать нет смысла.

    cdp_prev_null= (*cdp==0) ? 1 : 0;
    cdp++;                              
    *dtl+=1;
  }
  return;
} 
////////////////////////////////////////////////////////////////////////////////////////////////////
//Определение смещения пакетов друг относительно друга
//В качестве параметров передаются указатели на массивы данных
// Возваращаяется смещение
// >0 - второй пакет начался раньше, <0 - Первый пакет начался раньше
////////////////////////////////////////////////////////////////////////////////////////////////////
int 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++){
    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]++;
      s2++;
      s1++;
    }
    s2t++;
  }

  for (int i=0; i<READ_BITS; i++){
    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++){
    s2=ser2;
    s1=s1t;
    shift_score[sht]=0;
    for(byte sp=0; sp<READ_BITS-sht; sp++){
      if ((*s1 >(128+1) && *s2 >(128+1))||(*s1 <(128-1) && *s2 <(128-1)) ) shift_score[sht]++;
      s2++;
      s1++;
    }
    s1t++;
  }
// Ищем наилучшее совпадение для обоих вариантов 
  
  
  for (int i=0; i<READ_BITS; i++){
    if (shift_score[i]>best_correl_back){
      best_correl_back=shift_score[i];
      best_shift_back=i;
    }
  }
  //И возвращаем самое лучшее из двух
  if (best_correl_back > best_correl) return -best_shift_back;
  else return best_shift;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Сборка двух пакетов
//В качестве параметров передаются указатели на массивы данных
// Причём первым должен идти результирующий пакет, т.е. тот который имеет более длинную преамбулу.
//shift - смещение втрого пакета относительного первого
////////////////////////////////////////////////////////////////////////////////////////////////////
void assemble_data(byte* s1, byte* s2, int* shift){
  
  for (int g=0; g<=*shift-1; 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++;
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Создаёт кодовую посылку
//code - указатель на расшифрованную битовую последовательность
//result - указатель на кодовую посылку
//valid - указатель на карту достоверности кодовой посылки
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_info_data(byte* code, byte* result, byte* valid){
  
  byte* rd=result;
  byte* vd=valid;
  //Чистим массивы
  for (int l=0; l<PACKET_LENGTH; l++){
    *vd=0;
    *rd=0;
    vd++;
    rd++;
  }
  int csm;
  for (csm=0; csm<30;csm++){
    if (*code<128 && *(code+1)>128 && *(code+2)<128 && *(code+3)>128) break;//Найдена последовательность 0101 
    code++;
  }
  if (csm>22) return 0;// Стартовая последовательность в первых 20 битах не найдена, такой пакет этим методом не расшифруешь
  
  code+=4;//Переходим на начало считывания
  int ii=0;
  for (int i=0; i<READ_BITS-csm; i++) 
  {
    byte multipl;
    switch (ii){
      case 0: {multipl=0x01; break;}
      case 1: {multipl=0x02; break;}
      case 2: {multipl=0x04; break;}
      case 3: {multipl=0x08; break;}
    }
    if (*code==129 ) *result+=multipl;
    if (*code>129 ) {
      *result+=multipl;
      *valid+=multipl;
    }
    if (*code<127 ) *valid+=multipl;
    code++;
    ii++;
    if (ii==4) {
      ii=0;
      valid++;
      result++;
    }
  }
  return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение температуры
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
float get_temperature(byte* oregon_data){
  
  float tmprt;
  oregon_data+=8;
  //исправляем возможные ошибки:
  for (int g=0;g<4; g++)  if (*(oregon_data+g)>9) *(oregon_data+g)=*(oregon_data+g)-8;
  tmprt+=*(oregon_data)*0.1;
  tmprt+=*(oregon_data+1);
  tmprt+=*(oregon_data+2)*10;
  return (*(oregon_data+3)) ? -tmprt : tmprt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение маски годности
//validity_data - указатель на карту достоверности кодовой посылки
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_temperature_mask(byte* validity_data){
  
    return (*(validity_data+8)==0x0f && *(validity_data+9)==0x0f && *(validity_data+10)==0x0f && *(validity_data+11)==0x0f) ? 1 : 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает тип сенсора
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
word get_sensor(byte* oregon_data){
  
    return (word)(*(oregon_data))*0x1000 + (*(oregon_data+1))*0x0100 + (*(oregon_data+2))*0x10 + *(oregon_data+3);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение канала
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_channel(byte* oregon_data){
  
  byte channel;  
  switch (*(oregon_data+4))  
  {  
  case 1:  
    channel = 1;  
    break;  
  case 2:  
    channel = 2;  
    break;  
  case 4:  
    channel = 3;  
    break;  
  }  
  return channel;  
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_battery(byte* oregon_data){

  return (*(oregon_data+7) & 0x4) ? 0 : 1;  
  
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение влажности
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_humidity(byte* oregon_data){
  
  byte tmprt;
  oregon_data+=12;
  //исправляем возможные ошибки:
  for (int g=0;g<2; g++)  if (*(oregon_data+g)>9) *(oregon_data+g)=*(oregon_data+g)-8;
  tmprt=*(oregon_data);
  tmprt+=*(oregon_data+1)*10;
  return tmprt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение маски годности влажности 4 бита, старший - знак, младший -  десятые доли градуса
//validity_data - указатель на карту достоверности кодовой посылки
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_humidity_mask(byte* validity_data){
  
 return (*(validity_data+13)==0x0f && *(validity_data+14)==0x0f) ? 1 : 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает id датчика
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte get_id(byte* oregon_data){
  
  byte tmprt;
  oregon_data+=5;
  tmprt=*(oregon_data)*0x10;
  tmprt+=*(oregon_data+1);
  return tmprt;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//Проверка CRC
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
bool check_CRC(byte* oregon_data, word sensor_type){
  
  byte* pp=oregon_data;
  byte crc, resived_crc;
  crc=0;
  if (sensor_type==THGN132){
    for(int x=0; x<15; x++){
      crc+=*pp;
      pp++;  
    }
    resived_crc=(*(oregon_data+15))+(*(oregon_data+16))*0x10;
   return (resived_crc==crc)? 1 : 0;
  }

  if (sensor_type==THN132){
    for(int x=0; x<12; x++){
      crc+=*pp;
      pp++;  
    }
    resived_crc=(*(oregon_data+12))+(*(oregon_data+13))*0x10;
    return (resived_crc==crc)? 1 : 0;
  }
  return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//Востановление данныхпо типу датчика
////////////////////////////////////////////////////////////////////////////////////////////////////
void restore_data(byte* oregon_data, word sensor_type){
  
  byte* pp=oregon_data;
  if (sensor_type==THGN132){
    pp+=8;
    for(int x=0; x<6; x++){
      if(*pp>9 && x!=3) *pp-=8;
      pp++;  
    }
  }
  if (sensor_type==THN132){
    pp+=8;
    for(int x=0; x<3; x++){
      if(*pp>9) *pp-=8;
      pp++;  
    }
  }
  return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Вывод на дисплей температуры
////////////////////////////////////////////////////////////////////////////////////////////////////
void dysplay_tmp(int colmn, int raw, float* tmp_data){
  lcd.setCursor(colmn,raw);
  lcd.print("     ");
  if(*(tmp_data+raw)<-10  && *(tmp_data+raw)>=-100){
    lcd.setCursor(colmn,raw);
    lcd.print(*(tmp_data+raw));
  }
  if(*(tmp_data+raw)>-10 && *(tmp_data+raw)<0){
    lcd.setCursor(colmn+1,raw);
    lcd.print(*(tmp_data+raw));
    lcd.setCursor(colmn,raw);
    lcd.print("- ");
  }
  if(*(tmp_data+raw)>=0 && *(tmp_data+raw)<10){
    lcd.setCursor((colmn)+2,raw);
    lcd.print(*(tmp_data+raw));
  }
  if(*(tmp_data+raw)>=10 && *(tmp_data+raw)<=100){
    lcd.setCursor(colmn+1,raw);
    lcd.print(*(tmp_data+raw));
  }
  if(*(tmp_data+raw)<=100 && *(tmp_data+raw)<=100){
    lcd.setCursor(colmn+5,raw);
    lcd.print(char(0));
    lcd.print(" ");
  }
  lcd.setCursor(colmn+3, raw);
  lcd.print(char(6));        
  lcd.setCursor(colmn+6, raw);
}

 

 
snickser
Offline
Зарегистрирован: 02.07.2016

Так может проблема то как раз в антенне (куске провода), а не коде как таковом, хотя он в общем то не идеален как вы выяснили?... )

Я использую cупергетеродинный приёмник с промышленно скрученной антенной, слышит вообще весь эфир вокруг, даже брелки автосигнализаций на улице у людей... ))

https://ru.aliexpress.com/item/1set-RF-module-433-Mhz-superheterodyne-receiver-and-transmitter-Support-ASK-OOK-small-size-low-power/32571703475.html?spm=2114.13010608.0.0.Mg7Hy4&detailNewVersion=&categoryId=200003315

Porosenok
Offline
Зарегистрирован: 06.11.2016

Супергетеродинный приёмник - это, безусловно, здорово. Но это же простой путь, это не так захватывающе :-).

Меня смутило то, что сам Oregon использует простые приёмники и всё работает на приличном расстоянии. Захотелось в этом разобраться.

Что же касается антенны, то скрученная спираль уступает прямому проводу своей чувствительностью к близко расположенным проводящим предметам. В старых орегонах ставили полуволновой вибратор на скрученных спиралях. В новых погодных станциях уже прямые куски проволоки.

Кстати, при переходе с четвертьволнового на полуволновой вибратор по идее может вырасти чувствительнось приёмника, если будет согласование с входным контуром. Усиление должен быть 1.5дБ. Но вот сколько можно потерять на рассогласовании - вопрос открытый...

Porosenok
Offline
Зарегистрирован: 06.11.2016

По расшифровке информации  в Сериала может быть кое-что непонятно. Данные в посылке отображаются следующим образом:

I и O - уверенно определённые биты,

i и o - неуверенно определённые биты, нет подтверждения за счёт избыточности кода,

. - неизвестно что

 

vladiv
Offline
Зарегистрирован: 18.03.2014

Код проверен на тестовой платформе, простейший приемник с "пружинкой". Объективно дальность приема увеличилась от уличного датчика на 1,5 метра. Спасибо огромное, переделаю свой код с использованием Вашего, Porosenok! Вы проделали большую работу.

maksmkv
Offline
Зарегистрирован: 07.04.2013

Надо будет  попробовать  код, т.к. у меня код  как  и  у автора используется из сторонней ветки  и  информацию получаю, но не всегда корректную. Может быть  с данным кодом  что-либо  измениться.

Sprite
Offline
Зарегистрирован: 30.10.2016

Доброго времени суток.
Пробовал ваш скетч из этого поста http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-scientific-433mhz?page=3#comment-233870 работает отлично, спасибо вам за работу!

Sprite
Offline
Зарегистрирован: 30.10.2016

Не могли бы вы добавить поддержку датчиков v.3  в скетч из этого поста:

http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-s...

Уж очень он хорошо ловит датчики v.2.

Porosenok
Offline
Зарегистрирован: 06.11.2016

Мог бы. Но для этого надо в обязательном порядке обзавестись таким датчиком. Писать скетч без самого датчика, всё равно, что принимать роды по телефону.

Sprite
Offline
Зарегистрирован: 30.10.2016

Porosenok пишет:

Мог бы. Но для этого надо в обязательном порядке обзавестись таким датчиком. Писать скетч без самого датчика, всё равно, что принимать роды по телефону.

Хотя в этом посте человек пишет, что мой датчик не версия v.3, а версия v.2, http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-scientific-433mhz?page=5#comment-237565

Однако, ваш код его не видит, точнее видит, но не расшифровывает.

Не могли бы вы посмотреть, то что приходит в serial от этого датчика? Может подправить получится?

RECEIVING...
1)     IIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOIOOI VAL:267 SHIFT:0 
2)     IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOI VAL:267 SHIFT:0 COR: 3
RESULT IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOI 
PERIOD: 0  PACKET: CCC34F80322013855500 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     II....iii.i.i..ii...iiii.iiiiiii.i.iii......iOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOIOOI VAL:136 SHIFT:0 COR: 3
RESULT II....iii.i.i..ii...iiii.iiiiiii.i.iii......iOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOIOOI 
PERIOD: 1  WRONG  
1)     Iiiioo.................i.iiiiiii.i.iii......iOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOIOOI VAL:134 SHIFT:0 COR: 3
RESULT Iiiioo.................i.iiiiiii.i.iii......iOOOIIOOOIOOOIOOOOOOIOOOIIOOOOOIIOIOIOIOIOIOOI 
PERIOD: 1  WRONG  
1)     IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOIOOOIOOOIOOOOOOOOOOIIOOOOOIOIOOIOIOIOI VAL:267 SHIFT:0 
2)     IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOIOOOIOOOIOOOOOOOOOOIIOOOOOIOIOOIOIOIOI VAL:267 SHIFT:0 COR: 0
RESULT IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOIOOOIOOOIOOOOOOOOOOIIOOOOOIOIOOIOIOIOI 
PERIOD: 1  PACKET: BCC34F80222003825500 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOIOOOIOOOIOOIoiiiiiiiiiiiiiiiiiiii.oOIIOOOOOIOIOOIOIOIOI VAL:196 SHIFT:0 
2)     IIOOIOOOIOOOIOOIOOOOIIIOOIOOOOOOOOOOIIOOIOOIOOIIIIOOIOIOIOOIIOOO.OOOOOOIIOOOOOIOIOOIOIOIOI VAL:262 SHIFT:0 COR: 0
RESULT IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOIOOOIOOOIOOIIIIOOIOIOIOOIIOOOiOOOOOOIIOOOOOIOIOOIOIOIOI 
PERIOD: 2  PACKET: CCC31197A23203825500 VALIDITY: FFFFFFFFFFFDFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOIOIOOOOIOOOOOOOOOOIIOOOOOIOIOOIOIOIII VAL:266 SHIFT:0 
2)     IIIO.....................................................................................i VAL:8 SHIFT:0 COR: -12
RESULT IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOIOIOOOOIOOOOOOOOOOIIOOOOOIOIOOIOIOIII 
PERIOD: 3  PACKET: ACC34F80412003825700 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOIOOOIOOOIOOIOOOOOOOIOIOOOOOOOOOOIIOOIOOIOOIIIIOOIOIOOOO VAL:266 SHIFT:0 
2)     IIIIIIIIIIIIOiOIIIOIOO.i.OIIIIOOIOOOIOOOIOOIOOOOOOOIOIOOOOOOOOOOIIOOIOOiOOIi.oooi........i VAL:201 SHIFT:0 COR: -3
RESULT IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOIOOOIOOOIOOIOOOOOOOIOIOOOOOOOOOOIIOOIOOIOOIIIIOOIOIOOOO 
PERIOD: 3  PACKET: BCC31190820039C35000 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOIOOOIOOOIOOIOOOOOOOIOIOOOOOOOOOOIIOOIOOIOOIIOIOOIOIOIII VAL:267 SHIFT:0 
2)     IIIIIIIIIIIIIiiO.ooi.iiiiiiiiiii.i..i..i.....OOOOOOIOIOOOOOOOOOOIIOOIOOiOOIi.oooi........i VAL:120 SHIFT:0 COR: -3
RESULT IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOIOOOIOOOIOOIOOOOOOOIOIOOOOOOOOOOIIOOIOOIOOIIOIOOIOIOIII 
PERIOD: 4  PACKET: ACC31190820039C25700 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIIOOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIIOOOOOOIOOOOOOIOOIOIOOOOOIIIOIIOIOOOI VAL:266 SHIFT:0 
2)     IIIIIIIIIIIIIIIOIOIIOOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIIOOOOOOIOOOOOOIOOIOIOOOOOIIIOIIOIOOOI VAL:266 SHIFT:0 COR: 0
RESULT IIIIIIIIIIIIIIIOIOIIOOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIIOOOOOOIOOOOOOIOOIOIOOOOOIIIOIIOIOOOI 
PERIOD: 5  PACKET: 9CC34F807020928B5400 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIiIIIIIIIIiii.OIOIIoOIOOIIOoiIIIOOIOooioOOIOOIOooOIOOIOIOOOOOOOOOOIIOOIOOIOOIIoIOOIOIOIII VAL:209 SHIFT:0 
2)     IIOOIOOOIOOOIOOIOOOOIOOIOIOOOOOOOOOOIIOOIOOIOOIIOIOOIOIOIIIOIIIO.OOIOOIOIOOOOOIIIOIIOIOOOI VAL:261 SHIFT:0 COR: -31
RESULT IIiIIIIIIIIiii.OIOIIoOIOOIIOoiIIIOOIOOOIOOOIOOIOOOOIOOIOIOOOOOOOOOOIIOOIOOIOOIIOIOOIOIOIII 
PERIOD: 6  PACKET: 9CC31190920039C25700 VALIDITY: DF9FFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIOOOOOOIIOIIIIIOOOOIOIIIIOOOIOOOOIIIOIOOOOIOOIIOOOOOOIOOOOIOOOOOOIOOOIIO VAL:267 SHIFT:0 
2)     IOOIOOOOOIIOOIOIIOIOIOOOOOOO.............................................................. VAL:80 SHIFT:1 COR: -42
RESULT IIIIIIIIIIIIIIIOIOIOOOOOOIIOIIIIIOOOOIOIIIIOOOIOOOOIIIOIOOOOIOOIIOOOOOOIOOOOIOOOOOOIOOOIIO 
PERIOD: 6  PACKET: 0CE34F80712301201300 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     Ii...oOOOo.....iiiiii.i.ii.iii.i.iiiii.iiiiioOIOOOOIIIOIOOOOIOOIIOOOOOOIOOOOIOOOOOOIOOOIIO VAL:141 SHIFT:0 COR: -55
RESULT Ii...oOOOo.....iiiiii.i.ii.iii.i.iiiii.iiiiioOIOOOOIIIOIOOOOIOOIIOOOOOOIOOOOIOOOOOOIOOOIIO 
PERIOD: 6  WRONG  
1)     IIIIIIIIIIIIIIIOIOIOOOOOOIIOIIIIIOOIOOOIOOOIOOIOOOOIIOOIOOOOOOIOIOOOOIOIOOOOOOIIOOOIOOOIOI VAL:264 SHIFT:0 
2)     IOOIIOOOOIIOIoOOOOOOIO.................................................................... VAL:57 SHIFT:1 COR: -42
RESULT IIIIIIIIIIIIIIIOIOIOOOOOOIIOIIIIIOOIOOOIOOOIOOIOOOOIIOOIOOOOOOIOIOOOOIOIOOOOOOIIOOOIOOOIOI 
PERIOD: 7  PACKET: 0CE31190318241811500 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIIOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOOIIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII VAL:266 SHIFT:0 
2)     IOOOOoiiiiii.............................................................................. VAL:11 SHIFT:1 COR: -32
RESULT IIIIIIIIIIIIIIIOIOIIOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOOIIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII 
PERIOD: 8  PACKET: DCC34F80891092886700 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIOOOIOOOOOOOIIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIIIIIIIIiIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII VAL:261 SHIFT:0 COR: -5
RESULT IIOOOIOOOOOOOIIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIIIIIIIIiIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII 
PERIOD: 8  WRONG  
1)     IIIIIIIIIIIIIIIOIOiiiiiiiiiiiiiiiiiiiiiioooi.OIIIIIIIIiIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII VAL:178 SHIFT:0 COR: -59
RESULT IIIIIIIIIIIIIIIOIOiiiiiiiiiiiiiiiiiiiiiioooi.OIIIIIIIIiIOOIIOOOOOOOIOOIOIOOOOOIOOOIOIIOIII 
PERIOD: 8  PACKET: FFFFF19FF91092886700 VALIDITY: 000000CF7FFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOIOOIIOOOOOOOIOOIOIOOOOOIOIOOOIIOOIO VAL:266 SHIFT:0 
2)     IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOIOOIIOOOOOOOIOOIOIOOOOOIOIOOOIIOOIO VAL:266 SHIFT:0 COR: 0
RESULT IIIIIIIIIIIIIIIOIOIOOIIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIIOOIOOIIOOOOOOOIOOIOIOOOOOIOIOOOIIOOIO 
PERIOD: 10  PACKET: CCC34F80391092826200 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOIOOOIOOOIOOIIOOOOOOOIIOOOOOOOOOOIIOOIOOIOOIIIOIIOOIOIOII VAL:267 SHIFT:0 
2)     IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOIOOOIOOOIOOIIOOOOOOOIIOOOOOOOOOOIIOOIOOIOOIIIOIIOOIOIOI VAL:266 SHIFT:0 COR: 1
RESULT IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOIOOOIOOOIOOIIOOOOOOOIIOOOOOOOOOOIIOOIOOIOOIIIOIIOOIOIOI 
PERIOD: 11  PACKET: BCC31191030039CD4500 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOOOIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIO VAL:267 SHIFT:0 
2)     II.oo.......i.i..iiiiii.iiii.iiiii.ii.i.i.iiiOIIOOOOOOOIIOOOOOOOOOOIIOOIOOIOOIIIOIIOOIOIOI VAL:135 SHIFT:0 COR: 0
RESULT IIIIIIIIIIIIIIIOIOIIIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOOOOOIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIO 
PERIOD: 11  PACKET: BCC34F800910928E5300 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
1)     IIOOOIOOOOOOOOIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIOOOOOIiIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIO VAL:262 SHIFT:0 COR: 0
RESULT IIOOOIOOOOOOOOIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIOOOOOIiIOOIIOOOOOOOIOOIOIOOOOOIOIIIIOIOIIO 
PERIOD: 11  WRONG  
1)     IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIOIOOOOIIOOOOOOOOOOOIIOOOOOIIOOIIOIOIOI VAL:266 SHIFT:0 
2)     IIIO...................................................................................... VAL:8 SHIFT:0 COR: -12
RESULT IIIIIIIIIIIIIIIOIOIOIOIOOIIOOIIIIOOOOIOIIIIOOOIOOOOIOIOOOOIIOOOOOOOOOOOIIOOOOOIIOOIIOIOIOI 
PERIOD: 13  PACKET: ACC34F80581003895500 VALIDITY: FFFFFFFFFFFFFFFFFF70 WRONG  
 

Подправленный код из этого поста у меня работает со всеми датчиками:

 http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-scientific-433mhz?page=4#comment-237285

Porosenok
Offline
Зарегистрирован: 06.11.2016

Ваши датчики скорее всего версии 2, но пакеты явно длиннее и у них другой формат. Можно научиься читать и их, но это делается не за пять минут и даже не за вечер. У меня, к сожалению, нет в настоящее время никакого стимула, да и возможности этим заниматься. Хотя бы потому, что UNO это может уже не потянуть по количеству необходимой памяти. Нужна будет как минимум MEGA или Wemos D1, например.

Для того, чтобы считывать длинные пакеты до конца нужно для начала увеличить количество считываемых байтов изменив в скетче пераметры READ_BITS  и  READ_BITS2. Но это приведёт, что 132-ые датчики будут читаться хуже - вторая резервная посылка будет читаться неправильно. Т.е. желательно переписать процедуру оцифровки канала в память. Остальное: расшифровка полученных данные, подсчёт CRC - это уже просто, если найти соответствующие руководящие материалы.

Sprite
Offline
Зарегистрирован: 30.10.2016

Porosenok пишет:

Ваши датчики скорее всего версии 2, но пакеты явно длиннее и у них другой формат. Можно научиься читать и их, но это делается не за пять минут и даже не за вечер. У меня, к сожалению, нет в настоящее время никакого стимула, да и возможности этим заниматься. Хотя бы потому, что UNO это может уже не потянуть по количеству необходимой памяти. Нужна будет как минимум MEGA или Wemos D1, например.

Для того, чтобы считывать длинные пакеты до конца нужно для начала увеличить количество считываемых байтов изменив в скетче пераметры READ_BITS  и  READ_BITS2. Но это приведёт, что 132-ые датчики будут читаться хуже - вторая резервная посылка будет читаться неправильно. Т.е. желательно переписать процедуру оцифровки канала в память. Остальное: расшифровка полученных данные, подсчёт CRC - это уже просто, если найти соответствующие руководящие материалы.

У меня Mega 2560.

Вас понял, жаль.

sotyi
Offline
Зарегистрирован: 05.01.2017

Здравствуйте. А почему при компиляции выдаёт ошибку?

"POSITIVE" was not declared in this scope

в строке:

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

Как я понял POSITIVE не задекларирована.

Porosenok
Offline
Зарегистрирован: 06.11.2016

Можно попробовать поменять POSITIVE на 0 или 1. Но мне кажется, что это проблемы не решит, начнёт ругаться на другое место.

Вижу две причины  :

- Не та библиотека для работы с индикатором,

- Где-то при копировании пропала фигурная скобка.

 

Sprite
Offline
Зарегистрирован: 30.10.2016

sotyi пишет:

Здравствуйте. А почему при компиляции выдаёт ошибку?

"POSITIVE" was not declared in this scope

в строке:

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

Как я понял POSITIVE не задекларирована.


Скорее всего библиотека LiquidCrystal_I2C lcd у вас не такая, как у автора.

macros
Offline
Зарегистрирован: 07.11.2016

Спасибо за проект, я взял ваш код за основу в своем проекте метеостанции. Родная станция прием все же осуществляет более стабильно, думаю дело в приемнике.

Посмотрите функцию dysplay_tmp, помоему там вкралась ошибка для температуры -10. В 1002 строчку нужно изменить <-10 на <=-10.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Sprite пишет:
sotyi пишет:

Здравствуйте. А почему при компиляции выдаёт ошибку?

"POSITIVE" was not declared in this scope

в строке:

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

Как я понял POSITIVE не задекларирована.

Скорее всего библиотека LiquidCrystal_I2C lcd у вас не такая, как у автора.

Правильная библиотека тут

Porosenok
Offline
Зарегистрирован: 06.11.2016

macros пишет:

Посмотрите функцию dysplay_tmp, помоему там вкралась ошибка для температуры -10. В 1002 строчку нужно изменить <-10 на <=-10.

Спасибо, поправлю. На днях как раз решил  доловить клопов в скетче. Заодно и в класс завернуть, для удобства подключения.

Что касается лучшего приёма у родной станции - так она же от батареек работает, и процессор там медленный и экономный - помех практически нет. У меня зреет идея организовать не только отдельное питания приёмника, но и попробовать его полностью гальванически отвязать.

 

Sprite
Offline
Зарегистрирован: 30.10.2016

Porosenok пишет:

macros пишет:

Посмотрите функцию dysplay_tmp, помоему там вкралась ошибка для температуры -10. В 1002 строчку нужно изменить <-10 на <=-10.

Спасибо, поправлю. На днях как раз решил  доловить клопов в скетче. Заодно и в класс завернуть, для удобства подключения.

Что касается лучшего приёма у родной станции - так она же от батареек работает, и процессор там медленный и экономный - помех практически нет. У меня зреет идея организовать не только отдельное питания приёмника, но и попробовать его полностью гальванически отвязать.

 

Не могли бы вы выложить используемые вами библиотеки? Что то не хочет компилироваться скетч с библиотеками из сети.

Porosenok
Offline
Зарегистрирован: 06.11.2016

Дайте немного времени, допилю свою бибиотеку и выложу всё сразу...

Sprite
Offline
Зарегистрирован: 30.10.2016

Porosenok пишет:

Дайте немного времени, допилю свою бибиотеку и выложу всё сразу...

Вы хотите часть скетча перенести в библиотеку?
Если так, что плохо, поскольку ваш скетч видит только два типа орегоновских датчика.

Porosenok
Offline
Зарегистрирован: 06.11.2016

Нет, это наоборот хорошо. Это позволит сократить код скетча, сделать его более читаемым, и упростит подключение другх библиотек для чтение других типов датчиков.

snickser
Offline
Зарегистрирован: 02.07.2016

Подскажите, а из-за чего видно эти два датчика

1)     IIIIIIIIIIIIIOIOIIOOOIOIIOIOOOOOOIOOOIIOIIIOIOOOOOOIOOOOOOOOOOOOioiOOIIIOOOOOOOIIIIOO.o.o.OOi.oo SIZE:192 VAL:236 SYN:13 SHIFT:0
2)     IIIIIIOIOIIOOOIOIIOIOOOOOOIOOOIIOIIIOIOOOOOOiOOOOOOOOOOOOioiOOIIIOOOOOOOIIIiOO.o.o.OO.oooooooooo SIZE:192 VAL:208 SYN:6 SHIFT:0 COR: -7
RESULT IIIIIIOIOIIOOOIOIIOIOOOOOOIOOOIIOIIIOIOOOOOOIOOOOOOOOOOOOioiOOIIIOOOOOOOIIIIOO.o.o.OO.oooooooooo 
PERIOD:	4	1D201BB04008270C30 TYPE: THGN132N CHNL: 1 TMP: -0.4C HUM: 72% BAT: F ID: BB PROC. TIME: 525ms 
1)     IIIIIIIIIIIIIIOIOIIOOOIOIIOIOOOOOOIOOOOIIIOOIIOOOOIOIOOOOOOOOOOOOIOIOOIIIOOOIIIOIIOOIOIIIOOIOI.o SIZE:192 VAL:278 SYN:14 SHIFT:0
2)     IIIIIIIIIIIIIIIOIOIIOOOIOIIOIOOOOOOIOOOOIIIOOIIOOOOIOIOOOOOOOOOOOOIOIOOIIIOO..oooooooooo         SIZE:174 VAL:224 SYN:15 SHIFT:0 COR: 1
RESULT IIIIIIIIIIIIIIOIOIIOOOIOIIOIOOOOOOIOOOOIIIOOIIOOOOIOIOOOOOOOOOOOOIOIOOIIIOOOIIIOIIOOIOIIIOOIOI.o 
PERIOD:	4	1D201EC0500827CD47 TYPE: THGN132N CHNL: 1 TMP: -0.5C HUM: 72% BAT: F ID: EC PROC. TIME: 509ms 

второй (0xBB) является ретранслятором на ардуино,

но не видно этот датчик

1)     IOOOOOOOOOOOo...o.......................oi..i..i...iOOOOOIOOOOOOOOioIiOOooo.................oooo SIZE:192 VAL:78 SYN:255 SHIFT:1
2)     Io..oo.IIii.o....i......................i.....ioOOOOOOOIOIIOOOOOIIIIioo.oo.......oo              SIZE:164 VAL:60 SYN:255 SHIFT:1 COR: -2
RESULT IOOOOOOIIOi.o....i......................i.....ioOOOOOOOIOIIOOOOOIIIIOOo.oo.......oo              

который лежит рядом с приёмником и является почти (канал другой) точной копией 0xBB ?

Хотя с этого датчика сигнал принимается достаточно стабильтно и успешно:

25.934 OSV2 1A2D43BB992040334B56 4 bb 20.9 34% 9
26.273 OSV2 1A2D43BB992040334B56 4 bb 20.9 34% 9
 

Porosenok
Offline
Зарегистрирован: 06.11.2016

Без осциллограмм сложно сказать. Скорее всего он не точная копия. По провалам в центре могу предположить, что незначительно отличается частота передачи данных. Родная станция, я так понимаю, видит эту копию?

snickser
Offline
Зарегистрирован: 02.07.2016

Да, вы правы, ваш код даже строже чем базовая станция, расхождение в микросекунду чувствует... )

Подкорректировал задержку - заработало.

Кстати, есть орегон датчики у которых каналы не с 1-3, а с 1 до 5. У таких 3-й канал это 0x33, а 4-й канал кодируется как 0x43, ваш код такие не видит.

 

Porosenok
Offline
Зарегистрирован: 06.11.2016

snickser пишет:

Кстати, есть орегон датчики у которых каналы не с 1-3, а с 1 до 5. У таких 3-й канал это 0x33, а 4-й канал кодируется как 0x43, ваш код такие не видит.

Это-то несложно поправить, особенно если длина пакета не превышает THGN132.

Porosenok
Offline
Зарегистрирован: 06.11.2016

snickser пишет:

 ваш код даже строже чем базовая станция, расхождение в микросекунду чувствует... )

К сожалению, пока так. Но фирменные датчики очень чётко выдерживают частоту передачи данных, род них доработка не требуется...

snickser
Offline
Зарегистрирован: 02.07.2016

У меня на других моих ардуинах этот код ничего не слышит... Может конечно китайские ардуины глючные, но вообще странно это очень. Единственное что заметил, импульсы от передатчика приходят в интервалах

444..528
928..1032

 

Porosenok
Offline
Зарегистрирован: 06.11.2016

Не знаю, что и сказать. Китайские арудины, конечно, иные по настройкам, но на приём это влиять не должно

valesevent
Offline
Зарегистрирован: 10.08.2017

Добрый день, Porosenok, а поделитесь пожалуйста кодом передатчика.

oregon_v23
Offline
Зарегистрирован: 21.08.2018

Спасибо за проект, использую библиотеку Oregon_NR, существует ли возможность добавить расшифровку датчика BTHGN129, в мониторе порта датчик определяется 

TIME: 510sec 5D535B5033203540C021xxxxxxxxxxx CORRUPTED PACKET 
TIME: 581sec 5D535B5033203540C021xxxxxxxxxxx CORRUPTED PACKET 
TIME: 652sec 5D535B5043203540C022xxxxxxxxxxx CORRUPTED PACKET 
TIME: 723sec 5D535B5014205540C022xxxxxxxxxxx CORRUPTED PACKET 
TIME: 794sec 5D535B5055204500C022xxxxxxxxxxx CORRUPTED PACKET 
TIME: 865sec 5D535B5026203500C027xxxxxxxxxxx CORRUPTED PACKET 
TIME: 936sec 5D535B5016203500C026xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1007sec 5D535B5085202500C023xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1078sec 5D535B5065202500C021xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1149sec 5D535B5035203500C027xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1220sec 5D535B5015203500C02D4xxxxxxxxxx CORRUPTED PACKET 
TIME: 1291sec 5D535B5005203540C020xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1362sec 5D535B5094204540C021xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1433sec 5D535B5084204540C020xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1504sec 5D535B5174204540C020xxxxxxxxxxx CORRUPTED PACKET 
TIME: 1575sec 5D535B5164204540C027xxxxxxxxxxx CORRUPTED PACKET 
Porosenok
Offline
Зарегистрирован: 06.11.2016

Конечно возможность есть. Нет в наличии датчика и свободного времени.  Задача не совсем простая - времени нужно много

kaluganin
kaluganin аватар
Offline
Зарегистрирован: 25.12.2015

Подскажите, используя вашу библиотеку  почему при просмотре инфы с порта идет информация о посылках 1.2. а потом только то, что выводишь через print ? можно это как-то отключить??

Porosenok
Offline
Зарегистрирован: 06.11.2016

oregon.capture(0);

vladiv
Offline
Зарегистрирован: 18.03.2014

Добрый вечер!

На днях один из датчиков Oregon Scientific THGN132N (уличный), "мявкнув" в эфир несколько некорректных значений, перестал подавать признаки жизни. Замена элемента питания результата не принесла. Путем долгого поиска, удалось выяснить, что у самих метеостанций нередко выходят из строя кварцы. Кварц находится рядом с "кляксой", с обратной стороны. Номинал 32 кГц. Лучше брать с материнских плат или калькуляторов. Все работает.

Porosenok
Offline
Зарегистрирован: 06.11.2016

Да, я тоже за 10 лет эксплуатации двух таких метеостанций этот часовой кварц менял неоднократно.

kaluganin
kaluganin аватар
Offline
Зарегистрирован: 25.12.2015

у меня другая проблема... сдох на нем датчик влажности... заменил на похожий с али.. точность приемлимая