Led und PhotoDiodeo
[svn42.git] / rf433ctl / rf433ctl.pde
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <inttypes.h>
4 #include <OneWire.h>
5 #include <DallasTemperature.h>
6
7 //********************************************************************//
8
9 #define RF_DATA_OUT_PIN 13
10 #define IR_MOVEMENT_PIN 9
11 #define ONE_WIRE_PIN 8
12 #define PANIC_BUTTON_PIN 7
13 #define BLUELED_PWM_PIN 6
14 #define PHOTO_ANALOGPIN 0
15 //movement is reported if during IR_SAMPLE_DURATION at least IR_TRESHOLD ir signals are detectd
16 #define IR_SAMPLE_DURATION 20000
17 #define IR_TRESHOLD 13000
18 //duration PanicButton needs to be pressed before status change occurs (i.e. for two PanicButton Reports, the buttons needs to be pressed 1000 cycles, releases 1000 cycles and again pressed 1000 cycles)
19 #define PB_TRESHOLD 1000
20 #define PHOTO_SAMPLE_INTERVAL 4000
21
22 OneWire  onewire(ONE_WIRE_PIN);
23 DallasTemperature dallas_sensors(&onewire);
24 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
25
26 typedef struct {
27   byte offset;
28   byte state;
29 } rf_bit_t;
30
31 // offset is number of alphas (0.08ms)
32
33 const rf_bit_t zero_bit[] = { {  4, 1 },
34                               { 16, 0 },
35                               { 20, 1 },
36                               { 32, 0 },
37                               {  0, 0 } };
38
39 const rf_bit_t one_bit[] = { { 12, 1 },
40                              { 16, 0 },
41                              { 28, 1 },
42                              { 32, 0 },
43                              {  0, 0 } };
44
45 const rf_bit_t float_bit[] = { {  4, 1 },
46                                { 16, 0 },
47                                { 28, 1 },
48                                { 32, 0 },
49                                {  0, 0 } };
50
51 const rf_bit_t sync_bit[] = { {   4, 1 },
52                               { 128, 0 },
53                               {   0, 0 } };
54
55 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
56 typedef byte ad_bit_t;
57 #define WORD_LEN 13
58 typedef ad_bit_t word_t[WORD_LEN];
59
60 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
61
62 byte alpha_cnt = 0;
63 byte bit_cnt = 0;
64 byte chunk_cnt = 0;
65 byte word_cnt = 0;
66 const ad_bit_t* current_word;
67 byte volatile frame_finished = 1;
68
69 #define FRAME_LEN 8
70
71 #define A1_ON  0
72 #define A1_OFF 1
73 #define A2_ON  2
74 #define A2_OFF 3
75
76 #define B1_ON  4
77 #define B1_OFF 5
78 #define B2_ON  6
79 #define B2_OFF 7
80
81 #define C1_ON  8
82 #define C1_OFF 9
83 #define C2_ON  10
84 #define C2_OFF 11
85
86 #define D1_ON  12
87 #define D1_OFF 13
88 #define D2_ON  14
89 #define D2_OFF 15
90
91 const word_t words[]  = { 
92 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
93 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
94 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
95 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
96
97 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
98 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
99 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
100 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
101
102 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
103 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
104 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
105 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
106
107 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
108 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
109 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
110 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
111 };
112
113
114 //********************************************************************//
115
116 void start_timer()
117 {
118   // timer 1: 2 ms
119   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
120   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
121   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
122 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
123   TCNT1 = 0;          // reseting timer
124   TIMSK1 = 1<<OCIE1A; // enable Interrupt
125 }
126
127 void stop_timer() // stop the timer
128 {
129   // timer1
130   TCCR1B = 0; // no clock source
131   TIMSK1 = 0; // disable timer interrupt
132 }
133
134 void init_word(const word_t w)
135 {
136   current_word = w;
137   alpha_cnt = 0;
138   chunk_cnt = 0;
139   bit_cnt = 0;
140
141   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
142     digitalWrite(RF_DATA_OUT_PIN, HIGH);
143   else
144     digitalWrite(RF_DATA_OUT_PIN, LOW);
145
146   start_timer();
147 }
148
149 ISR(TIMER1_COMPA_vect)
150 {
151   alpha_cnt++;
152   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
153     return;
154
155   chunk_cnt++;
156   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
157     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
158       digitalWrite(RF_DATA_OUT_PIN, HIGH);
159     else
160       digitalWrite(RF_DATA_OUT_PIN, LOW);
161     return;
162   }
163   
164   bit_cnt++;
165   if(bit_cnt < WORD_LEN) {
166     alpha_cnt = 0;
167     chunk_cnt = 0;
168     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
169       digitalWrite(RF_DATA_OUT_PIN, HIGH);
170     else
171       digitalWrite(RF_DATA_OUT_PIN, LOW);
172     return;
173   }
174   stop_timer();
175   digitalWrite(RF_DATA_OUT_PIN, LOW);
176
177   word_cnt++;
178   if(word_cnt < FRAME_LEN)
179     init_word(current_word);
180
181   frame_finished = 1;
182 }
183
184 //***********//
185
186
187 void send_frame(const word_t w)
188 {
189   word_cnt = 0;
190   frame_finished = 0;
191   init_word(w);
192
193   for(;;)
194     if(frame_finished)
195       break;
196
197   Serial.println("Ok");
198 }
199
200 //********************************************************************//
201
202 void printTemperature(DeviceAddress deviceAddress)
203 {
204   dallas_sensors.requestTemperatures();
205   float tempC = dallas_sensors.getTempC(deviceAddress);
206   Serial.print("Temp C: ");
207   Serial.println(tempC);
208   //Serial.print(" Temp F: ");
209   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
210 }
211
212 //********************************************************************//
213
214 unsigned int light_level_mean_ = 0;
215 unsigned int light_sample_time_ = 0;
216
217 void updateLightLevel(unsigned int pin)
218 {
219   light_sample_time_++;
220   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
221     return;
222   light_sample_time_ = 0;
223   
224   unsigned int value = analogRead(pin);
225   if (value == light_level_mean_)
226     return;
227   
228   unsigned int diff = abs(value - light_level_mean_);
229   if (diff > 250)
230     light_level_mean_ = value;
231   else
232       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.98 + ((float)value)*0.02 );
233 }
234
235 void printLightLevel()
236 {
237   Serial.print("Photo: ");
238   Serial.println(light_level_mean_);
239 }
240
241 //********************************************************************//
242
243 unsigned int flash_led_time_=0;
244 void calculate_led_level(unsigned int pwm_pin)
245 {
246   if (flash_led_time_ == 0)
247     return;
248   if (millis() % 10)
249     return;
250   flash_led_time_--;
251   int c = abs(sin(float(flash_led_time_) / 100.0)) * 256;
252   analogWrite(pwm_pin,c);
253 }
254
255 void flash_led(int times)
256 {
257   flash_led_time_=314*times;
258 }
259
260 //********************************************************************//
261
262 void setup()
263 {
264   pinMode(RF_DATA_OUT_PIN, OUTPUT);
265   digitalWrite(RF_DATA_OUT_PIN, LOW);
266   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
267   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
268   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
269   digitalWrite(PANIC_BUTTON_PIN, HIGH);  // turn on pullup resistors 
270   analogWrite(BLUELED_PWM_PIN,0);
271   
272   onewire.reset();
273   onewire.reset_search();
274   dallas_sensors.begin();
275   //in case we change temp sensor:
276   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
277     Serial.println("Error: Unable to find address for Device 0"); 
278   dallas_sensors.setResolution(onShieldTemp, 9);
279   
280   Serial.begin(9600);
281 }
282
283 unsigned int ir_time=IR_SAMPLE_DURATION;
284 unsigned int ir_count=0;
285 boolean pb_last_state=0;
286 boolean pb_state=0;
287 boolean pb_postth_state=0;
288 unsigned int pb_time=0;
289
290 void loop()
291 {
292   ir_time--;
293   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
294
295   if (pb_time < PB_TRESHOLD)
296     pb_time++;
297   pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
298   
299   if (ir_time == 0)
300   {
301     if (ir_count >= IR_TRESHOLD)
302     {
303       flash_led(1);
304       Serial.println("movement");
305     }
306     ir_time=IR_SAMPLE_DURATION;
307     ir_count=0;
308   }
309   
310   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
311   {
312     if (pb_state && ! pb_postth_state)
313     {   
314       pb_postth_state=1;
315       Serial.println("PanicButton");
316       flash_led(7);
317     }
318     else if (!pb_state)
319       pb_postth_state=0;
320   }
321   else if (pb_state != pb_last_state)
322   {
323     pb_time=0;
324     pb_last_state=pb_state;
325   }
326   
327   updateLightLevel(PHOTO_ANALOGPIN);
328   calculate_led_level(BLUELED_PWM_PIN);
329   
330   if(Serial.available()) {
331     char command = Serial.read();
332     
333     if(command == 'A')
334       send_frame(words[A1_ON]);
335     else if(command == 'a')
336       send_frame(words[A1_OFF]);
337     else if(command == 'B')
338       send_frame(words[A2_ON]);
339     else if(command == 'b')
340       send_frame(words[A2_OFF]);
341
342     else if(command == 'C')
343       send_frame(words[B1_ON]);
344     else if(command == 'c')
345       send_frame(words[B1_OFF]);
346     else if(command == 'D')
347       send_frame(words[B2_ON]);
348     else if(command == 'd')
349       send_frame(words[B2_OFF]);
350
351     else if(command == 'E')
352       send_frame(words[C1_ON]);
353     else if(command == 'e')
354       send_frame(words[C1_OFF]);
355     else if(command == 'F')
356       send_frame(words[C2_ON]);
357     else if(command == 'f')
358       send_frame(words[C2_OFF]);
359
360     else if(command == 'G')
361       send_frame(words[D1_ON]);
362     else if(command == 'g')
363       send_frame(words[D1_OFF]);
364     else if(command == 'H')
365       send_frame(words[D2_ON]);
366     else if(command == 'h')
367       send_frame(words[D2_OFF]);
368     else if(command == 'T')
369       printTemperature(onShieldTemp);
370     else if(command == 'P')
371       printLightLevel();
372
373     else
374       Serial.println("Error: unknown command");
375   }
376 }