oregon sensors in Dz

433Mhz opensource Receiver & Transmitter.

Moderators: leecollings, Stuntteam

Post Reply
jackslayter
Posts: 59
Joined: Tuesday 07 October 2014 11:00
Target OS: Raspberry Pi / ODroid
Domoticz version: stable
Location: France RA
Contact:

oregon sensors in Dz

Post by jackslayter »

Hi, i have a rflink, in debug log in IDE i see my oregon sensors but not in domoticz, why?
it's the same with my OWL180.
whereas my other devices like door contact or kaku work fine
thank you
RPi2 + RFLink, Domoticz
Chacon - micromodule 200w, remote 3b, 2x module 1000w, remote 16b, smoke detector, door contact, 2x 3500w plug
Oregon - 3x Thgr122Nx / OWL - CM180 / TRC02_2 RGB / Cheap - PiR, door contact, Temp Hum / 4x REVOLT NC5461
User avatar
Stuntteam
Posts: 399
Joined: Wednesday 06 May 2015 16:39
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: oregon sensors in Dz

Post by Stuntteam »

Sounds like a bug.. check your email..
-=# RFLink Gateway Development Team #=-
Introduction: http://www.nemcon.nl/blog2/
Generic RFLink Support forum: http://www.esp8266.nu/forum/viewforum.php?f=8
jackslayter
Posts: 59
Joined: Tuesday 07 October 2014 11:00
Target OS: Raspberry Pi / ODroid
Domoticz version: stable
Location: France RA
Contact:

Re: oregon sensors in Dz

Post by jackslayter »

my cheap receiver/transmitter are so bad on rpi2, so i will buy Aurel transceiver rtx mid 5v
RPi2 + RFLink, Domoticz
Chacon - micromodule 200w, remote 3b, 2x module 1000w, remote 16b, smoke detector, door contact, 2x 3500w plug
Oregon - 3x Thgr122Nx / OWL - CM180 / TRC02_2 RGB / Cheap - PiR, door contact, Temp Hum / 4x REVOLT NC5461
jackslayter
Posts: 59
Joined: Tuesday 07 October 2014 11:00
Target OS: Raspberry Pi / ODroid
Domoticz version: stable
Location: France RA
Contact:

Re: oregon sensors in Dz

Post by jackslayter »

I have a problem with OWL 180, the data are received but not in the good field and the value is divided by 10
1.png
1.png (16.58 KiB) Viewed 6056 times
RPi2 + RFLink, Domoticz
Chacon - micromodule 200w, remote 3b, 2x module 1000w, remote 16b, smoke detector, door contact, 2x 3500w plug
Oregon - 3x Thgr122Nx / OWL - CM180 / TRC02_2 RGB / Cheap - PiR, door contact, Temp Hum / 4x REVOLT NC5461
User avatar
Stuntteam
Posts: 399
Joined: Wednesday 06 May 2015 16:39
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: oregon sensors in Dz

Post by Stuntteam »

I will look into this..
-=# RFLink Gateway Development Team #=-
Introduction: http://www.nemcon.nl/blog2/
Generic RFLink Support forum: http://www.esp8266.nu/forum/viewforum.php?f=8
jackslayter
Posts: 59
Joined: Tuesday 07 October 2014 11:00
Target OS: Raspberry Pi / ODroid
Domoticz version: stable
Location: France RA
Contact:

Re: oregon sensors in Dz

Post by jackslayter »

Hi, you could have fix it ?
thx
RPi2 + RFLink, Domoticz
Chacon - micromodule 200w, remote 3b, 2x module 1000w, remote 16b, smoke detector, door contact, 2x 3500w plug
Oregon - 3x Thgr122Nx / OWL - CM180 / TRC02_2 RGB / Cheap - PiR, door contact, Temp Hum / 4x REVOLT NC5461
maxmizer
Posts: 8
Joined: Sunday 25 October 2015 8:17
Target OS: Windows
Domoticz version:
Contact:

Re: oregon sensors in Dz

Post by maxmizer »

I have the same problem with Oregon UVN800
RFlink =0.0
RfXcom=2
dugolf
Posts: 6
Joined: Tuesday 14 October 2014 22:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.7450
Location: France
Contact:

Re: oregon sensors in Dz

Post by dugolf »

Hi

With Domoticz Version: 2.3397 and RfLink V1.1 r30 with the plugon 48 as below and the arduino simulator of an oregon Temp/Humidity ; it is ok the sensor is detected.

RfLink plugin_048.c:
The plugin is updated to remove the first 4 bits of the message which are the 4 bits of synchro

Code: Select all

//#######################################################################################################
//##                    This Plugin is only for use with the RFLink software package                   ##
//##                                     Plugin-48 Oregon V1/2/3                                       ##
//#######################################################################################################
/*********************************************************************************************\
 * This protocol takes care of receiving Oregon Scientific outdoor sensors that use the V1, V2 and V3 protocol
 *
 * models: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X,
 *         THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500,
 *         THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122
 *         THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave, RGR928 
 *         UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, RGR126, BTHG968
 *
 * Author             : StuntTeam, Thibaut Girka 
 * Support            : http://sourceforge.net/projects/rflink/
 * License            : This code is free for use in any open source project when this header is included.
 *                      Usage of any parts of this code in a commercial application is prohibited!  
 *********************************************************************************************
 * Changelog: v0.1 beta 
 *********************************************************************************************
 * Technical information:
 * Supports Oregon V1, V2 and V3 protocol messages
 * Core code from https://github.com/Cactusbone/ookDecoder/blob/master/ookDecoder.ino
 * Copyright (c) 2014 Charly Koza [email protected] Copyright (c) 2012 Olivier Lebrun [email protected] 
 * Copyright (c) 2012 Dominique Pierre (zzdomi) Copyright (c) 2010 Jean-Claude Wippler [email protected]
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
 * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 * is furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 \*********************************************************************************************/
