Чтение и эмуляция датчиков Oregon Scientific (433Mhz)

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

Утро бодрое snickser

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

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

 

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

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

Да нет у вас там никаких датчиков v.3... успакойтесь, все ваши датчики v2 ;)

Для правки кода тов. Porosenok лучше обратиться к нему...

 

 

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

snickser пишет:

Да нет у вас там никаких датчиков v.3... успакойтесь, все ваши датчики v2 ;)

Если так, то почему же ни один код в котором используется только v.2 не работает с RTGN318, а с добавлением v.3 начинает работать?

snickser пишет:

Для правки кода тов. Porosenok лучше обратиться к нему...

Написал в теме его проекта, но тишина. На этом форуме ведь нет личных сообщений?

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

Ну, те скечи у вас не работают совсем по иным причинам, нежели наличие или отсутствие v3 декодера. В первом посте декодер v3 есть, но там кривой v2. А код с #113 в чистом виде учитывает только THN132N (EA4C) и просто игнорирует остальные датчики. Потому его надо немного поправить руками чтоб он был под ваши нужды.

Я же вам дал скомбинированный универсальный код с первой страницы и декодер v2 из поста №113, внеся туда проверку контрольной суммы и показ информации по вашей просьбе.

 

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

snickser пишет:

Я же вам дал скомбинированный код первой страницы и декодер v2 из поста №113, внеся туда проверку контрольной суммы и показ информации по вашей просьбе.

Да, всё верно, спасибо вам ещё раз за помощь.

Но код от Porosenok, как мне кажется, лучше ловит сигнал от сенсора, вот я и хочу, чтобы он понимал все мои сенсоры.

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

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

 

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

snickser пишет:

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

 


Возможно вы и правы.
Буду оба кода проверять на дальность и сравнивать.

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

snickser пишет:

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

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

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

snickser пишет:
Вот, держите, возможно сработает... ;)

    if( data[8] == (Sum(8,data)-0xa)&0xFF ){
      Serial.print(" "+String(channel(data))+" "+String(serial(data),HEX));
      Serial.print(" "+String(temperature(data),1)+" "+String(humidity(data))+"%");
      Serial.print(" "+String(battery(data)));
    } else {
      int sum = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff);
      if( (sum&0xF) == (data[6]>>4) && (sum>>4) == (data[7]&0xF) ){
        Serial.print(" "+String(channel(data))+" "+String(serial(data),HEX));
        Serial.print(" "+String(temperature(data),1));
        Serial.print(" "+String(battery(data)));
      } else {
        Serial.print(" Checksum error");
      }
    }
    Serial.println();

    decoder.resetDecoder();
}

Подскажите пожалуйста, по строчке Serial.print(" "+String(battery(data))); на выходе пишет "0"

138.112 OSV2 EA4C40DC20243044 3 dc 24.2 0
 
191.422 OSV2 BACC438F302310835594 4 8f 23.3 31% 0
 

Можно ли как то это поменять?

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

Можно, а на что вы хотите поменять ноль?... )

Датчик возвращает только два значения, 0 - когда батарейка исправна, и 0хС когда уже совсем плохо, иногда в этом поле появляется 0x8 - но это фуфел какой-то... )

 

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

snickser пишет:

Можно, а на что вы хотите поменять ноль?... )

Датчик возвращает только два значения, 0 - когда батарейка исправна, и 0хС когда уже совсем плохо, иногда в этом поле появляется 0x8 - но это фуфел какой-то... )

Отлично, спаибо за разъяснение, теперь ясно.

Хочу вывести на экран значек пустой батарейки, когда от датчика придёт "0хС".

Проверяю коды, который переделали для меня вы и код от Porosenok.

При абсолютно одинаковых условиях, код от Porosenok ловит показания от датчика, а переделанный код нет. Если датчики поднести ближе, то переделанный код начинает ловит датчик.

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

 

 

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

Думаю всё дело в хорошей антенне на приёмнике!... Вы какую используете?

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

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

snickser пишет:

Думаю всё дело в хорошей антенне на приёмнике!... Вы какую используете?

