return no data if no new signals are received
[Arduino] / rpi_promini / rpi_promini.ino
1 /*
2
3   Connect Arduino ProMini 3.3V 8Mhz Atmega328 to Raspberry Pi
4   
5   RPI pin  Arduino
6   RXD      TXD
7   TXD      RXD
8   GPIO6    RST
9   GND      GND
10   +5V      RAW
11
12            2    433Mhz receive
13            3    433Mhz outdoor temperature sensor receiver
14            10   433Mhz send
15            11   DS18B20
16            13   513Mhz send
17
18 */
19
20 #include <RCSwitch.h>
21
22 #include <OneWire.h>
23 #include <DallasTemperature.h>
24
25 RCSwitch mySwitch = RCSwitch();
26
27 // DS18B20 on pin 11
28 OneWire oneWire(11);
29 DallasTemperature sensors(&oneWire);
30
31
32 // 513Mhz light sockets
33 #define TX_PIN 12
34 #define LED_PIN 13
35
36 int int_0 = 300; // ms
37 int int_1 = 900; // ms
38 int wait  = 2000; // ms
39 int repeat = 5; // times
40
41 void send_513(char *code) {
42   Serial.print("send 513Mhz ");
43   Serial.println(code);
44   
45   // we have to send same signal at least two times
46   for(int r = 0; r < repeat; r++ ) {
47
48     digitalWrite(LED_PIN, HIGH);
49
50     for(int i = 0; i < strlen(code); i++) {
51       int i1 = int_0;
52       int i2 = int_1;
53       if (code[i] == '1' ) {
54         i1 = int_1;
55         i2 = int_0;
56       }
57       digitalWrite(TX_PIN, HIGH);
58       delayMicroseconds(i1);
59       digitalWrite(TX_PIN, LOW);
60       delayMicroseconds(i2);
61     }
62
63     delayMicroseconds(wait); // guess
64   }
65
66   digitalWrite(LED_PIN, LOW);
67 }
68
69
70 // outdoor 433 MHz temperature sensor
71
72 // Unknown 433Mhz weather sensor decoder. Untested in the real world.
73 // http://arduino.cc/forum/index.php/topic,142871.msg1106336.html#msg1106336
74
75 // __           ___       ___    ___
76 //   |         |  |      |  |   |  |
77 //   |_________|  |______|  |___|  |
78 //
79 //   |  Sync      |    1    |  0   |
80 //   |  9780us    | 4420us  | 2410us
81 //      9810        4410      2490
82
83 // Defines
84 #define DataBits0 4                                       // Number of data0 bits to expect
85 #define DataBits1 32                                      // Number of data1 bits to expect
86 #define allDataBits 36                                    // Number of data sum 0+1 bits to expect
87 // isrFlags bit numbers
88 #define F_HAVE_DATA 1                                     // 0=Nothing in read buffer, 1=Data in read buffer
89 #define F_GOOD_DATA 2                                     // 0=Unverified data, 1=Verified (2 consecutive matching reads)
90 #define F_CARRY_BIT 3                                     // Bit used to carry over bit shift from one long to the other
91 #define F_STATE 7                                         // 0=Sync mode, 1=Data mode
92
93 // uno: pin 2 = int.0 or pin 3 = int.1 see
94 // http://arduino.cc/en/Reference/attachInterrupt
95 #define ISR_PIN 3
96 #define ISR_INT 1
97
98 // Constants
99 const unsigned long sync_MIN = 9600;                      // Minimum Sync time in micro seconds
100 const unsigned long sync_MAX = 9900;
101
102 const unsigned long bit1_MIN = 4200;
103 const unsigned long bit1_MAX = 4600;
104
105 const unsigned long bit0_MIN = 2200;
106 const unsigned long bit0_MAX = 2600;
107
108 const unsigned long glitch_Length = 300;                  // Anything below this value is a glitch and will be ignored.
109
110 // Interrupt variables
111 unsigned long fall_Time = 0;                              // Placeholder for microsecond time when last falling edge occured.
112 unsigned long rise_Time = 0;                              // Placeholder for microsecond time when last rising edge occured.
113 byte bit_Count = 0;                                       // Bit counter for received bits.
114 unsigned long build_Buffer[] = {0,0};                     // Placeholder last data packet being received.
115 volatile unsigned long read_Buffer[] = {0,0};             // Placeholder last full data packet read.
116 volatile byte isrFlags = 0;                               // Various flag bits
117 volatile unsigned long last_Buffer[] = {0,0};
118
119 void PinChangeISR(){                                     // Pin 2 (Interrupt 0) service routine
120   unsigned long Time = micros();                          // Get current time
121   if (digitalRead(ISR_PIN) == LOW) {
122 // Falling edge
123     if (Time > (rise_Time + glitch_Length)) {
124 // Not a glitch
125       Time = micros() - fall_Time;                        // Subtract last falling edge to get pulse time.
126       if (bitRead(build_Buffer[1],31) == 1)
127         bitSet(isrFlags, F_CARRY_BIT);
128       else
129         bitClear(isrFlags, F_CARRY_BIT);
130
131       if (bitRead(isrFlags, F_STATE) == 1) {
132 // Looking for Data
133         if ((Time > bit0_MIN) && (Time < bit0_MAX)) {
134 // 0 bit
135           build_Buffer[1] = build_Buffer[1] << 1;
136           build_Buffer[0] = build_Buffer[0] << 1;
137           if (bitRead(isrFlags,F_CARRY_BIT) == 1)
138             bitSet(build_Buffer[0],0);
139           bit_Count++;
140         }
141         else if ((Time > bit1_MIN) && (Time < bit1_MAX)) {
142 // 1 bit
143           build_Buffer[1] = build_Buffer[1] << 1;
144           bitSet(build_Buffer[1],0);
145           build_Buffer[0] = build_Buffer[0] << 1;
146           if (bitRead(isrFlags,F_CARRY_BIT) == 1)
147             bitSet(build_Buffer[0],0);
148           bit_Count++;
149         }
150         else {
151 // Not a 0 or 1 bit so restart data build and check if it's a sync?
152           bit_Count = 0;
153           build_Buffer[0] = 0;
154           build_Buffer[1] = 0;
155           bitClear(isrFlags, F_GOOD_DATA);                // Signal data reads dont' match
156           bitClear(isrFlags, F_STATE);                    // Set looking for Sync mode
157           if ((Time > sync_MIN) && (Time < sync_MAX)) {
158             // Sync length okay
159             bitSet(isrFlags, F_STATE);                    // Set data mode
160           }
161         }
162         if (bit_Count >= allDataBits) {
163 // All bits arrived
164           bitClear(isrFlags, F_GOOD_DATA);                // Assume data reads don't match
165           if (build_Buffer[0] == read_Buffer[0]) {
166             if (build_Buffer[1] == read_Buffer[1]) 
167               bitSet(isrFlags, F_GOOD_DATA);              // Set data reads match
168           }
169           read_Buffer[0] = build_Buffer[0];
170           read_Buffer[1] = build_Buffer[1];
171           last_Buffer[0] = build_Buffer[0];
172           last_Buffer[1] = build_Buffer[1];
173           bitSet(isrFlags, F_HAVE_DATA);                  // Set data available
174           bitClear(isrFlags, F_STATE);                    // Set looking for Sync mode
175 digitalWrite(13,HIGH); // Used for debugging
176           build_Buffer[0] = 0;
177           build_Buffer[1] = 0;
178           bit_Count = 0;
179         }
180       }
181       else {
182 // Looking for sync
183         if ((Time > sync_MIN) && (Time < sync_MAX)) {
184 // Sync length okay
185           build_Buffer[0] = 0;
186           build_Buffer[1] = 0;
187           bit_Count = 0;
188           bitSet(isrFlags, F_STATE);                      // Set data mode
189 digitalWrite(13,LOW); // Used for debugging
190         }
191       }
192       fall_Time = micros();                               // Store fall time
193     }
194   }
195   else {
196 // Rising edge
197     if (Time > (fall_Time + glitch_Length)) {
198       // Not a glitch
199       rise_Time = Time;                                   // Store rise time
200     }
201   }
202 }
203
204
205
206 void serial_outdoor_dump(void) {
207   
208     if (bitRead(isrFlags,F_GOOD_DATA) != 1) {
209        Serial.println("# no data");
210        return;
211     }
212     
213     unsigned long myData0 = 0;
214     unsigned long myData1 = 0;
215
216     // We have at least 2 consecutive matching reads
217     myData0 = last_Buffer[0]; // first 4 bits
218     myData1 = last_Buffer[1]; // rest of 32 bits
219     bitClear(isrFlags,F_HAVE_DATA); // Flag we have read the data
220
221     Serial.print("temp=");
222     int temp = ( myData1 >> 8 ) & 0xFFF;
223     if ( temp & 0x800 ) temp = temp | 0xF000;
224     Serial.print(temp / 10.0, 1);
225
226     Serial.print(" humidity=");
227     Serial.print( myData1 & 0xFF );
228
229     byte b1 = ( myData1 >> 20 ); // second byte from received packet
230
231     Serial.print(" button=");
232     Serial.print( b1 & 0x04);
233
234     Serial.print(" battery=");
235     Serial.print( b1 & 0x08);
236
237     Serial.print(" channel=");
238     Serial.print( ( b1 & 0x03 ) + 1 );
239
240     Serial.print(" rid=");
241     Serial.println( myData1 >> 24 );
242
243 }
244
245
246
247 // setup
248
249 void setup() {
250   Serial.begin(9600);
251   mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin #2  
252   mySwitch.enableTransmit(10); // with sender wired in receiving doesn't work, pin #10
253
254   // DS18B20
255   sensors.begin();
256
257   // outdoor temperature sensor
258   pinMode(13,OUTPUT); // Used for debugging
259   pinMode(ISR_PIN,INPUT);
260   attachInterrupt(ISR_INT,PinChangeISR,CHANGE);
261
262
263   Serial.print("press buttons on remote or send AB where A = socket (0..9), B = state (0 = off, 1 = on)\nB00...00 (24 digits) to send binary\n");
264 }
265
266 int serial_pos = 0;
267 char serial_data[2]; // socket (0-9), state (0-1)
268 char binary_data[24];
269
270 void loop() {
271   if (mySwitch.available()) {
272     Serial.print(mySwitch.getReceivedBitlength());
273     Serial.print(" bits ");
274     Serial.println(mySwitch.getReceivedValue(), BIN);
275     mySwitch.resetAvailable();
276   }
277   if (Serial.available() > 0) {
278      char input = Serial.read();
279      if ( input == 'T' ) {
280        Serial.print("DS18B20 temperature = ");
281        sensors.requestTemperatures();
282        Serial.println( sensors.getTempCByIndex(0) );       
283      } else
284
285      if ( input == 'B' ) {
286        Serial.readBytesUntil('\n', binary_data, sizeof(binary_data));
287        Serial.print("send B");
288        Serial.println( binary_data );
289        mySwitch.send( binary_data );
290      } else
291
292     // light sockets at 513 Mhz
293      if (input == 'a') {
294        send_513("1000100110110000000000010");
295      } else
296      if (input == 'b') {
297        send_513("1011001001011111000000010");
298      } else
299
300      if (input == 'o') {
301        serial_outdoor_dump();
302      }
303
304      if ( input >= 0x30 && input <= 0x39 ) {
305        input = input - 0x30; // ASCII to number
306        serial_data[serial_pos++] = input;
307      } else {     
308        Serial.print("ignore: ");
309        Serial.println(input, HEX);
310      }
311      
312      if ( serial_pos == 2 ) {
313        Serial.print("socket: ");
314        Serial.print(serial_data[0], DEC);
315        Serial.print(" state: ");
316        Serial.println(serial_data[1] ? "on" : "off");
317        serial_pos = 0;
318        if ( serial_data[1] ) { // on
319          switch ( serial_data[0] ) {
320          case 1:
321            mySwitch.send("110101011101010000001100");
322            break;
323          case 2:
324            mySwitch.send("110101010111010000001100");
325            break;
326          case 3:
327            mySwitch.send("110101010101110000001100");
328            break;
329          default:
330            Serial.print("invalid switch on number ");
331            Serial.println(serial_data[0], DEC);
332          }
333        } else { // off
334          switch ( serial_data[0] ) {
335          case 1:
336            mySwitch.send("110101011101010000000011");
337            break;
338          case 2:
339            mySwitch.send("110101010111010000000011");
340            break;
341          case 3:
342            mySwitch.send("110101010101110000000011");
343            break;
344          default:
345            Serial.print("invalid switch off number ");
346            Serial.println(serial_data[0], DEC);
347          }
348        }
349      }
350   }
351 }