#define OSV3_PULSECOUNT_MIN 50  // 126
#define OSV3_PULSECOUNT_MAX 290 // make sure to check the max length in plugin 1 as well..!

#ifdef PLUGIN_048
/*
 * Many devices use 160 bits, known exceptions:
 * 0xEA4c         136 bits  // TH132N
 * 0xEA7c         240 bits  // UV138
 * 0x5A5D / 1A99  176 bits  // THGR918 / WTGR800
 * 0x5A6D         192 bits  // BTHR918N
 * 0x8AEC         192 bits  // RTGR328N
 * 0x9AEC         208 bits  // RTGR328N
 * 0xDA78         144 bits  // UVN800
 * 0x2A19         184 bits  // RCR800
 * 0x2A1d         168 bits  // WGR918
 */
// =====================================================================================================
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;
	}
};


class OregonDecoderV1 : public DecodeOOK {
	public:
		OregonDecoderV1_org() {}
			virtual char decode(word width) {
			if (200 <= width && width < 1200) {
				byte w = width >= 700;
				switch (state) {
					case UNKNOWN:
						if (w == 0)
							++flip;
						else if (10 <= flip && flip <= 50) {
							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;
				}
				return 0;
			}
			if (width >= 2500 && pos >= 9)
				return 1;
			return -1;
		}
}; 

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 >= 675;
		if (150 <= width && width < 1200) {
			byte w = width >= 600;
			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 total_bits == 160 ? 1 : 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 >= 675;
			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;
	}
};

OregonDecoderV1 orscV1;
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;

volatile word pulse;
// =====================================================================================================
// =====================================================================================================
byte osdata[13];               