В том то и дело, что я решил сравнить именно коды, при абсолютно равных условиях "железа".

Приёмник, Ардуину и всё остальное не трогаю, только заливаю скетч и смотрю в serial, затем заливаю другой скетч и опять смотрю в сериал, а потом сравниваю результаты.

Антенна кабель в изоляйии длинной 16,5 мм и толщиной 1,8 мм.

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

А, ну понятно, там да, код имеющий "защиту" от помех всегда выиграет, но хорошая антенна - уже залог успеха!... )

Рекомендую такой приёмник https://ru.aliexpress.com/store/product/1set-RF-module-433-Mhz-superhete...

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

ИМХО в условиях помещения, уже без разницы, какая антенна. Это на улице, где от датчика идёт бегущая волна антенна играет далеко не последнюю роль. А в помещении, где из-за переотражений в комнате может быть совершенно непредсказуемая интерференционная картина нужно просто искать место, где лучше приём. Вы когда-нибудь на комнатную телевизионную антенну пытались поймать сигнал? Вот тут то же самое, те же частоты, только поляризация вертикальная, что хуже для приёма - больше переотражений.

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

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

snickser пишет:

А, ну понятно, там да, код имеющий "защиту" от помех всегда выиграет, но хорошая антенна - уже залог успеха!... )

Рекомендую такой приёмник https://ru.aliexpress.com/store/product/1set-RF-module-433-Mhz-superhete...

Я заказал такой https://ru.aliexpress.com/item/RXB6-433Mhz-Superheterodyne-Wireless-Receiver-Module/32651921064.html?spm=2114.13010608.0.0.wT36FY, жду.

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

snickser пишет:

Можно, а на что вы хотите поменять ноль?... )

Датчик возвращает только два значения, 0 - когда батарейка исправна, и 0хС когда уже совсем плохо, иногда в этом поле появляется 0x8 - но это фуфел какой-то... )

Подскажите пожалуйста, что я сделал не так?

        if( String(battery(data)) == 0){
          lcd.setCursor(9,0);
          lcd.print("Bat:OK");
          }
          else {
          lcd.setCursor(9,0);
          lcd.print("Bat:LOW");
          }

Выводит всегда: "Bat:LOW"

В serial при этом пишет:

34.110 OSV2 DACC438F50231083592C 4 8f 23.5 31% 0

Porosenok
Offline
Зарегистрирован: 06.11.2016
//if( String(battery(data)) == 0)
if( battery(data) == 0)

 

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

Porosenok пишет:

//if( String(battery(data)) == 0)
if( battery(data) == 0)

 

Благодарю.

 

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

snickser пишет:

Можно, а на что вы хотите поменять ноль?... )

Датчик возвращает только два значения, 0 - когда батарейка исправна, и 0хС когда уже совсем плохо, иногда в этом поле появляется 0x8 - но это фуфел какой-то... )

 

Подскажите, может быть такое, что при нормальном уровне заряда батареи не всегда выводиться "0"?
У меня сейчас выдает "1". Причём число одинаковое для всех датчиков. Батарейки новые.

upd :
Стало ввдавать "0". Всё ОК.

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

Да, может, туда иногда лезет всякая чушь, надо смотреть есть ли там 0хС, а всё остальное игнорировать.

lcd.setCursor(9,0);
if( battery(data) == 0xС ){
  lcd.print("Bat:LOW");
} else {
  lcd.print("Bat:OK");
}

 

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

snickser пишет:

Да, может, туда иногда лезет всякая чушь, надо смотреть есть ли там 0хС, а всё остальное игнорировать.

if battery(data) == 0xС ){
  lcd.setCursor(9,0);
  lcd.print("Bat:LOW");
} else {
  lcd.setCursor(9,0);
  lcd.print("Bat:OK");
}

 


Вас понял.
Вроде пробовал указывать это условие
if (battery(data) == 0xС ), но компилятор ругался. Завтра попробую ещё раз.

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

Может попробовать так?

if (battery(data) == 0x0С ) 

 

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

snickser пишет:

