2 #include <avr/interrupt.h>
5 #include <DallasTemperature.h>
7 //********************************************************************//
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
22 OneWire onewire(ONE_WIRE_PIN);
23 DallasTemperature dallas_sensors(&onewire);
24 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
32 // offset is number of alphas (0.08ms)
34 const rf_bit_t zero_bit[] = { { 4, 1 },
40 const rf_bit_t one_bit[] = { { 12, 1 },
46 const rf_bit_t float_bit[] = { { 4, 1 },
52 const rf_bit_t sync_bit[] = { { 4, 1 },
56 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
57 typedef byte ad_bit_t;
59 typedef ad_bit_t word_t[WORD_LEN];
61 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
67 const ad_bit_t* current_word;
68 byte volatile frame_finished = 1;
92 const word_t words[] = {
93 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
94 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A1_OFF
95 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
96 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A2_OFF
98 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
99 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B1_OFF
100 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
101 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B2_OFF
103 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
104 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C1_OFF
105 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
106 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C2_OFF
108 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
109 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // D1_OFF
110 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
111 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC } // D2_OFF
115 //********************************************************************//
120 TCCR1A = 0; // prescaler 1:8, WGM = 4 (CTC)
121 TCCR1B = 1<<WGM12 | 1<<CS11; //
122 OCR1A = 159; // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
123 // OCR1A = 207; // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
124 TCNT1 = 0; // reseting timer
125 TIMSK1 = 1<<OCIE1A; // enable Interrupt
128 void stop_timer() // stop the timer
131 TCCR1B = 0; // no clock source
132 TIMSK1 = 0; // disable timer interrupt
135 void init_word(const word_t w)
142 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
143 digitalWrite(RF_DATA_OUT_PIN, HIGH);
145 digitalWrite(RF_DATA_OUT_PIN, LOW);
150 ISR(TIMER1_COMPA_vect)
153 if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
157 if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
158 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
159 digitalWrite(RF_DATA_OUT_PIN, HIGH);
161 digitalWrite(RF_DATA_OUT_PIN, LOW);
166 if(bit_cnt < WORD_LEN) {
169 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
170 digitalWrite(RF_DATA_OUT_PIN, HIGH);
172 digitalWrite(RF_DATA_OUT_PIN, LOW);
176 digitalWrite(RF_DATA_OUT_PIN, LOW);
179 if(word_cnt < FRAME_LEN)
180 init_word(current_word);
188 void send_frame(const word_t w)
198 Serial.println("Ok");
201 //********************************************************************//
203 void printTemperature(DeviceAddress deviceAddress)
205 dallas_sensors.requestTemperatures();
206 float tempC = dallas_sensors.getTempC(deviceAddress);
207 Serial.print("Temp C: ");
208 Serial.println(tempC TEMPC_OFFSET);
209 //Serial.print(" Temp F: ");
210 //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
213 //********************************************************************//
215 unsigned int light_level_mean_ = 0;
216 unsigned int light_sample_time_ = 0;
218 void updateLightLevel(unsigned int pin)
220 light_sample_time_++;
221 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
223 light_sample_time_ = 0;
225 unsigned int value = analogRead(pin);
226 if (value == light_level_mean_)
229 unsigned int diff = abs(value - light_level_mean_);
230 if (light_level_mean_ < 6 || diff > 250)
231 light_level_mean_ = value;
233 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.98 + ((float)value)*0.02 );
236 void printLightLevel()
238 Serial.print("Photo: ");
239 Serial.println(light_level_mean_);
242 //********************************************************************//
244 unsigned long wm_start_=0;
245 bool wait_millis(unsigned long ms)
249 if (millis() < wm_start_ || millis() > wm_start_+ ms)
264 unsigned int flash_led_time_=0;
265 void calculate_led_level(unsigned int pwm_pin)
267 if (flash_led_time_ == 0)
272 int c = abs(sin(float(flash_led_time_) / 100.0)) * 256;
273 analogWrite(pwm_pin,c);
276 void flash_led(int times)
278 flash_led_time_ += 314*times;
281 //********************************************************************//
285 pinMode(RF_DATA_OUT_PIN, OUTPUT);
286 digitalWrite(RF_DATA_OUT_PIN, LOW);
287 pinMode(IR_MOVEMENT_PIN, INPUT); // set pin to input
288 digitalWrite(IR_MOVEMENT_PIN, LOW); // turn off pullup resistors
289 pinMode(PANIC_BUTTON_PIN, INPUT); // set pin to input
290 digitalWrite(PANIC_BUTTON_PIN, HIGH); // turn on pullup resistors
291 analogWrite(BLUELED_PWM_PIN,0);
294 onewire.reset_search();
295 dallas_sensors.begin();
296 //in case we change temp sensor:
297 if (!dallas_sensors.getAddress(onShieldTemp, 0))
298 Serial.println("Error: Unable to find address for Device 0");
299 dallas_sensors.setResolution(onShieldTemp, 9);
304 unsigned int ir_time=IR_SAMPLE_DURATION;
305 unsigned int ir_count=0;
306 boolean pb_last_state=0;
308 boolean pb_postth_state=0;
309 unsigned int pb_time=0;
314 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
316 if (pb_time < PB_TRESHOLD)
318 pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
322 if (ir_count >= IR_TRESHOLD)
325 Serial.println("movement");
327 ir_time=IR_SAMPLE_DURATION;
331 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
333 if (pb_state && ! pb_postth_state)
336 Serial.println("PanicButton");
342 else if (pb_state != pb_last_state)
345 pb_last_state=pb_state;
348 updateLightLevel(PHOTO_ANALOGPIN);
349 calculate_led_level(BLUELED_PWM_PIN);
351 if(Serial.available()) {
352 char command = Serial.read();
355 send_frame(words[A1_ON]);
356 else if(command == 'a')
357 send_frame(words[A1_OFF]);
358 else if(command == 'B')
359 send_frame(words[A2_ON]);
360 else if(command == 'b')
361 send_frame(words[A2_OFF]);
363 else if(command == 'C')
364 send_frame(words[B1_ON]);
365 else if(command == 'c')
366 send_frame(words[B1_OFF]);
367 else if(command == 'D')
368 send_frame(words[B2_ON]);
369 else if(command == 'd')
370 send_frame(words[B2_OFF]);
372 else if(command == 'E')
373 send_frame(words[C1_ON]);
374 else if(command == 'e')
375 send_frame(words[C1_OFF]);
376 else if(command == 'F')
377 send_frame(words[C2_ON]);
378 else if(command == 'f')
379 send_frame(words[C2_OFF]);
381 else if(command == 'G')
382 send_frame(words[D1_ON]);
383 else if(command == 'g')
384 send_frame(words[D1_OFF]);
385 else if(command == 'H')
386 send_frame(words[D2_ON]);
387 else if(command == 'h')
388 send_frame(words[D2_OFF]);
389 else if(command == 'T')
390 printTemperature(onShieldTemp);
391 else if(command == 'P')
395 Serial.println("Error: unknown command");