void reportSerial(class DecodeOOK& decoder) {
	byte pos;
	const byte* data = decoder.getData(pos);
	for (byte i = 0; i < pos; ++i) {
        if (i < 13) osdata[i]=data[i];
	}
	decoder.resetDecoder();
}
// =====================================================================================================
// calculate a packet checksum by performing a 
byte checksum(byte type, int count, byte check) {
     byte calc=0;
     // type 1, add all nibbles, deduct 10
     if (type == 1) {
        for(byte i = 0; i<count;i++) {
           calc += (osdata[i]&0xF0) >> 4;
           calc += (osdata[i]&0xF);
        }
        calc=calc-10;
     } else 
     // type 2, add all nibbles up to count, add the 13th nibble , deduct 10
     if (type == 2) {
        for(byte i = 0; i<count;i++) {
           calc += (osdata[i]&0xF0) >> 4;
           calc += (osdata[i]&0xF);
        }
        calc += (osdata[6]&0xF);
        calc=calc-10;
     } else 
     // type 3, add all nibbles up to count, subtract 10 only use the low 4 bits for the compare
     if (type == 3) {
        for(byte i = 0; i<count;i++) {
           calc += (osdata[i]&0xF0) >> 4;
           calc += (osdata[i]&0xF);
        }
        calc=calc-10;
        calc=(calc&0x0f);
     } else 
     if (type == 4) {
        for(byte i = 0; i<count;i++) {
           calc += (osdata[i]&0xF0) >> 4;
           calc += (osdata[i]&0xF);
        }
        calc=calc-10;
        
     } 
     if (check == calc ) return 0;     
     return 1;
}
// =====================================================================================================
boolean Plugin_048(byte function, char *string) {
	  
      if ((RawSignal.Number < OSV3_PULSECOUNT_MIN) || (RawSignal.Number > OSV3_PULSECOUNT_MAX) ) return false; 

      byte rc=0;
      byte found = 0;
      
      int temp = 0;
      byte hum = 0;
      int comfort = 0;
      int baro = 0;
      int forecast = 0;
      int uv = 0;
      int wdir = 0;
      int wspeed = 0;
      int awspeed = 0;
      int rain = 0;
      int raintot = 0;

      word p = pulse;
      // ==================================================================================
      for (int x = 1; x < RawSignal.Number; x++) {
      //for (int x = 0; x < RawSignal.Number; x++) {
          p = RawSignal.Pulses[x]*RawSignal.Multiply;
          if (p != 0) {
             if (orscV1.nextPulse(p)) {
                reportSerial(orscV1);
                found=1; 
             } 
             if (orscV2.nextPulse(p)) { 
                reportSerial(orscV2);
                found=2;
             } 
             if (orscV3.nextPulse(p)) { 
                reportSerial(orscV3);
                found=3;
             } 
          }
      }
	  // Serial.print("found = ");
	  // Serial.println(found);
	  
      if (found == 0)
		  return false;
	  
	  // M.G. Remove 4 Sync bits (lower 4 bits of first byte)
	  if (found == 2) {
		for(byte x=0; x<13;x++) {
			osdata[x] = (osdata[x] >> 4);
			if (x < 12)
				osdata[x] += (osdata[x+1] & 0x0f) << 4;
		}
	  }
	  
      // ==================================================================================
      // Protocol and device info:
      // ==================================================================================
      // Serial.print("Oregon V");
      // Serial.print(found);
      // Serial.print(": ");
      // for(byte x=0; x<13;x++) {
      //    Serial.print( osdata[x],HEX ); 
      //    Serial.print((" ")); 
      //}
      // Serial.println();  
      // Serial.print("Oregon ID="); 
      unsigned int id=(osdata[0]<<8)+ (osdata[1]);
      rc=osdata[0];
      // Serial.println(id,HEX);  
      // ==================================================================================
      // Process the various device types:
      // ==================================================================================
      // Oregon V1 packet structure
      // SL-109H, AcuRite 09955
      // TEMP + CRC
      // ==================================================================================
      // 8487101C
      // 84+87+10=11B > 1B+1 = 1C
      if (found==1) {       // OSV1 
         int sum = osdata[0]+osdata[1]+osdata[2];  // max. value is 0x2FD
         sum= (sum &0xff) + (sum>>8);              // add overflow to low byte
         if (osdata[3] != (sum & 0xff) ) {
            //Serial.println("CRC Error"); 
            return false;
         }
         // -------------       
         //temp = ((osdata[2]>>4) * 100)  + ((osdata[1] & 0x0F) * 10) + ((osdata[1] >> 4));
         //if ((osdata[2] & 0x02) == 2) temp=temp | 0x8000;  // bit 1 set when temp is negative, set highest bit on temp valua
         temp = ((osdata[2] & 0x0F) * 100)  + ((osdata[1] >> 4) * 10) + ((osdata[1] & 0x0F));
         if ((osdata[2] & 0x20) == 0x20) temp=temp | 0x8000;  // bit 1 set when temp is negative, set highest bit on temp valua
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";OregonV1;ID=00"));           // Label
        //sprintf(pbuffer, "ID=00%02x;", rc & 0xCF);       
        PrintHexByte((rc)&0xcf);                      // rolling code + channel
        // ----------------------------------
        sprintf(pbuffer, ";TEMP=%04x;", temp);     
        Serial.print( pbuffer );
        if (osdata[2] & 0x80) {
           Serial.print(F("BAT=LOW;"));
        } else {
           Serial.print(F("BAT=OK;"));
        }
        Serial.println();
      } 
      // ==================================================================================
      // ea4c  Outside (Water) Temperature: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131
      // TEMP + BAT + CRC
      // ca48  Pool (Water) Temperature: THWR800
      // 0a4d  Indoor Temperature: THR128, THR138, THC138 
      // ==================================================================================
      // OSV2 EA4C20725C21D083 // THN132N
      // OSV2 EA4C101360193023 // THN132N
      // OSV2 EA4C40F85C21D0D4 // THN132N
      // OSV2 EA4C20809822D013
      //      0123456789012345
      //      0 1 2 3 4 5 6 7
      if(id == 0xea4c || id == 0xca48 || id == 0x0a4d) {
        byte sum=(osdata[7]&0x0f) <<4; 
        sum=sum+(osdata[6]>>4);
        if ( checksum(2,6, sum) !=0) {  // checksum = all nibbles 0-11+13 results is nibbles 15 <<4 + 12
            //Serial.println("CRC Error"); 
            return false;
        }
        // -------------       
        temp = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
        if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon Temp;ID="));           // Label
        //PrintHexByte(rc);
        PrintHexByte(osdata[3]);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";TEMP=%04x;", temp);     
        Serial.print( pbuffer );
        //if ((osdata[3] & 0x0F) >= 4) {
        if ((osdata[4] & 0x0c) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();
      } else
      // ==================================================================================
      // 1a2d  Indoor Temp/Hygro: THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, THGR268, THGR122X
      // 1a3d  Outside Temp/Hygro: THGR918, THGRN228NX, THGN500
      // fa28  Indoor Temp/Hygro: THGR810
      // *aac  Outside Temp/Hygro: RTGR328N
      // ca2c  Outside Temp/Hygro: THGR328N
      // fab8  Outside Temp/Hygro: WTGR800
      // TEMP + HUM sensor + BAT + CRC
      // ==================================================================================
      // OSV2 AACC13783419008250AD[RTGR328N,...] Id:78 ,Channel:0 ,temp:19.30 ,hum:20 ,bat:10
      // OSV2 1A2D40C4512170463EE6[THGR228N,...] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
      // OSV2 1A2D1072512080E73F2C[THGR228N,...] Id:72 ,Channel:1 ,temp:20.50 ,hum:78 ,bat:90
      // OSV2 1A2D103742197005378E // THGR228N
      // OSV3 FA28A428202290834B46 // 
      // OSV3 FA2814A93022304443BE // THGR810
      // OSV2 1A2D1002 02060552A4C
      //      1A3D10D91C273083..
      //      1A3D10D90C284083..
      //      01234567890123456789
      //      0 1 2 3 4 5 
      // F+A+2+8+1+4+A+9+3+0+2+2+3+0+4+4=4d-a=43 
      if(id == 0xfa28 || id == 0x1a2d || id == 0x1a3d || (id&0xfff)==0xACC || id == 0xca2c || id == 0xfab8 ) {
        if ( checksum(1,8,osdata[8]) !=0) return false;   // checksum = all nibbles 0-15 results is nibbles 16.17
        // -------------       
        temp = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
        if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
        // -------------       
        hum = ((osdata[7] & 0x0F)*16)+ (osdata[6] >> 4);
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon TempHygro;ID="));           // Label
        PrintHexByte(osdata[1]);
        PrintHexByte(osdata[3]);
        // ----------------------------------
        sprintf(pbuffer, ";TEMP=%04x;", temp);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "HUM=%02x;", hum);     
        Serial.print( pbuffer );
        if ((osdata[4] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();
      } else
      // ==================================================================================
      // 5a5d  Indoor Temp/Hygro/Baro: Huger - BTHR918
      // 5a6d  Indoor Temp/Hygro/Baro: BTHR918N, BTHR968. BTHG968 
      // TEMP + HUM + BARO + FORECAST + BAT
      // NO CRC YET
      // ==================================================================================
      // 5A 6D 00 7A 10 23 30 83 86 31
      // 5+a+6+d+7+a+1+2+3+3+8+3=47 -a=3d  +8=4f +8+6=55      
      // 5+a+6+d+7+a+1+2+3+3=3c-a=32
      // 5+a+6+d+7+a+1+2+3+3+0+8+3+8+6=55 -a =4b +3=4e !=1
      // 0  1  2  3  4  5  6  7  8  9
      if(id == 0x5a6d || id == 0x5a5d || id == 0x5d60) {
        // -------------       
        temp = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
        if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
        // -------------       
        hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
        
        //0: normal, 4: comfortable, 8: dry, C: wet
        int tmp_comfort = osdata[7] >> 4;
        if (tmp_comfort == 0x00)
			comfort=0;
		else if (tmp_comfort == 0x04)
			comfort=1;
		else if (tmp_comfort == 0x08)
			comfort=2;
		else if (tmp_comfort == 0x0C)
			comfort=3;
			
        // -------------       
        baro = (osdata[8] + 856);  // max value = 1111 / 0x457
        
        //2: cloudy, 3: rainy, 6: partly cloudy, C: sunny
        int tmp_forecast = osdata[9]>>4;
        if (tmp_forecast == 0x02)
			forecast = 3;
        else if (tmp_forecast == 0x03)
			forecast = 4;
        else if (tmp_forecast == 0x06)
			forecast = 2;
        else if (tmp_forecast == 0x0C)
			forecast = 1;
        
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon BTHR;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";TEMP=%04x;", temp);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "HUM=%02x;", hum);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "HSTATUS=%d;", comfort);
        Serial.print( pbuffer );
        sprintf(pbuffer, "BARO=%04x;", baro);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "BFORECAST=%d;", forecast);
        Serial.print( pbuffer );

		//below is not correct, and for now discarded
        //if (((osdata[3] & 0x0F) & 0x04) != 0) {
        //   Serial.print("BAT=LOW;"); 
        //} else {        
        //   Serial.print("BAT=OK;"); 
        //}        
        Serial.println();
      } else
      // ==================================================================================
      // 2914  Rain Gauge:
      // 2d10  Rain Gauge:
      // 2a1d  Rain Gauge: RGR126, RGR682, RGR918, RGR928, PCR122
      // 2A1D0065502735102063 
      // 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0=3e-a=34 != 63 
      // 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0+6=44-a=3A 
      // ==================================================================================
      if(id == 0x2a1d || id == 0x2d10 || id == 0x2914) { // Rain sensor
        //Checksum - add all nibbles from 0 to 8, subtract 9 and compare
        /*
        int cs = 0;
        for (byte i = 0; i < pos-2; ++i) { //all but last byte
            cs += data[i] >> 4;
            cs += data[i] & 0x0F;
        }
        int csc = (data[8] >> 4) + ((data[9] & 0x0F)*16);    
        cs -= 9;  //my version as A fails?
        Serial.print(csc); 
        Serial.print(" vs ");   
        Serial.println(cs);
        */
        rain = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
        raintot = ((osdata[7]  >> 4) * 10)  + (osdata[6]>>4);
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon Rain;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[3]);
        // ----------------------------------
        sprintf(pbuffer, ";RAIN=%04x;", rain);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "RAINTOT=%04x;", raintot);     
        Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();
      } else
      // ==================================================================================
      // 2a19  Rain Gauge: PCR800
      // RAIN + BAT + CRC
      // ==================================================================================
      // OSV3 2A19048E399393250010 
      //      01234567890123456789
      //      0 1 2 3 4 5 6 7 8 9
      // 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10 
      if(id == 0x2a19) { // Rain sensor
        int sum = (osdata[9] >> 4);  
        if ( checksum(3,9,sum) !=0) { // checksum = all nibbles 0-17 result is nibble 18
            //Serial.print("CRC Error, "); 
            return false;
        }
        rain = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
        //Serial.print(" RainTotal=");
        //raintot = ((osdata[7]  >> 4) * 10)  + (osdata[6]>>4);
        //Serial.print(raintot); 
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon Rain2;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[4]);
        // ----------------------------------
        sprintf(pbuffer,";RAIN=%04x;", rain);     
        Serial.print( pbuffer );
        //sprintf(pbuffer, "RAINTOT=%04x;", raintot);     
        //Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();
      } else
      // ==================================================================================
      // 1a89  Anemometer: WGR800
      // WIND DIR + SPEED + AV SPEED + CRC
      // ==================================================================================
      // OSV3 1A89048800C026400543
      // OSV3 1A89048800C00431103B
      // OSV3 1a89048848c00000003e W
      // OSV3 1a890488c0c00000003e E     
      //      1A89042CB0C047000147      
      //      0 1 2 3 4 5 6 7 8 9 
      // 1+A+8+9+0+4+8+8+0+0+C+0+0+4+3+1+1+0=45-a=3b
      if(id == 0x1a89) { // Wind sensor
        if ( checksum(1,9,osdata[9]) !=0) return false;
        wdir=((osdata[4] >> 4) & 0x0f);
        // -------------       
        wspeed = (osdata[6] >> 4) * 10;
        wspeed = wspeed + (osdata[6] &0x0f) * 100;
        wspeed = wspeed + (osdata[5] &0x0f);
        // -------------       
        awspeed = (osdata[8] >> 4) * 100;
        awspeed = awspeed + (osdata[7] &0x0f) * 10;
        awspeed = awspeed + (osdata[7] >> 4);
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon Wind;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";WINDIR=%04d;", wdir);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "WINSP=%04x;", wspeed);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "AWINSP=%04x;", awspeed);     
        Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();
      } else
      // ==================================================================================
      // 3a0d  Anemometer: Huger-STR918, WGR918
      // 1984  Anemometer:
      // 1994  Anemometer:
      // WIND DIR + SPEED + AV SPEED + BAT + CRC
      // 3A0D006F400800000031
      // ==================================================================================
      if(id == 0x3A0D || id == 0x1984 || id == 0x1994 ) {
        if ( checksum(1,9,osdata[9]) !=0) {
            //Serial.print("CRC Error, "); 
            return false;
        }
        wdir = ((osdata[5]>>4) * 100)  + ((osdata[5] & 0x0F * 10) ) + (osdata[4] >> 4);    
        wdir=wdir / 22.5;
        wspeed = ((osdata[7] & 0x0F) * 100)  + ((osdata[6]>>4) * 10)  + ((osdata[6] & 0x0F)) ;
        awspeed = ((osdata[8]>>4) * 100)  + ((osdata[8] & 0x0F) * 10)+((osdata[7] >>4)) ;      
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon Wind2;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";WINDIR=%04d;", wdir);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "WINSP=%04x;", wspeed);     
        Serial.print( pbuffer );
        sprintf(pbuffer, "AWINSP=%04x;", awspeed);     
        Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();      
	  } else
      // ==================================================================================
      // ea7c  UV Sensor: UVN128, UV138
      // UV + BAT
      // NO CRC YET
      // ==================================================================================
      if(id == 0xea7c) { 
        uv=((osdata[5] & 0x0F) * 10)  + (osdata[4] >> 4);
        Serial.print(uv); 
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon UVN128/138;ID="));           // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";UV=%04x;", uv);     
        Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();    
      } else
      // ==================================================================================
      // da78  UV Sensor: UVN800
      // UV 
      // NO CRC YET
      // ==================================================================================
      if( id == 0xda78) { 
        uv=(osdata[6] & 0xf0) + (osdata[5] &0x0f) ;
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        Serial.print(F(";Oregon UVN800;ID="));               // Label
        PrintHexByte(rc);
        PrintHexByte(osdata[2]);
        // ----------------------------------
        sprintf(pbuffer, ";UV=%04x;", uv);     
        Serial.print( pbuffer );
        if ((osdata[3] & 0x0F) >= 4) {
           Serial.print(F("BAT=LOW;")); 
        } else {        
           Serial.print(F("BAT=OK;")); 
        }        
        Serial.println();     
      } else
      // ==================================================================================
      // *aec  Date&Time: RTGR328N
      // 8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
      // 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9+1=6B -A=61  != 30
      // 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9=6a-A=60 0=0
      // NO CRC YET
      //20;06;Oregon Unknown;DEBUG=8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
      //20;20;Oregon Unknown;DEBUG=8A EC 13 FC 40 33 44 91 11 30 0 0 0 ;

      
      // OSV3 2A19048E399393250010 
      //      01234567890123456789
      //      0 1 2 3 4 5 6 7 8 9
      // 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10 

      // ==================================================================================
      // 8AEA1378077214924242C16CBD  21:49 29/04/2014 
      // 0 1 2 3 4 5 6 7 8 9 0 1 2
      // 8+A+E+A+1+3+7+8+0+7+7+2+1+4+9+2+4+2+4+2+C+1+6+C=88 !=   BD
      // Date & Time
      // ==================================================================================
      // eac0  Ampere meter: cent-a-meter, OWL CM113, Electrisave
      // ==================================================================================
      if(id == 0xeac0) { 
        //Serial.println("UNKNOWN LAYOUT");
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        // ----------------------------------
        Serial.print(F(";Oregon Unknown;DEBUG="));                 // Label
        PrintHex8( osdata, 13);
        Serial.println(";");  
      } else  
      // ==================================================================================
      // 0x1a* / 0x2a* 0x3a** Power meter: OWL CM119
      // ==================================================================================
      // 0x628* Power meter: OWL CM180
      // ==================================================================================
      // OSV3 6284 3C 7801 D0 
      // OSV3 6280 3C 2801 A0A8BA05 00 00 ?? ?? ?? 
      // ==================================================================================
      // 1a99  Anemometer: WGTR800
      // WIND + TEMP + HUM + CRC
      // ==================================================================================
      if(id == 0x1a99) { // Wind sensor
        //Serial.println("UNKNOWN LAYOUT");
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        // ----------------------------------
        Serial.print(F(";Oregon Unknown;DEBUG="));                // Label
        PrintHex8( osdata, 13);
        Serial.println(";");  
      } else    
      // ==================================================================================
      if( (id&0xf00)==0xA00 ) { // Any Oregon sensor with id xAxx 
        // ----------------------------------
        // Output
        // ----------------------------------
        Serial.print("20;");
        PrintHexByte(PKSequenceNumber++);
        // ----------------------------------
        Serial.print(F(";Oregon Unknown;DEBUG="));                // Label
        PrintHex8( osdata, 13);
        Serial.println(";");  
      }
      // ==================================================================================
      RawSignal.Repeats=true;                    // suppress repeats of the same RF packet 
      RawSignal.Number=0;
      return true;
}
#endif // PLUGIN_048
Arduino oregon sensor simulator (Protocol V2.1):
433 TX_PIN 10
DHT11 sensor on pin 2