Да, может, туда иногда лезет всякая чушь, надо смотреть есть ли там 0хС, а всё остальное игнорировать.

lcd.setCursor(9,0);
if( battery(data) == 0xС ){
  lcd.print("Bat:LOW");
} else {
  lcd.print("Bat:OK");
}

 

Работает, спасибо!

4ishops
Offline
Зарегистрирован: 06.10.2012

Sprite пишет:

Работает, спасибо!

 

Вы по итогам своих доработок добавьте ваш итоговый скетч сюда, ок?

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

4ishops пишет:

Sprite пишет:

Работает, спасибо!

 

Вы по итогам своих доработок добавьте ваш итоговый скетч сюда, ок?


Обязательно.
Но пока я только разобрался с выводом результата на LCD 1602.
К отправке данных на narodmon даже не приступал.
Параллельно пытаюсь запустить скетч на esp8266.

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

Sprite][quote=4ishops пишет:

Параллельно пытаюсь запустить скетч на esp8266.

Вот тут вас может ждать много сюрпризов. Я, например, долго не мог понять, почему стэк переполняется в случайные моменты. Оказалось при шумном эфире процессор слишком часто ходит в прерывание.

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

Porosenok] </p> <p>[quote=Sprite пишет:
4ishops пишет:

Параллельно пытаюсь запустить скетч на esp8266.

Вот тут вас может ждать много сюрпризов. Я, например, долго не мог понять, почему стэк переполняется в случайные моменты. Оказалось при шумном эфире процессор слишком часто ходит в прерывание.


Я застрял намного раньше)))
1) На какой пин подключать приемник.
2) Заставить работать LCD i2c.

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

Sprite пишет:

Я застрял намного раньше))) 1) На какой пин подключать приемник. 2) Заставить работать LCD i2c.

1. На разных платах названия разные. Например, если написан вывод на пин2, то это должен быть GPIO2 процессора. А далее надо смотреть схему конкретной платы (wemos, nodemcu,...)

2. Вроде бы видел где-то  библиотеки I2C LCD под ESP процессоры. Но пока не разбирался

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

И не забудьте главное - ESP не выносит 5В на выводах. Горит...

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

Porosenok пишет:

Sprite пишет:

Я застрял намного раньше))) 1) На какой пин подключать приемник. 2) Заставить работать LCD i2c.

1. На разных платах названия разные. Например, если написан вывод на пин2, то это должен быть GPIO2 процессора. А далее надо смотреть схему конкретной платы (wemos, nodemcu,...)


Скетч при этом надо переписывать? Инициировать порт?

Porosenok] </p> <p>[quote=Sprite пишет:

2. Вроде бы видел где-то  библиотеки I2C LCD под ESP процессоры. Но пока не разбирался


Много разных перепробовал. На какие то компилятор ругается, какие то загружаются, но не рабоиают. Буду разбираться.

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

Porosenok пишет:

И не забудьте главное - ESP не выносит 5В на выводах. Горит...


Понял, спасибо за совет.

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

4ishops пишет:

Sprite пишет:

Работает, спасибо!

 

Вы по итогам своих доработок добавьте ваш итоговый скетч сюда, ок?

Пока получилось так.

Код:

// ATmega 2560
// Приёмник подключается к PWM(2)
// LCD подключается SCL -> SCL(21); SDA -> SDA(20)


#define PORT 2
#define printByte(args) write(args);

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f,16,2);  // Адрес LCD 0x3f, может быть 0x27

uint8_t cels[8]  = {0x2,0x5,0x5,0x2}; // Значок цельсия
uint8_t batlow[8]  = {0xE,0x1f,0x11,0x11,0x11,0x11,0x1f,0x1f}; // Значок пустой батарейки
uint8_t batok[8] = {0xE,0x1f,0x11,0x1f,0x1f,0x1f,0x1f,0x1f};  // Значок полной батарейки

class DecodeOOK {
protected:
    byte total_bits, bits, flip, state, pos, data[25];

    virtual char decode (word width) =0;
    
public:

    enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };

    DecodeOOK () { resetDecoder(); }

    bool nextPulse (word width) {
        if (state != DONE)
        
            switch (decode(width)) {
                case -1: resetDecoder(); break;
                case 1:  done(); break;
            }
        return isDone();
    }
    
    bool isDone () const { return state == DONE; }

    const byte* getData (byte& count) const {
        count = pos;
        return data; 
    }
    
    void resetDecoder () {
        total_bits = bits = pos = flip = 0;
        state = UNKNOWN;
    }
    
    // add one bit to the packet data buffer
    
    virtual void gotBit (char value) {
        total_bits++;
        byte *ptr = data + pos;
        *ptr = (*ptr >> 1) | (value << 7);

        if (++bits >= 8) {
            bits = 0;
            if (++pos >= sizeof data) {
                resetDecoder();
                return;
            }
        }
        state = OK;
    }
    
    // store a bit using Manchester encoding
    void manchester (char value) {
        flip ^= value; // manchester code, long pulse flips the bit
        gotBit(flip);
    }
    
    // move bits to the front so that all the bits are aligned to the end
    void alignTail (byte max =0) {
        // align bits
        if (bits != 0) {
            data[pos] >>= 8 - bits;
            for (byte i = 0; i < pos; ++i)
                data[i] = (data[i] >> bits) | (data[i+1] << (8 - bits));
            bits = 0;
        }
        // optionally shift bytes down if there are too many of 'em
        if (max > 0 && pos > max) {
            byte n = pos - max;
            pos = max;
            for (byte i = 0; i < pos; ++i)
                data[i] = data[i+n];
        }
    }
    
    void reverseBits () {
        for (byte i = 0; i < pos; ++i) {
            byte b = data[i];
            for (byte j = 0; j < 8; ++j) {
                data[i] = (data[i] << 1) | (b & 1);
                b >>= 1;
            }
        }
    }
    
    void reverseNibbles () {
        for (byte i = 0; i < pos; ++i)
            data[i] = (data[i] << 4) | (data[i] >> 4);
    }
    
    void done () {
        while (bits)
            gotBit(0); // padding
        state = DONE;
    }
};

// 433 MHz decoders



class OregonDecoderV2 : public DecodeOOK 
{
   public:  
  OregonDecoderV2() {}

      // add one bit to the packet data buffer
  virtual void gotBit (char value) 
      {
         if(!(total_bits & 0x01))
         {
            data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
         }

         total_bits++;
         pos = total_bits >> 4;

         if (pos >= sizeof data) 
         {
            resetDecoder();
            return;
         }
         state = OK;
      }

  virtual char decode(word width) 
      {
         if (200 <= width && width < 1200) 
         {
            byte w = width >= 700;

            switch (state) 
            {
               case UNKNOWN:
                  if (w != 0) 
                  {
                     // Long pulse
                     ++flip;
                  } 
                  else if (w == 0 && 24 <= flip) 
                  {
                     // Short pulse, start bit
                     flip = 0;
                     state = T0;
                  } 
                  else 
                  {
                     // Reset decoder
                     return -1;
                  }
                  break;
               case OK:
                  if (w == 0) 
                  {
                     // Short pulse
                     state = T0;
                  }
                  else 
                  {
                     // Long pulse
                     manchester(1);
                  }
                  break;
               case T0:
                  if (w == 0) 
                  {
                     // Second short pulse
                     manchester(0);
                  } 
                  else 
                  {
                     // Reset decoder
                     return -1;
                  }
               break;
            }
         } 
         else if (width >= 2500  && pos >= 8) 
         {
            return 1;
         } 
         else 
         {
            return -1;
         }
         return 0;
      }

};


class OregonDecoderV3 : public DecodeOOK {
public:
    OregonDecoderV3() {}
    
    // add one bit to the packet data buffer
    virtual void gotBit (char value) {
        data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
        total_bits++;
        pos = total_bits >> 3;
        if (pos >= sizeof data) {
            resetDecoder();
            return;
        }
        state = OK;
    }
    
