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