Code: Select all

/*
 * Oregon Scientific v2.1 Emitter with DHT11 sensor
*/

/*

   Exemple de trames:
   OSV2 EA4C106F7011D0D30300
   OSV3 FA28A428202290834B46
   OSV2 EA4C106F7011D0D30300
   OSV2 EA4C106F7011D0D30300
   OSV3 FA28A428202290834B46
   OSV2 EA4C106F7011D0D30300
   OSV2 EA4C106F7011D0D30300
   OSV3 FA28A428202290834B46
   OSV3 FA28A428202290834B46
   OSV2 EA4C106F6011C0A30600
   OSV2 EA4C106F6011C0A30600
   OSV2 EA4C106F6011C0A30600
   OSV3 FA28A428202290834B46
   OSV2 EA4C106F6011C0A30600
   OSV3 FA28A428202290834B46
   OSV2 EA4C106F6011C0A30600
   OSV2 EA4C106F6011C0A30600

   Bit 0 is sent first, then bit 1, 2, 3, 4, 5, 6, and then bit 7 of a byte
   
   The sample packet above is from a THGR122NX on channel 1 with rolling code  EC . It's returning a temperature of +27.3°C, and humidity 65%:
   1A 2D 10 EC 32 27 50 06 44 25 
   
  - 0-3: Device ID. The ID for THGN132N sensors is  1A2D .
  - 4: Channel. This corresponds to the channel slider on the back of the sensor ( 1, 2, or 4 for channel 1, 2 or 3).
  - 5: Battery? All of my readings have 0 for this nibble. I'm half-expecting it to become non-zero on low battery.
  - 6-7: Rolling code. This is a unique identifier for the sensor. It resets when the battery is replaced.
  - 8: The tenths digit of the temperature.
  - 10: The tens digit of the temperature.
  - 11: The unit digit of the temperature.
  - 12: The unit digit of the humidity.
  - 13: The sign for the temperature. This nibble will be 0 for a +ve temp, and non-zero for -ve. During my testing with the sensor in the freezer, I've only seen this return 0 or 8.
  - 15: The tens digit of the humidity.

  --------------------------------------------------------
  |  Sensor Name      |  Code   | Type                   |
  --------------------------------------------------------
  |  Oregon-THR128    |         |                        |
  |  Oregon-THR138    | 0x0A4D  | Inside Temperature     |
  |  Oregon-THC138    |         |                        |
  -------------------------------------------------------- 
  | Oregon-THC238     |         |                        |
  | Oregon-THC268     |         |                        |
  | Oregon-THN132N    |         |                        |
  | Oregon-THWR288A   | 0xEA4C  | Outside/Water Temp     | 
  | Oregon-THRN122N   |         |                        |
  | Oregon-THN122N    |         |                        |
  | Oregon-AW129      |         |                        |
  | Oregon-AW131      |         |                        |
  --------------------------------------------------------
  | Oregon-THWR800    | 0xCA48  | Water Temp             |
  -------------------------------------------------------- 
  | Oregon-THGN122N   |         |                        |
  | Oregon-THGN123N   |         |                        |
  | Oregon-THGR122NX  | 0x1A2D  | Inside Temp-Hygro      |
  | Oregon-THGR228N   |         |                        |
  | Oregon-THGR238    |         |                        |
  | Oregon-THGR268    |         |                        |
  --------------------------------------------------------
  | Oregon-THGR810    | 0xFA28  | Inside Temp-Hygro      |
  | Oregon-RTGR328N   | 0x*ACC  | Outside Temp-Hygro     |
  | Oregon-THGR328N   | 0xCA2C  | Outside Temp-Hygro     |
  | Oregon-WTGR800    | 0xFAB8  | Outside Temp-Hygro     |
  --------------------------------------------------------
  | Oregon-THGR918    |         |                        |
  | Oregon-THGRN228NX | 0x1A3D  | Outside Temp-Hygro     |
  | Oregon-THGN500    |         |                        |
  --------------------------------------------------------
  | Huger - BTHR918   | 0x5A5D  | Inside Temp-Hygro-Baro |
  --------------------------------------------------------
  | Oregon-BTHR918N   |         |                        |
  | Oregon-BTHR968    | 0x5A6D  | Inside Temp-Hygro-Baro |
  --------------------------------------------------------
  | Oregon-RGR126     |         |                        |
  | Oregon-RGR682     | 0x2A1D  | Rain Gauge             |
  | Oregon-RGR918     |         |                        |
  --------------------------------------------------------
  | Oregon-PCR800     | 0x2A19  | Rain Gauge             |
  | Oregon-WTGR800    | 0x1A99  | Anemometer             |
  | Oregon-WGR800     | 0x1A89  | Anemometer             |
  --------------------------------------------------------
  | Huger-STR918      |         |                        |
  | Oregon-WGR918     | 0x3A0D  | Anemometer             |
  --------------------------------------------------------
  | Oregon-UVN128     |         |                        |
  | Oregon-UV138      | 0xEA7C  | UV sensor              |
  --------------------------------------------------------
  | Oregon-UVN800     | 0xDA78  | UV sensor              |
  | Oregon-RTGR328N   | 0x*AEC  | Date & Time            |
  --------------------------------------------------------
  | cent-a-meter      |         |                        |
  | OWL CM113         | 0xEAC0  | Ampere meter           |
  | Electrisave       |         |                        |
  --------------------------------------------------------
  | OWL CM119         | 0x1A*                            |
  |                   | 0x2A*   | Power meter            |
  |                   | 0x3A**  |                        |
  --------------------------------------------------------

*/