    virtual char decode (word width) {
        if (200 <= width && width < 1200) {
            byte w = width >= 700;
            switch (state) {
                case UNKNOWN:
                    if (w == 0)
                        ++flip;
                    else if (32 <= flip) {
                        flip = 1;
                        manchester(1);
                    } else
                        return -1;
                    break;
                case OK:
                    if (w == 0)
                        state = T0;
                    else
                        manchester(1);
                    break;
                case T0:
                    if (w == 0)
                        manchester(0);
                    else
                        return -1;
                    break;
            }
        } else {
            return -1;
        }
        return  total_bits == 80 ? 1: 0;
    }
};


OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;

volatile word pulse;

void ext_int_1(void) {
    static word last;
    // determine the pulse length in microseconds, for either polarity
    pulse = micros() - last;
    last += pulse;
}

//
// Oregon packet decoder
//

float temperature(const byte* data)
{
   int sign = (data[6]&0x8) ? -1 : 1;
   float temp = ((data[5]&0xF0) >> 4)*10 + (data[5]&0xF) + (float)(((data[4]&0xF0) >> 4) / 10.0);
   return sign * temp;
}

byte humidity(const byte* data)
{
   return (data[7]&0xF) * 10 + ((data[6]&0xF0) >> 4) ;
}

float humi_ext(const byte* data)
{
   return  humidity(data) + ((data[7]&0xF0)>>4)/10.0 ;
}

byte battery(const byte* data)
{
   return (data[4] & 0xF) ;
}

byte serial(const byte* data)
{
   return (data[3]);
}

byte channel(const byte* data)
{
   byte channel;
   switch (data[2])
   {
      case 0x10:
         channel = 1;
         break;
      case 0x20:
         channel = 2;
         break;
      case 0x40:
         channel = 3;
         break;
      case 0x13:
         channel = 1;
         break;
      case 0x23:
         channel = 2;
         break;
      case 0x33:
         channel = 3;
         break;
      case 0x43:
         channel = 4;
         break;
      case 0x53:
         channel = 5;
         break;
   }
 return channel;
} 

int Sum(byte count, const byte* data)
{
  int s = 0;
 
  for(byte i = 0; i<count;i++)
  {
    s += (data[i]&0xF0) >> 4;
    s += (data[i]&0xF);
  }
 
  if(int(count) != count)
    s += (data[count]&0xF0) >> 4;
 
  return s;
}

////////////////////////////////////////////////////
////////////////////////////////////////////////////
/////////// Вывод результата в Serial  /////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////

void reportSerial (const char* s, class DecodeOOK& decoder) {
    byte pos;
    const byte* data = decoder.getData(pos);
    Serial.print(millis()/1000.,3);
    Serial.print(" ");
    Serial.print(s);
    Serial.print(' ');
    for (byte i = 0; i < pos; ++i) {
        Serial.print(data[i] >> 4, HEX);
        Serial.print(data[i] & 0x0F, HEX);
    }

    if( data[8] == (Sum(8,data)-0xa)&0xFF )
    {
      Serial.print(" Bat.: "+String(battery(data)));
      Serial.print(" ID: "+String(serial(data),HEX));
      Serial.println();
      Serial.print("Ch."+String(channel(data)));
      Serial.println();
      Serial.print("T="+String(temperature(data),1)+"C"+" H="+String(humidity(data))+"%");
      Serial.println();
          if(battery(data) == 0xC){
          Serial.print("Bat: LOW");
          Serial.println();}
          else {
          Serial.print("Bat: OK");
          Serial.println();}

      }
      else
      {
      int sum = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff);
      if( (sum&0xF) == (data[6]>>4) && (sum>>4) == (data[7]&0xF) ){
      Serial.print(" Bat: "+String(battery(data)));
      Serial.print(" ID: "+String(serial(data),HEX));
      Serial.println();
      Serial.print("Ch."+String(channel(data)));
      Serial.println();
      Serial.print("T="+String(temperature(data),1)+"C");
      Serial.println();
          if (battery(data) == 0xC){
          Serial.print("Bat: LOW");
          Serial.println();
          }
          else {
          Serial.print("Bat: OK");
          Serial.println();
          }
        }
        else
        {
        Serial.print(" Checksum error");
        }
     Serial.println(); 
    }

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
///////////////////  Вывод результата на LCD   /////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

