Кстати, на днях собирал в едином корпусе транслятор данных с датчиков на narodmon. Заметил ещё такую особенность - приёмник надо относить от контроллера подальше, контроллер очень сильно фонит. Поэтому в одном корпусе не вышло...
Ну, там по аналогии легко догадаться... с первого раза ))
Вставляете рядом с кодом V2...
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;
if (orscV2.nextPulse(p))
reportSerial("OSV2", orscV2);
if (orscV3.nextPulse(p))
reportSerial("OSV3", orscV3);
Только меня терзают смутные сомнения, что он так же "глуховат" как и оригинальный, так как взять оттуда же...
А Вы уверены, что у вас там именно v3 протокол в эфире?
Это два других датчика. Тот что код короче скорее всего THN132N , потому как он без влажности. Но он говорит что на 4 канале (третий, а не второй как вы написали). А тот что длинее скорее всего RTGN318. Или это вы соседские датчики видите ))
Это два других датчика. Тот что код короче скорее всего THN132N , потому как он без влажности. Но он говорит что на 4 канале (третий, а не второй как вы написали). А тот что длинее скорее всего RTGN318. Или это вы соседские датчики видите ))
EA4C:40:44:11:24:20:63
24.1 градуса... третий канал. Вроде подходит.
Вы можете помочь и дописать скетч, чтобы он сразу переводил в понятные цифры?
Так этот датчик только и работает с кодом который вы подправили, добавили v.3 в код из поста#113.
С другими кодами RTGN318 не работает, т.к. там только v.2 прописана.
Я не знаю как программируются каналы в этом датчике, дело в том что в документации на этот счёт пусто. Кроме стандартных значений 1,2,4 тот код ничего не умеет понимать.
Покажите полные пакеты от датчика на 3 и 5 канале, можно будет придумать как их показывать.
Я не знаю как программируются каналы в этом датчике, дело в том что в документации на этот счёт пусто. Кроме стандартных значений 1,2,4 тот код ничего не умеет понимать.
Покажите полные пакеты от датчика на 3 и 5 канале, можно будет придумать как их показывать.
А вот интересно, у вас есть пятиканальная базовая станция которая умеет этот датчик показывать?... Что будет, точнее как по порядку они выстроятся на базе, если сделать два датчика один на 3-ем канале, а другой на 4-ом... )
Дело в том, что номера каналов могут быть числом 1,2,4 (старший разряд третьего бита), но у ваших датчиков там может быть 1,2,3,4,5. Вот и интересно, что случится если смешать 3 и 4. Как их база расставить. Дело в том что старые базы число 4 воспринимают как третий канал.
А вот интересно, у вас есть пятиканальная базовая станция которая умеет этот датчик показывать?... Что будет, точнее как по порядку они выстроятся на базе, если сделать два датчика один на 3-ем канале, а другой на 4-ом... )
Дело в том, что номера каналов могут быть числом 1,2,4 (старший разряд третьего бита), но у ваших датчиков там может быть 1,2,3,4,5. Вот и интересно, что случится если смешать 3 и 4. Как их база расставить. Дело в том что старые базы число 4 воспринимают как третий канал.
Дело в том, что у меня станция Oregon BAR 800, с ней в комплекте датчик RTGN318. В инструкции к станции написано, что канал установить на "1". Станция может отображать только один канал, нет переключения по каналам. Даже на экране нет отображения номера канала. Мало того, если установить канал отличный от "1", то сигнал с него станция примет только один раз и больше не примет, поэтому со станцией работают датчики только с первым каналом.
Кстати, на днях собирал в едином корпусе транслятор данных с датчиков на narodmon. Заметил ещё такую особенность - приёмник надо относить от контроллера подальше, контроллер очень сильно фонит. Поэтому в одном корпусе не вышло...
Сейчас будет вопрос, как две DATA в один PWM2 вставить )))
Сейчас будет вопрос, как две DATA в один PWM2 вставить )))
))) вопрос на 5 баллов )) Имелось в виду, что пофиг какой DATA соединять с D2 т.к. по сути это один вывод, просто выведен на 2 контакта.
Зачем так сделано? - не знаю.
На приемнике На Ардуино
1) VCC - +5
2) - GND
3) - PWM 2
4) GND - GND
Может надо так:
1) VCC - +5
2) DATA - PWM 2
3) DATA - PWM 2
4) GND - GND
Спасибо за ответ.
Убрал один провод DATA от GND и всё заработало.
У меня есть в наличии 4 разных модели датчика Oregon. Сигнал ринимается только от двух. Есть ли возможность добавить другие модели датчика?
Смотря какие датчики. Разные датчики используют разные версии протоколов. Всего их 3 - v1.0 , v2.1 и v3.0
Обсуждаемый в данной ветке код работает с версией протокола 2.1 Вбейте в google модель ваших датчиков и выясните версию протокола RF
Если протокол 2.1, то видимо что то с датчиком
thgn800 датчик не видит. Была у меня классная станция, ребёнок разбил, датчик остался
Смотря какие датчики. Разные датчики используют разные версии протоколов. Всего их 3 - v1.0 , v2.1 и v3.0
Обсуждаемый в данной ветке код работает с версией протокола 2.1 Вбейте в google модель ваших датчиков и выясните версию протокола RF
Если протокол 2.1, то видимо что то с датчиком
Датчик такой Oregon RTGN318.
Рабочий на 100%. Метеостанция с ним работает отлично.
Не смог найти версию RF.
RTGN318 - пятиканальный с дальностью в 70м. Оба видовых признака версии 3.0
RTGN318 - пятиканальный с дальностью в 70м. Оба видовых признака версии 3.0
Спасибо за разъяснение. Просто на предыдущей страницы высказывалось мнение, что это 2.1.
А есть подобные скетчи или темы работающие с 3.0?
На первой странице векти форума вроде бы был скетч, поддерживающий все версии.
На первой странице векти форума вроде бы был скетч, поддерживающий все версии.
Судя по описанию похоже на то.
Спасибо, попробую.
На первой странице векти форума вроде бы был скетч, поддерживающий все версии.
Скетч из первого поста темы у меня не заработал. Пишет только DecoderOK и всё.
На обновлённый скетч из 14 поста темы ругается компилятор, не могу понять в чём проблема.
На обновлённый скетч из 14 поста темы ругается компилятор, не могу понять в чём проблема.
Что пишет то?
На обновлённый скетч из 14 поста темы ругается компилятор, не могу понять в чём проблема.
Что пишет то?
Ругается на библиотеку "#include "decoders.h" которой нет по ссылке https://github.com/jcw/jeelib
Подскажите, кто нибудь смог скомпилировать и загрузить скетч из этого поста?
http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-s...
Продолжая тему, если кому интересно сделал веб серверок с отображением датчиков орегоновских. отличие - основной код вынесен в библиотеки.
Не могли бы вы поделиться библиотеками?
Скетч из первого поста темы у меня не заработал. Пишет только DecoderOK и всё.
На обновлённый скетч из 14 поста темы ругается компилятор, не могу понять в чём проблема.
Используйте код из поста №113. Тот что на первой странице - глуховат.
Скетч из первого поста темы у меня не заработал. Пишет только DecoderOK и всё.
На обновлённый скетч из 14 поста темы ругается компилятор, не могу понять в чём проблема.
Используйте код из поста №113. Тот что на первой странице - глуховат.
Он не поддерживает v.3
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; } };http://jeelabs.net/projects/cafe/wiki/Decoding_the_Oregon_Scientific_V2_...
Этого кода нет в посте #113. В какое место его добавить?
Ну, там по аналогии легко догадаться... с первого раза ))
Вставляете рядом с кодом V2...
if (orscV2.nextPulse(p)) reportSerial("OSV2", orscV2); if (orscV3.nextPulse(p)) reportSerial("OSV3", orscV3);Только меня терзают смутные сомнения, что он так же "глуховат" как и оригинальный, так как взять оттуда же...
А Вы уверены, что у вас там именно v3 протокол в эфире?
Ну, там по аналогии легко догадаться... с первого раза ))
Вставляете рядом с кодом V2...
if (orscV2.nextPulse(p)) reportSerial("OSV2", orscV2); if (orscV3.nextPulse(p)) reportSerial("OSV3", orscV3);Только меня терзают смутные сомнения, что он так же "глуховат" как и оригинальный, так как взять оттуда же...
Догадаться то можно легко, но не всегда это работает.
Я вот уже второй день пытаюсь переделать скетч от Ув. Porosenok, чтобы он выодил на экран 1602, вместо 2004 и всё безрезультатно(((
А Вы уверены, что у вас там именно v3 протокол в эфире?
RTGN318 - пятиканальный с дальностью в 70м. Оба видовых признака версии 3.0
Ну, вы попробуйте для начала... Как уже и говорил код V2 декодера в посте #113 лучше "слышит" датчики.
Вот полный код, попробуйте его
// RF Receiver #define PORT 2 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; } }; class CrestaDecoder : public DecodeOOK { public: CrestaDecoder () {} virtual char decode (word width) { if (200 <= width && width < 1300) { byte w = width >= 750; switch (state) { case UNKNOWN: if (w == 1) ++flip; else if (2 <= flip && flip <= 10) state = T0; else return -1; break; case OK: if (w == 0) state = T0; else gotBit(1); break; case T0: if (w == 0) gotBit(0); else return -1; break; } } else if (width >= 2500 && pos >= 7) return 1; else return -1; return 0; } }; class KakuDecoder : public DecodeOOK { public: KakuDecoder () {} virtual char decode (word width) { if (180 <= width && width < 450 || 950 <= width && width < 1250) { byte w = width >= 700; switch (state) { case UNKNOWN: case OK: if (w == 0) state = T0; else return -1; break; case T0: if (w) state = T1; else return -1; break; case T1: state += w + 1; break; case T2: if (w) gotBit(0); else return -1; break; case T3: if (w == 0) gotBit(1); else return -1; break; } } else if (width >= 2500 && 8 * pos + bits == 12) { for (byte i = 0; i < 4; ++i) gotBit(0); alignTail(2); return 1; } else return -1; return 0; } }; class XrfDecoder : public DecodeOOK { public: XrfDecoder () {} // see also <a data-cke-saved-href="<a href="http://davehouston.net/rf.htm" rel="nofollow">http://davehouston.net/rf.htm</a>" href="<a href="http://davehouston.net/rf.htm" rel="nofollow">http://davehouston.net/rf.htm</a>" rel="nofollow"><a href="http://davehouston.net/rf.htm" rel="nofollow">http://davehouston.net/rf.htm</a></a> virtual char decode (word width) { if (width > 2000 && pos >= 4) return 1; if (width > 5000) return -1; if (width > 4000 && state == UNKNOWN) state = OK; else if (350 <= width && width < 1800) { byte w = width >= 720; switch (state) { case OK: if (w == 0) state = T0; else return -1; break; case T0: gotBit(w); break; } } else return -1; return 0; } }; class HezDecoder : public DecodeOOK { public: HezDecoder () {} // see also <a data-cke-saved-href="<a href="http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki" rel="nofollow">http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki</a>" href="<a href="http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki" rel="nofollow">http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki</a>" rel="nofollow"><a href="http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki" rel="nofollow">http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki</a></a> virtual char decode (word width) { if (200 <= width && width < 1200) { byte w = width >= 600; gotBit(w); } else if (width >= 5000 && pos >= 5 /*&& 8 * pos + bits == 50*/) { for (byte i = 0; i < 6; ++i) gotBit(0); alignTail(7); // keep last 56 bits return 1; } else return -1; return 0; } }; // 868 MHz decoders class VisonicDecoder : public DecodeOOK { public: VisonicDecoder () {} virtual char decode (word width) { if (200 <= width && width < 1000) { byte w = width >= 600; switch (state) { case UNKNOWN: case OK: state = w == 0 ? T0 : T1; break; case T0: gotBit(!w); if (w) return 0; break; case T1: gotBit(!w); if (!w) return 0; break; } // sync error, flip all the preceding bits to resync for (byte i = 0; i <= pos; ++i) data[i] ^= 0xFF; } else if (width >= 2500 && 8 * pos + bits >= 36 && state == OK) { for (byte i = 0; i < 4; ++i) gotBit(0); alignTail(5); // keep last 40 bits // only report valid packets byte b = data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4]; if ((b & 0xF) == (b >> 4)) return 1; } else return -1; return 0; } }; class EMxDecoder : public DecodeOOK { public: EMxDecoder () {} // see also <a data-cke-saved-href="<a href="http://fhz4linux.info/tiki-index.php?page=EM+Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=EM+Protocol</a>" href="<a href="http://fhz4linux.info/tiki-index.php?page=EM+Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=EM+Protocol</a>" rel="nofollow"><a href="http://fhz4linux.info/tiki-index.php?page=EM+Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=EM+Protocol</a></a> virtual char decode (word width) { if (200 <= width && width < 1000) { byte w = width >= 600; switch (state) { case UNKNOWN: if (w == 0) ++flip; else if (flip > 20) state = OK; else return -1; break; case OK: if (w == 0) state = T0; else return -1; break; case T0: gotBit(w); break; } } else if (width >= 1500 && pos >= 9) return 1; else return -1; return 0; } }; class KSxDecoder : public DecodeOOK { public: KSxDecoder () {} // see also <a data-cke-saved-href="<a href="http://www.dc3yc.homepage.t-online.de/protocol.htm" rel="nofollow">http://www.dc3yc.homepage.t-online.de/protocol.htm</a>" href="<a href="http://www.dc3yc.homepage.t-online.de/protocol.htm" rel="nofollow">http://www.dc3yc.homepage.t-online.de/protocol.htm</a>" rel="nofollow"><a href="http://www.dc3yc.homepage.t-online.de/protocol.htm" rel="nofollow">http://www.dc3yc.homepage.t-online.de/protocol.htm</a></a> virtual char decode (word width) { if (200 <= width && width < 1000) { byte w = width >= 600; switch (state) { case UNKNOWN: gotBit(w); bits = pos = 0; if (data[0] != 0x95) state = UNKNOWN; break; case OK: state = w == 0 ? T0 : T1; break; case T0: gotBit(1); if (!w) return -1; break; case T1: gotBit(0); if (w) return -1; break; } } else if (width >= 1500 && pos >= 6) return 1; else return -1; return 0; } }; class FSxDecoder : public DecodeOOK { public: FSxDecoder () {} // see also <a data-cke-saved-href="<a href="http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol</a>" href="<a href="http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol</a>" rel="nofollow"><a href="http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol" rel="nofollow">http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol</a></a> virtual char decode (word width) { if (300 <= width && width < 775) { byte w = width >= 500; switch (state) { case UNKNOWN: if (w == 0) ++flip; else if (flip > 20) state = T1; else return -1; break; case OK: state = w == 0 ? T0 : T1; break; case T0: gotBit(0); if (w) return -1; break; case T1: gotBit(1); if (!w) return -1; break; } } else if (width >= 1500 && pos >= 5) return 1; else return -1; return 0; } }; OregonDecoderV2 orscV2; OregonDecoderV3 orscV3; CrestaDecoder cres; KakuDecoder kaku; XrfDecoder xrf; HezDecoder hez; VisonicDecoder viso; EMxDecoder emx; KSxDecoder ksx; FSxDecoder fsx; 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; } void reportSerial (const char* s, class DecodeOOK& decoder) { byte pos; const byte* data = decoder.getData(pos); Serial.print(String(millis()/1000.,3) + " "); Serial.print(s); Serial.print(' '); for (byte i = 0; i < pos; ++i) { Serial.print(data[i] >> 4, HEX); Serial.print(data[i] & 0x0F, HEX); } Serial.println(); decoder.resetDecoder(); } void setup () { 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); // if (cres.nextPulse(p)) // reportSerial("CRES", cres); if (kaku.nextPulse(p)) reportSerial("KAKU", kaku); if (xrf.nextPulse(p)) reportSerial("XRF", xrf); if (hez.nextPulse(p)) reportSerial("HEZ", hez); } if (p != 0) { if (viso.nextPulse(p)) reportSerial("VISO", viso); if (emx.nextPulse(p)) reportSerial("EMX", emx); if (ksx.nextPulse(p)) reportSerial("KSX", ksx); if (fsx.nextPulse(p)) reportSerial("FSX", fsx); } }Ну, вы попробуйте для начала... Как уже и говорил код V2 декодера в посте #113 лучше "слышит" датчики.
Вот полный код, попробуйте его
Спасибо за полный код. Попробовал.
В Serial что то идёт.
Что нужно добавить в код, чтобы это расшифровать?
И судя по всему v.3 не видит.
Рядом с приёмником лежат три датчика:
Канал 1 - THGN122N
Канал 2 - THN132N
Канал 3 - RTGN318
Ну, OSV2 1A2D10B14023508235F0 - это точно Орегон, на первом канале.
Про остальные надо думать.
Формат строки очень прост
1A:2D:10:B1:40:23:50:82:35:F0
note: channels were 1,2,4- 4 is channel 3.
Reported to change on battery replacement.
BCD format
BCD format
BCD format
BCD format
Non zero indicates negative
BCD format
Получаем 23.4 градуса и 25% влажность. Надо только проверку Checksum делать, потому как CRC не всегда приезжает из того кода.
Ну, OSV2 1A2D10B14023508235F0 - это точно Орегон, на первом канале.
Про остальные надо думать.
Формат строки очень прост
1A:2D:10:B1:40:23:50:82:35:F0
Получаем 23.4 градуса и 25% влажность. Надо только проверку Checksum делать, потому как CRC не всегда приезжает из того кода.
Есть другие рабочие коды, которые сразу выдают параметры температуры и влажности, но они v.3 так же не видят, вот в чём проблема.
Ну смотрите, у вас ещё приезжает
OSV2 AACC338E482300835A24
и
OSV2 EA4C404411242063
Это два других датчика. Тот что код короче скорее всего THN132N , потому как он без влажности. Но он говорит что на 4 канале (третий, а не второй как вы написали). А тот что длинее скорее всего RTGN318. Или это вы соседские датчики видите ))
EA4C:40:44:11:24:20:63
24.1 градуса... третий канал. Вроде подходит.
Ну смотрите, у вас ещё приезжает
OSV2 AACC338E482300835A24
и
OSV2 EA4C404411242063
Это два других датчика. Тот что код короче скорее всего THN132N , потому как он без влажности. Но он говорит что на 4 канале (третий, а не второй как вы написали). А тот что длинее скорее всего RTGN318. Или это вы соседские датчики видите ))
EA4C:40:44:11:24:20:63
24.1 градуса... третий канал. Вроде подходит.
Вы можете помочь и дописать скетч, чтобы он сразу переводил в понятные цифры?
Я не думаю, что это соседские датчики.
ну держите... ;)
// RF Receiver #define PORT 2 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]>>4) { case 0x1: channel = 1; break; case 0x2: channel = 2; break; case 0x4: channel = 3; 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; } void reportSerial (const char* s, class DecodeOOK& decoder) { byte pos; const byte* data = decoder.getData(pos); Serial.print(String(millis()/1000.,3) + " "); 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(" "+String(channel(data))+" "+String(serial(data),HEX)); Serial.print(" "+String(temperature(data),1)+" "+String(humidity(data))+"%"); Serial.print(" "+String(battery(data))); } else if( data[6] == (Sum(6,data)-0xa)&0xFF ){ Serial.print(" "+String(channel(data))+" "+String(serial(data),HEX)); Serial.print(" "+String(temperature(data),1)); Serial.print(" "+String(battery(data))); } else { Serial.print(" Checksumm error"); } Serial.println(); decoder.resetDecoder(); } void setup () { 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); } }ну держите... ;)
Спасибо вам ОГРОМНОЕ!
Датчик за окном RTGN318 - канал 1:
36.486 OSV2 BACC1391200300C84AA9 1 91 3.2 80% 0
Честно говоря я поставил наугад, у меня таких нет чтоб проверить... докрутите код сами )
Вот оригинальный код подсчёта контрольных сум, первая часть для датчиков без влажности.
/** * \brief Calculate checksum * \param data Oregon message */ void calculateAndSetChecksum(byte* data) { #ifdef THN132N int s = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff); data[6] |= (s&0x0F) << 4; data[7] = (s&0xF0) >> 4; #else data[8] = ((Sum(8, data) - 0xa) & 0xFF); #endif }Честно говоря я поставил наугад, у меня таких нет чтоб проверить... докрутите код сами )
Знал бы что крутить, покрутил бы.
Спасибо за помощь.
Самое главное, что V.3 работает.
Нет у вас там никакого V3... ;) все ваши датчики используют протокол v2
Нет у вас там никакого V3... ;) все ваши датчики используют протокол v2
Если так, то почему же не работают датчики RTGN318 с кодом, с которым прекрасно работают датчики THGN122N и THN132N?
В смысле? Вы же сами писали только что...
В смысле? Вы же сами писали только что...
Так этот датчик только и работает с кодом который вы подправили, добавили v.3 в код из поста#113.
С другими кодами RTGN318 не работает, т.к. там только v.2 прописана.
Да, но он не используется :) иначе бы вместо OSV2 там писалось бы OSV3 =)
Я лишь использовал код декодера V2 тот что работает лучше по моему мнению, и именно он то у вас и заработал!... )
Да, но он не используется :) иначе бы вместо OSV2 там писалось бы OSV3 =)
Я лишь использовал код декодера V2 тот что работает лучше по моему мнению, и именно он то у вас и заработал!... )
Тогда странно.
Я попробую код из #113 и проверю, какие датчики работают, а какие нет. Ведь в нём нет поддержки v.3?
Вы ведь в код из #113 добавили только v.3?
Вот, держите, возможно сработает... ;)
// RF Receiver #define PORT 2 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]>>4) { case 0x1: channel = 1; break; case 0x2: channel = 2; break; case 0x4: channel = 3; 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; } 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(" "+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(); } void setup () { 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); } }Спасибо!
Для RTGN318 результат выводит по 2 одинаковые строки:
Для RTGN318 при выборе разных каналов выдаёт такое:
1 - 1 a8
2 - 2 28
3 - 103 a7
4 - 3 ab
5 - 103 2d
Я не знаю как программируются каналы в этом датчике, дело в том что в документации на этот счёт пусто. Кроме стандартных значений 1,2,4 тот код ничего не умеет понимать.
Покажите полные пакеты от датчика на 3 и 5 канале, можно будет придумать как их показывать.
Я не знаю как программируются каналы в этом датчике, дело в том что в документации на этот счёт пусто. Кроме стандартных значений 1,2,4 тот код ничего не умеет понимать.
Покажите полные пакеты от датчика на 3 и 5 канале, можно будет придумать как их показывать.
3 канал на RTGN318:
2287.793 OSV2 DACC3326282600835067 103 26 26.2 30% 8
А вот интересно, у вас есть пятиканальная базовая станция которая умеет этот датчик показывать?... Что будет, точнее как по порядку они выстроятся на базе, если сделать два датчика один на 3-ем канале, а другой на 4-ом... )
Дело в том, что номера каналов могут быть числом 1,2,4 (старший разряд третьего бита), но у ваших датчиков там может быть 1,2,3,4,5. Вот и интересно, что случится если смешать 3 и 4. Как их база расставить. Дело в том что старые базы число 4 воспринимают как третий канал.
А вот интересно, у вас есть пятиканальная базовая станция которая умеет этот датчик показывать?... Что будет, точнее как по порядку они выстроятся на базе, если сделать два датчика один на 3-ем канале, а другой на 4-ом... )
Дело в том, что номера каналов могут быть числом 1,2,4 (старший разряд третьего бита), но у ваших датчиков там может быть 1,2,3,4,5. Вот и интересно, что случится если смешать 3 и 4. Как их база расставить. Дело в том что старые базы число 4 воспринимают как третий канал.
Дело в том, что у меня станция Oregon BAR 800, с ней в комплекте датчик RTGN318. В инструкции к станции написано, что канал установить на "1". Станция может отображать только один канал, нет переключения по каналам. Даже на экране нет отображения номера канала. Мало того, если установить канал отличный от "1", то сигнал с него станция примет только один раз и больше не примет, поэтому со станцией работают датчики только с первым каналом.
Тогда найдите и поменяйте вот эту функцию на эту
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; }Думается число 3 в младшем разряде у вас будет постоянно.
Или вот более изящно )))
byte channel(const byte* data) { byte channel; switch (data[2]>>4) { case 0x1: channel = 1; break; case 0x2: channel = 2; break; case 0x3: channel = 3; break; case 0x4: if(data[2]==0x43){ channel = 4; } else { channel = 3; } break; case 0x5: channel = 5; break; } return channel; }Тогда найдите и поменяйте вот эту функцию на эту
Поменял.
Для RTGN318.
Устанавливаю канал - 1.
Нажимаю Reset на датчике.
Устанавливаю канал - 2.
Нажимаю Reset на датчике.
Устанавливаю канал - 3.
Нажимаю Reset на датчике.
Устанавливаю канал - 4.
Нажимаю Reset на датчике.
Устанавливаю канал - 5.
Нажимаю Reset на датчике.
ну, норм. =)
ну, норм. =)
Да, спасибо за помощь!
Буду с этим дальше возиться.
Выводить на экран 1602 и отправка на narodmon.