// defined THN132N Temp only
// undefined THGR228N Temp/Humidity
// #define THN132N

const byte TX_PIN = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

#define DHTPIN 2     // what pin we're connected to

#include "DHT.h"

// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);

// Outside/Water Temp
#define  Oregon_THN132N_ID   0xEA4C
// Inside Temp-Hygro
#define  Oregon_THGR228N_ID  0x1A2D  

const unsigned long TIME = 512;
const unsigned long TWOTIME = TIME*2;
 
#define SEND_HIGH() digitalWrite(TX_PIN, HIGH)
#define SEND_LOW() digitalWrite(TX_PIN, LOW)
 
// Buffer for Oregon message
#ifdef THN132N
  byte OregonMessageBuffer[9];
#else
  byte OregonMessageBuffer[9];
#endif
 
/**
 * \brief    Send logical "0" over RF
 * \details  azero bit be represented by an off-to-on transition
 * \         of the RF signal at the middle of a clock period.
 * \         Remenber, the Oregon v2.1 protocol add an inverted bit first 
 */
inline void sendZero(void) 
{
  SEND_HIGH();
  delayMicroseconds(TIME);
  SEND_LOW();
  delayMicroseconds(TWOTIME);
  SEND_HIGH();
  delayMicroseconds(TIME);
}
 
