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