/// Датчик с влажностью

    if( data[8] == (Sum(8,data)-0xa)&0xFF ){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print ("Ch." +String(channel(data),HEX));
      lcd.setCursor(0,1);
      lcd.print("T="+String(temperature(data),1)); lcd.printByte(0); lcd.print("C");
      lcd.print("   H="+String(humidity(data))+"%");
      if( (battery(data)) == 0xC){
      lcd.setCursor(11,0);
      lcd.printByte(1); lcd.print(" LOW");}
      else {
      lcd.setCursor(11,0);
      lcd.printByte(2); lcd.print(" OK");}
    }
    
/// Датчик без влажности      
     else {
       int sum = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff);
       if( (sum&0xF) == (data[6]>>4) && (sum>>4) == (data[7]&0xF) ){
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print ("Ch." +String(channel(data),HEX));
       lcd.setCursor(0,1);
       lcd.print("T="+String(temperature(data),1)); lcd.printByte(0); lcd.print("C"); lcd.print("   H --");
       if( (battery(data)) == 0xC){
       lcd.setCursor(11,0);
       lcd.printByte(1); lcd.print(" LOW");}
       else {
       lcd.setCursor(11,0);
       lcd.printByte(2); lcd.print(" OK");}       
       } 
                
         
     }

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////  Конец вывода результата на LCD   /////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////





    decoder.resetDecoder();
}




void setup () {
  lcd.init();
   lcd.backlight();
    lcd.createChar(0, cels);
    lcd.createChar(1, batlow);
    lcd.createChar(2, batok);
    
    Serial.begin(9600);
    Serial.println("\n[ookDecoder]");
     
    
    pinMode(PORT, INPUT);  // use the AIO pin

   attachInterrupt(digitalPinToInterrupt(PORT), ext_int_1, CHANGE);



}

void loop () {

  
    static int i = 0;
    
    cli();
    word p = pulse;
    pulse = 0;
    sei();

    //if (p != 0){ Serial.print(++i); Serial.print('\n');}
    
    if (p != 0) {
        if (orscV2.nextPulse(p))
            reportSerial("OSV2", orscV2);  
        if (orscV3.nextPulse(p))
            reportSerial("OSV3", orscV3);        
      }
}

 

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

Я так понимаю вы выводите показания датчиков сразу как только с них приходят данные, что несколько неправильно с моей точки зрения. Данные с датчика могут не приходить долго, стандартные таймаут на передачу 39,41,43 секунды, в зависимости от канала. Или когда сразу приходят два разных датчика первый слишком быстро пропадает.

 

Я бы сделал запоминание последних пришедших данные с датчика в массив, и показывал все элементы массива через каждые 5-10 секунд по кругу. Так более наглядно. Плюс туда же ещё сохранять время последнего приёма, и контролировать его, при превышении допустим часа отображать что датчик не обнаруживается больше. Вдруг там батарейка сдохла или ветром сдуло )

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

snickser пишет:

Я бы сделал запоминание последних пришедших данные с датчика в массив, и показывал все элементы массива через каждые 5-10 секунд по кругу. Так более наглядно. Плюс туда же ещё сохранять время последнего приёма, и контролировать его, при превышении допустим часа отображать что датчик не обнаруживается больше. Вдруг там батарейка сдохла или ветром сдуло )

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

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