/**
 * \brief    Send logical "1" over RF
 * \details  a one bit be represented by an on-to-off transition
 * \         of the RF signal at the middle of a clock period.
 * \         Remenber, the Oregon v2.1 protocol add an inverted bit first 
 */
inline void sendOne(void) 
{
   SEND_LOW();
   delayMicroseconds(TIME);
   SEND_HIGH();
   delayMicroseconds(TWOTIME);
   SEND_LOW();
   delayMicroseconds(TIME);
}
 
/**
* Send a bits quarter (4 bits = MSB from 8 bits value) over RF
*
* @param data Source data to process and sent
*/
 
/**
 * \brief    Send a bits quarter (4 bits = MSB from 8 bits value) over RF
 * \param    data   Data to send
 */
inline void sendQuarterMSB(const byte data) 
{
  (bitRead(data, 4)) ? sendOne() : sendZero();
  (bitRead(data, 5)) ? sendOne() : sendZero();
  (bitRead(data, 6)) ? sendOne() : sendZero();
  (bitRead(data, 7)) ? sendOne() : sendZero();
}
 
/**
 * \brief    Send a bits quarter (4 bits = LSB from 8 bits value) over RF
 * \param    data   Data to send
 */
inline void sendQuarterLSB(const byte data) 
{
  (bitRead(data, 0)) ? sendOne() : sendZero();
  (bitRead(data, 1)) ? sendOne() : sendZero();
  (bitRead(data, 2)) ? sendOne() : sendZero();
  (bitRead(data, 3)) ? sendOne() : sendZero();
}
 
