modifications for 36-bit sensor by Vitaliy86
[Arduino] / outdoor_temperature_sensor / outdoor_temperature_sensor.ino
1 // Unknown 433Mhz weather sensor decoder. Untested in the real world.
2 // http://arduino.cc/forum/index.php/topic,142871.msg1106336.html#msg1106336
3
4 // __           ___       ___    ___
5 //   |         |  |      |  |   |  |
6 //   |_________|  |______|  |___|  |
7 //
8 //   |  Sync      |    1    |  0   |
9 //   |  8320us    | 4500us  | 2530us
10
11 // Defines
12 #define DataBits0 4                                       // Number of data0 bits to expect
13 #define DataBits1 32                                      // Number of data1 bits to expect
14 #define allDataBits 36                                    // Number of data sum 0+1 bits to expect
15 // isrFlags bit numbers
16 #define F_HAVE_DATA 1                                     // 0=Nothing in read buffer, 1=Data in read buffer
17 #define F_GOOD_DATA 2                                     // 0=Unverified data, 1=Verified (2 consecutive matching reads)
18 #define F_CARRY_BIT 3                                     // Bit used to carry over bit shift from one long to the other
19 #define F_STATE 7                                         // 0=Sync mode, 1=Data mode
20
21
22
23 // Constants
24 const unsigned long sync_MIN = 4300;                      // Minimum Sync time in micro seconds
25 const unsigned long sync_MAX = 4700;
26
27 const unsigned long bit1_MIN = 2300;
28 const unsigned long bit1_MAX = 2700;
29
30 const unsigned long bit0_MIN = 1330;
31 const unsigned long bit0_MAX = 1730;
32
33 const unsigned long glitch_Length = 300;                  // Anything below this value is a glitch and will be ignored.
34
35 // Interrupt variables
36 unsigned long fall_Time = 0;                              // Placeholder for microsecond time when last falling edge occured.
37 unsigned long rise_Time = 0;                              // Placeholder for microsecond time when last rising edge occured.
38 byte bit_Count = 0;                                       // Bit counter for received bits.
39 unsigned long build_Buffer[] = {0,0};                     // Placeholder last data packet being received.
40 volatile unsigned long read_Buffer[] = {0,0};             // Placeholder last full data packet read.
41 volatile byte isrFlags = 0;                               // Various flag bits
42
43 void PinChangeISR0(){                                     // Pin 2 (Interrupt 0) service routine
44   unsigned long Time = micros();                          // Get current time
45   if (digitalRead(2) == LOW) {
46 // Falling edge
47     if (Time > (rise_Time + glitch_Length)) {
48 // Not a glitch
49       Time = micros() - fall_Time;                        // Subtract last falling edge to get pulse time.
50       if (bitRead(build_Buffer[1],31) == 1)
51         bitSet(isrFlags, F_CARRY_BIT);
52       else
53         bitClear(isrFlags, F_CARRY_BIT);
54
55       if (bitRead(isrFlags, F_STATE) == 1) {
56 // Looking for Data
57         if ((Time > bit0_MIN) && (Time < bit0_MAX)) {
58 // 0 bit
59           build_Buffer[1] = build_Buffer[1] << 1;
60           build_Buffer[0] = build_Buffer[0] << 1;
61           if (bitRead(isrFlags,F_CARRY_BIT) == 1)
62             bitSet(build_Buffer[0],0);
63           bit_Count++;
64         }
65         else if ((Time > bit1_MIN) && (Time < bit1_MAX)) {
66 // 1 bit
67           build_Buffer[1] = build_Buffer[1] << 1;
68           bitSet(build_Buffer[1],0);
69           build_Buffer[0] = build_Buffer[0] << 1;
70           if (bitRead(isrFlags,F_CARRY_BIT) == 1)
71             bitSet(build_Buffer[0],0);
72           bit_Count++;
73         }
74         else {
75 // Not a 0 or 1 bit so restart data build and check if it's a sync?
76           bit_Count = 0;
77           build_Buffer[0] = 0;
78           build_Buffer[1] = 0;
79           bitClear(isrFlags, F_GOOD_DATA);                // Signal data reads dont' match
80           bitClear(isrFlags, F_STATE);                    // Set looking for Sync mode
81           if ((Time > sync_MIN) && (Time < sync_MAX)) {
82             // Sync length okay
83             bitSet(isrFlags, F_STATE);                    // Set data mode
84           }
85         }
86         if (bit_Count >= allDataBits) {
87 // All bits arrived
88           bitClear(isrFlags, F_GOOD_DATA);                // Assume data reads don't match
89           if (build_Buffer[0] == read_Buffer[0]) {
90             if (build_Buffer[1] == read_Buffer[1]) 
91               bitSet(isrFlags, F_GOOD_DATA);              // Set data reads match
92           }
93           read_Buffer[0] = build_Buffer[0];
94           read_Buffer[1] = build_Buffer[1];
95           bitSet(isrFlags, F_HAVE_DATA);                  // Set data available
96           bitClear(isrFlags, F_STATE);                    // Set looking for Sync mode
97 digitalWrite(13,HIGH); // Used for debugging
98           build_Buffer[0] = 0;
99           build_Buffer[1] = 0;
100           bit_Count = 0;
101         }
102       }
103       else {
104 // Looking for sync
105         if ((Time > sync_MIN) && (Time < sync_MAX)) {
106 // Sync length okay
107           build_Buffer[0] = 0;
108           build_Buffer[1] = 0;
109           bit_Count = 0;
110           bitSet(isrFlags, F_STATE);                      // Set data mode
111 digitalWrite(13,LOW); // Used for debugging
112         }
113       }
114       fall_Time = micros();                               // Store fall time
115     }
116   }
117   else {
118 // Rising edge
119     if (Time > (fall_Time + glitch_Length)) {
120       // Not a glitch
121       rise_Time = Time;                                   // Store rise time
122     }
123   }
124 }
125
126
127 void setup() {
128 pinMode(13,OUTPUT); // Used for debugging
129   Serial.begin(9600);
130   pinMode(2,INPUT);
131   Serial.println(F("ISR Pin 2 Configured For Input."));
132   attachInterrupt(0,PinChangeISR0,CHANGE);
133   Serial.println(F("Pin 2 ISR Function Attached. Here we go."));
134 }
135
136 void loop() {
137   unsigned long myData0 = 0;
138   unsigned long myData1 = 0;
139   if (bitRead(isrFlags,F_GOOD_DATA) == 1) 
140 {
141     // We have at least 2 consecutive matching reads
142     myData0 = read_Buffer[0]; // Read the data spread over 2x 32 variables
143     myData1 = read_Buffer[1];
144     bitClear(isrFlags,F_HAVE_DATA); // Flag we have read the data
145     dec2binLong(myData0,DataBits0);
146     dec2binLong(myData1,DataBits1);
147
148     Serial.print(" - Battery=");
149     byte H = (myData1 >> 26) & 0x3;   // Get Battery
150     Serial.print(H);
151     
152     Serial.print(" Channel=");
153     H = ((myData1 >> 24) & 0x3) + 1;        // Get Channel
154     Serial.print(H);
155     
156     Serial.print(" Temperature=");
157     byte ML = (myData1 >> 12) & 0xF0; // Get MMMM
158 //     Serial.print(" (M=");
159 //     Serial.print(ML);
160     H = (myData1 >> 12) & 0xF;        // Get LLLL
161 //     Serial.print(" L=");
162 //     Serial.print(H);
163     ML = ML | H;                      // OR MMMM & LLLL nibbles together
164     H = (myData1 >> 20) & 0xF;        // Get HHHH
165 //     Serial.print(" H=");
166 //     Serial.print(H);
167 //     Serial.print(" T= ");
168     byte HH = 0;
169     if((myData1 >> 23) & 0x1 == 1) //23 bit
170          HH = 0xF;
171     int Temperature = (H << 8)|(HH << 12) | ML;  // Combine HHHH MMMMLLLL
172 //     Serial.print( Temperature);
173 //     Serial.print(") ");
174     // Temperature = Temperature*3; //F // Remove Constant offset
175     Serial.print(Temperature/10.0,1);   
176     Serial.print("C Humidity=");
177     H = (myData1 >> 0) & 0xF0;        // Get HHHH
178 //     Serial.print(" (H=");
179 //     Serial.print(H);
180     ML = (myData1 >> 0) & 0xF;       // Get LLLL
181 //     Serial.print(" L=");
182 //     Serial.print(ML);
183 //     Serial.print(") ");
184     ML = ML | H;                      // OR HHHH & LLLL nibbles together
185     Serial.print(ML);
186     Serial.println("%");
187   }
188   delay(100);
189 }
190
191 void dec2binLong(unsigned long myNum, byte NumberOfBits) {
192   if (NumberOfBits <= 32){
193     myNum = myNum << (32 - NumberOfBits);
194     for (int i=0; i<NumberOfBits; i++) {
195       if (bitRead(myNum,31) == 1) 
196       Serial.print("1");
197       else 
198       Serial.print("0");
199       myNum = myNum << 1;
200     }
201   }
202 }