Вчера забрал с почты и подключил приемник на гетеродине (не рекламы ради
http://s.aliexpress.com/eMrYR7nq). Даже без антены он начал ловить сигнал от датчика за окном в 2ух метрах, и это при том, что подключил я его к "шумящей" esp8266.
Припаял антенну около 17 см, как по ссылке (интересная информация по приемникам) (http://www.nemcon.nl/blog2/2015/07/aa) сигнал улучшился. Ловит намного лучше, чем приемник из первого поста темы.
Сегодня буду тестировать с Mega.

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

Вот очень печально, что у всех приёмников нет вывода АРУ. Все эти "ловит/не ловит" малоинформативны. Узнать бы настоящий уровень сигнала. Это бы и в поиске места для антенны помогло.

KVadik
KVadik аватар
Offline
Зарегистрирован: 15.06.2014

Porosenok пишет:
Вот очень печально, что у всех приёмников нет вывода АРУ. Все эти "ловит/не ловит" малоинформативны. Узнать бы настоящий уровень сигнала. Это бы и в поиске места для антенны помогло.

Ну про "у всех" это вы загнули, это у тех что за $0.5-$1 нет. У всяких Si4432, CC1101 она, насколько я помню, есть.

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

KVadik пишет:

Ну про "у всех" это вы загнули, это у тех что за $0.5-$1 нет. У всяких Si4432, CC1101 она, насколько я помню, есть.

Тогда ответьте мне на простой вопрос. Если 4432 поддерживает OOK, конфигурирование пакета и стоит $2, почему для приёма сигнала от орегоновских датчиков мы используем всякие китайские супергетородины и прочую муть? Я чего-то не знаю?

И кстати ещё. Подскажите, где почитать на тему исправления показаний влажности орегоновских датчиков? У меня все три из разных серий, все сейчас за бортом и при -9С все показывают 40-50%, что явно враньё.

XOR
Offline
Зарегистрирован: 25.04.2015

все резистивные сенсоры (GY-HR00X и тп) что я находил ниже 0С не меряют, а при -10С и ниже он вообще по константе (последнее измеренное при -9.9) считает. а с чего вы взяли что 40-50% явно враньё?

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

Потому что метеоцентр передаёт 85%

XOR
Offline
Зарегистрирован: 25.04.2015

они осенью измеряют сухим и влажным и вносят поправку в М-19, а зимой измерют только М-19 с учетом поправки.  чьи попугаи точнее тот еще вопрос, психромер и dht22 показывают +- 2%, sht10 занижает на 20%, орегоновский через год стал занижать еще больше.

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

Porosenok пишет:

Потому что метеоцентр передаёт 85%

Посмотрите на wunderground.com рядом с собой, если есть датчики, что показывают, и там где стоит метеоцентр ) там есть карта с PWS.

И да, орегоновские датчики весьма слабо откалиброваны, могут показывать до +/- 30% легко...

Я даже для этого собрал их все вместе, и DHT22 c HTU21, и когда показания устаканились, взял один за эталон, а к остальным ввёл попрaвочный коэффициент. У меня кстати три HTU21, и тоже все показывают разный % влажности. +/- до 10 даже иной раз.

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

Так может имеет смысл обновлять в орегоновских датчиках сенсоры влажности, раз они быстро деградируют? Но на какой именно?

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

snickser пишет:

Я даже для этого собрал их все вместе, и DHT22 c HTU21, и когда показания устаканились, взял один за эталон, а к остальным ввёл попрaвочный коэффициент.

А коэффициент получается какого порядка?

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

Porosenok,

Несколько единиц в плюс или минус от эталона ставлю в программе рисовалке графиков, в диапазоне 30-60% расхождения некритичны, а вне этого диапазона уже не сильно интересны. Итак понятно что влажность высокая или низкая.

$h[2]-=4.2 if $h[2]!="U";
$h[3]+=7 if $h[3]!="U";
$h[4]-=6.1 if $h[4]!="U";
$h[5]-=9.8 if $h[5]!="U";

как пример расхождения значений. ;)

 

gulin176
Offline
Зарегистрирован: 03.09.2016

Хочу сказать что у меня влажность датчик показывает отлично и почти сходится с bme280. Если и делать какую то поправку в программе то надо её явно обозначать потому как меня влажность датчика полностью устраивает

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

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

gulin176
Offline
Зарегистрирован: 03.09.2016

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

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

Загрязниться поверхность может, насобирав из воздуха примесей, которые прореагируют с полимером, покрывающим гребёнку электродов. Со временим это и приводит к потере чувствительности. У меня всем датчикам примерно лет по 6-7. Вероятно от того они одинаково и показывают не то.