/******************************************************************/
/******************************************************************/
/******************************************************************/
 
/**
 * \brief    Send a buffer over RF
 * \param    data   Data to send
 * \param    size   size of data to send
 */
void sendData(byte *data, byte size)
{
  for(byte i = 0; i < size; ++i)
  {
    sendQuarterLSB(data[i]);
    sendQuarterMSB(data[i]);
  }
}
 
/**
 * \brief    Send an Oregon message
 * \param    data   The Oregon message
 */
void sendOregon(byte *data, byte size)
{
    sendPreamble();
    sendSync();
    sendData(data, size);
    sendPostamble();
}
 
/**
 * \brief    Send preamble
 * \details  The preamble consists of 16 "1" bits
 */
inline void sendPreamble(void)
{
  byte PREAMBLE[]={0xFF,0xFF};
  sendData(PREAMBLE, 2);
}
 
/**
 * \brief    Send postamble
 * \details  The postamble consists of 8 "0" bits
 */
inline void sendPostamble(void)
{
#ifdef THN132N
  sendQuarterLSB(0x00);
#else
  byte POSTAMBLE[]={0x00};
  sendData(POSTAMBLE, 1);  
#endif
}
 
/**
 * \brief    Send sync nibble
 * \details  The sync is 0xA. It is not use in this version since the sync nibble
 * \         is include in the Oregon message to send.
 */
inline void sendSync(void)
{
  sendQuarterLSB(0xA);
}
 
/******************************************************************/
/******************************************************************/
/******************************************************************/
 
/**
 * \brief    Set the sensor type
 * \param    data       Oregon message
 * \param    type       Sensor type
 */
inline void setType(byte *data, byte* type) 
{
  data[0] = type[0];
  data[1] = type[1];
}
 
/**
 * \brief    Set the sensor channel
 * \param    data       Oregon message
 * \param    channel    Sensor channel (0x10, 0x20, 0x40)
 */
inline void setChannel(byte *data, byte channel) 
{
    data[2] = channel;
}
 
/**
 * \brief    Set the sensor ID
 * \param    data       Oregon message
 * \param    ID         Sensor unique ID
 */
inline void setId(byte *data, byte ID) 
{
  data[3] = ID;
}
 
/**
 * \brief    Set the sensor battery level
 * \param    data       Oregon message
 * \param    level      Battery level (0 = low, 1 = high)
 */
void setBatteryLevel(byte *data, byte level)
{
  if(!level) data[4] = 0x0C;
  else data[4] = 0x00;
}
 
/**
 * \brief    Set the sensor temperature
 * \param    data       Oregon message
 * \param    temp       the temperature
 */
void setTemperature(byte *data, float temp) 
{
  // Set temperature sign
  if(temp < 0)
  {
    data[6] = 0x08;
    temp *= -1;  
  }
  else
  {
    data[6] = 0x00;
  }
 
  // Determine decimal and float part
  int tempInt = (int)temp;
  int td = (int)(tempInt / 10);
  int tf = (int)round((float)((float)tempInt/10 - (float)td) * 10);
 
  int tempFloat =  (int)round((float)(temp - (float)tempInt) * 10);
 
  // Set temperature decimal part
  data[5] = (td << 4);
  data[5] |= tf;
 
  // Set temperature float part
  data[4] |= (tempFloat << 4);
}
 
