#include "esic.h" #include #include #include "esp_log.h" #include "../rxTimer.h" #include "../led.h" /** ********************************************************************************** * TEMP 3 * ESIC WT450H +---+ +---+ +-------+ + high | | | | | | | | | | | | | | + +---+ +---+ +-------+ low ^ ^ ^ ^ ^ clock cycle | 1 | 1 | 0 | 0 | translates as Each transmission is 36 bits long (i.e. 72 ms) .short_width = 976, // half-bit width 976 us .long_width = 1952, // bit width 1952 us Data is transmitted in pure binary values, NOT BCD-coded. Example transmission (House 1, Channel 1, RH 59 %, Temperature 23.5 �C) 1100 00010011001110110100100110011000 b00 - b03 (4 bits): Constant, 1100, probably preamble b04 - b07 (4 bits): House code (here: 0001 = HC 1) b08 - b09 (2 bits): Channel code - 1 (here 00 = CC 1) b10 - b12 (3 bits): Constant, 110 b13 - b19 (7 bits): Relative humidity (here 0111011 = 59 %) b20 - b34 (15 bits): Temperature (see below) b35 - b35 (1 bit) : Parity (xor of all bits should give 0) The temperature is transmitted as (temp + 50.0) * 128, which equals (temp * 128) + 6400. Adding 50.0 �C makes all values positive, an unsigned 15 bit integer where the first 8 bits correspond to the whole part of the temperature (here 01001001, decimal 73, substract 50 = 23). Remaining 7 bits correspond to the fractional part. To avoid floating point calculations I store the raw temperature value as a signed integer in the variable esicTemp, then transform it to actual temperature * 10 using "esicTemp = (esicTemp - 6400) * 10 / 128", where 6400 is the added 50 times 128. When reporting the temperature I simply print "esicTemp / 10" (integer division, no fraction), followed by a decimal point and "esicTemp % 10" (remainder, which equals first fractional decimal digit). Summary of bit fields: 1100 0001 00 110 0111011 010010011001100 0 c1 hc cc c2 rh t p c1, c2 = constant field 1 and 2 hc, cc = house code and channel code rh, t = relative humidity, temperature p = parity bit 1111111111111110 This interpretation is from: https://github.com/merbanan/rtl_433/blob/master/src/devices/wt450.c 1100 0001 | 0011 0011 | 1000 0011 | 1011 0011 | 0001 xxxx ssss | ccxx bhhh | hhhh tttt | tttt tttt | sseo - x: constant - s: House code - c: Channel - b: battery low indicator (0=>OK, 1=>LOW) - h: Humidity - t: Temperature, 12 bit, offset 50, scale 16 - s: sequence number of message repeat - e: parity of all even bits - o: parity of all odd bits ********************************************************************************** */ volatile unsigned long long temp3_x_data; void ESIC_ResetDecoder() { temp3_x_data = 0; } #define NO_OF_PULSES 60 #define max(a,b) (((a)>(b))?(a):(b)) #define isShortPulse(width) (((long_pulse/2)-maxDiff) <= width && width <= ((long_pulse/2)+maxDiff)) #define isLongPulse(width) ((long_pulse-maxDiff) <= width && width <= (long_pulse+maxDiff)) unsigned int temp3_pulses[NO_OF_PULSES]; static int long_pulse = 1955; static int maxDiff = 300; static void storePulses(unsigned int inWidth) { int i; // Shift pulses down for(i=1;i1;i--) { temp3_pulses[i] = temp3_pulses[i-2]; } temp3_pulses[0] = 0; temp3_pulses[1] = 0; } } } /*static void adjustTiming() { int p1 = temp3_pulses[NO_OF_PULSES-8]; int p2 = temp3_pulses[NO_OF_PULSES-7]; int p3 = temp3_pulses[NO_OF_PULSES-6]; int p4 = temp3_pulses[NO_OF_PULSES-5]; int p5 = temp3_pulses[NO_OF_PULSES-4]; int p6 = temp3_pulses[NO_OF_PULSES-3]; int p7 = temp3_pulses[NO_OF_PULSES-2]; int p8 = temp3_pulses[NO_OF_PULSES-1]; // Check max differance between the short pulses int sh_mean = (p1+p2+p3+p4) / 4; int sh_max_diff = max(max(abs(p1-sh_mean),abs(p2-sh_mean)),max(abs(p3-sh_mean),abs(p4-sh_mean))); // Check max differance between the long pulses int long_mean = (p5+p6+p7+p8) / 4; int long_max_diff = max(max(abs(p5-long_mean),abs(p6-long_mean)),max(abs(p7-long_mean),abs(p8-long_mean))); if( sh_max_diff < maxDiff && long_max_diff < maxDiff ) { int mean = (long_mean + sh_mean)/2; if( long_mean > (mean+maxDiff) && sh_mean < (mean-maxDiff) ) { if( abs(long_mean - (sh_mean*2)) < maxDiff ) { long_pulse = (long_mean + sh_mean*2)/2; maxDiff = long_mean / 15; } } } }*/ // The latest/newest pulse is at the end of the array [59] // This ([59]) is the latest bit in the bit-stream from the transmitter // This is way we input the bits at a high position and shift them towards lower values // So..start reading backwards and working towards the first/highest bits static int checkPulsePattern() { int i = NO_OF_PULSES-1; // Start reading from the last received (end of array) int b = 0; unsigned long long code = 0; while( i >= 0 ) { int combWidth = temp3_pulses[i] + temp3_pulses[i-1]; if( isLongPulse(temp3_pulses[i]) ) { b++; i-=1; code = code >> 1; } else if( isShortPulse(temp3_pulses[i]) && isShortPulse(temp3_pulses[i-1]) ) { b++; i-=2; code = ((code >> 1) | 0x200000000); } else if( isLongPulse( combWidth ) ) { b++; i-=2; code = ((code >> 1) | 0x200000000); } else { return -1; } if( b == 34 ) { /* 0000 0001 00 110 0101000 010010110101000 1 AND: 0011 1111 00 111 0000000 000000000000000 0 = 001111110011100000000000000000000000 = 0x3F3800000 RES: 0000 0001 00 110 0000000 000000000000000 0 = 000000010011000000000000000000000000 = 0x013000000 Summary of bit fields: 1100 0001 00 110 0111011 010010011001100 0 c1 hc cc c2 rh t p */ if( (code & 0x3F3800000) == 0x013000000 ) { temp3_x_data = (code&0xFFFFFFFF); // Check parity int even=0; unsigned long long data = temp3_x_data; for(int i=0;i<32;i++) { if( data & 1 ) even++; data >>= 1; } if( even % 2 != 0 ) { return -1; } // A correct code has been received //printf("Code received: %llu on row:%d\n",(code&0xFFFFFFFF),row_no); temp3_x_data &= 0xFFFFFFF0; // Remove sequence and parity bits in lowest nibble return 1; } else { return -1; } } } return 0; } static int temp3decode (unsigned int inWidth) { int width = inWidth; //preProcessPulses(inWidth); if( width == -1 ) return -1; if( width == 0 ) return 0; storePulses(inWidth); sweepForNoise(); //adjustTiming(); return checkPulsePattern(); } int64_t nextPulseESICSensor(uint32_t width) { static int64_t previous_data = 0; static uint32_t old_time=0; static uint32_t now; int64_t retVal = -1; if( width > 0 ) { if( temp3_x_data == 0 ) { temp3decode(width); } } if( temp3_x_data > 0 ) { now = millis(); if( temp3_x_data != previous_data || (now > (old_time+1000)) ) { previous_data = temp3_x_data; retVal = temp3_x_data; blinkTheLED(); } old_time = now; ESIC_ResetDecoder(); } return retVal; }