/**
 * \brief    Set the sensor humidity
 * \param    data       Oregon message
 * \param    hum        the humidity
 */
void setHumidity(byte* data, byte hum)
{
    data[7] = (hum/10);
    data[6] |= (hum - data[7]*10) << 4;
}
 
/**
 * \brief    Sum data for checksum
 * \param    count      number of bit to sum
 * \param    data       Oregon message
 */
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;
}
 
/**
 * \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
}
 
/******************************************************************/
/******************************************************************/
/******************************************************************/
 
void setup()
{
  pinMode(TX_PIN, OUTPUT);
 
  Serial.begin(9600);
  Serial.println("\n[Oregon V2.1 encoder]");
  SEND_LOW();  
 
#ifdef THN132N  
  Serial.println("THN132N - temperature only");
  // Create the Oregon message for a temperature only sensor (TNHN132N)
  // byte ID[] = {0xEA,0x4C};
  byte ID[] = {Oregon_THN132N_ID >> 8,Oregon_THN132N_ID & 0xff};
#else
  Serial.println("THGR228N - temperature/humidity");
  // Create the Oregon message for a temperature/humidity sensor (THGR228N)
  // byte ID[] = {0x1A,0x2D};
  byte ID[] = {Oregon_THGR228N_ID >> 8,Oregon_THGR228N_ID & 0xff};
#endif  
 
  setType(OregonMessageBuffer, ID);
  setChannel(OregonMessageBuffer, 0x20);
  setId(OregonMessageBuffer, 0xBB);
}
 
void loop()
{
  // Get Temperature, humidity and battery level from sensors
  // (ie: 1wire DS18B20 for température, ...)
  setBatteryLevel(OregonMessageBuffer, 1); // 0 : low, 1 : high
  
  // Read temperature as Celsius
  float t = dht.readTemperature();
  Serial.print("Temperature = ");
  Serial.print(t);
  Serial.println("C");
  setTemperature(OregonMessageBuffer, t);
 
#ifndef THN132N
  float h = dht.readHumidity() + 0.5;
  Serial.print("Humidity = ");
  Serial.print(h);
  Serial.println("%");
  // Set Humidity
  setHumidity(OregonMessageBuffer, (int)h);
#endif  
 
  // Calculate the checksum
  calculateAndSetChecksum(OregonMessageBuffer);
 
  // Show the Oregon Message
  for (byte i = 0; i < sizeof(OregonMessageBuffer); ++i)   {
    Serial.print(OregonMessageBuffer[i] >> 4, HEX);
    Serial.print(OregonMessageBuffer[i] & 0x0F, HEX);
  }
  Serial.println("");
  
  // Send the Message over RF
  sendOregon(OregonMessageBuffer, sizeof(OregonMessageBuffer));
  // Send a "pause"
  SEND_LOW();
  delayMicroseconds(TWOTIME*8);
  // Send a copie of the first message. The v2.1 protocol send the
  // message two time 
  sendOregon(OregonMessageBuffer, sizeof(OregonMessageBuffer));
 
  // Wait for 30 seconds before send a new message 
  SEND_LOW();
  delay(30000);
}
Perhaps this can help you with real oregon sensor

Michel
dugolf
Posts: 6
Joined: Tuesday 14 October 2014 22:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.7450
Location: France
Contact:

Re: oregon sensors in Dz

Post by dugolf »

I have downloaded the firmware RFLink_v1.1_r37 and it is working properly without any modification using the "Arduino oregon sensor simulator" above
Thanks to Stuntteam
dugolf
Posts: 6
Joined: Tuesday 14 October 2014 22:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.7450
Location: France
Contact:

Re: oregon sensors in Dz

Post by dugolf »

Test with RFLink_v1.1_r37
1 - THN132N simulation
When i send EA4C106F30119003 the message is recognized by rflink as:
20;6E;Oregon Temp;ID=6F10;TEMP=0071;BAT=OK;
The ID is 6F10 where 10 is the channel

2 - THGR228N simulation
When i send 1A2D40C45021700639 the message is recognised by rflink as:
20;9D;Oregon TempHygro;ID=2DC4;TEMP=00d7;HUM=67;HSTATUS=0;BAT=OK;
The ID is 2DC4. It does not contain the channel number.

I thought as to THN132N , it would be equal to C440 where 40 is the channel number.
Where is my mistake ?
dugolf
Posts: 6
Joined: Tuesday 14 October 2014 22:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.7450
Location: France
Contact:

Re: oregon sensors in Dz

Post by dugolf »

I think if there is a problem, it's in Plugin_048.c:
For THN132N (id == 0xea4c):
Serial.print(F(";Oregon Temp;ID=")); // Label
PrintHexByte(osdata[3]);
PrintHexByte(osdata[2]);

For THGR228N (id == 0x1a2d):
Serial.print(F(";Oregon TempHygro;ID=")); // Label
PrintHexByte(osdata[1]);
PrintHexByte(osdata[3]);
The begin of the buffer description is the same for THN132N & THGR228N.
osdata[0], osdata[1] = ea4c or 1a2d
osdata[2] = channel
osdata[3] = id

For THGR228N the code sould be the same:
Serial.print(F(";Oregon TempHygro;ID=")); // Label
PrintHexByte(osdata[3]);
PrintHexByte(osdata[2]);

am i right ?
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest