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 15000
17 #define IR_TRESHOLD 10000
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 };
25 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT -4.0
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_ARDUINO_GENEREATED_HEAT);
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 unsigned int flash_led_brightness_=256;
266 unsigned int flash_led_delay_=8;
267 void calculate_led_level(unsigned int pwm_pin)
269 if (flash_led_time_ == 0)
271 if (wait_millis(flash_led_delay_))
274 int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
275 analogWrite(pwm_pin,c);
278 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor)
280 flash_led_time_ += 314*times;
281 unsigned int new_flash_led_brightness=256/brightness_divisor;
282 unsigned int new_flash_led_delay = flash_led_delay_ / delay_divisor;
283 if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
284 flash_led_brightness_=new_flash_led_brightness;
285 if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
286 flash_led_delay_=new_flash_led_delay;
289 //********************************************************************//
293 pinMode(RF_DATA_OUT_PIN, OUTPUT);
294 digitalWrite(RF_DATA_OUT_PIN, LOW);
295 pinMode(IR_MOVEMENT_PIN, INPUT); // set pin to input
296 digitalWrite(IR_MOVEMENT_PIN, LOW); // turn off pullup resistors
297 pinMode(PANIC_BUTTON_PIN, INPUT); // set pin to input
298 digitalWrite(PANIC_BUTTON_PIN, HIGH); // turn on pullup resistors
299 analogWrite(BLUELED_PWM_PIN,0);
304 onewire.reset_search();
305 dallas_sensors.begin();
306 //in case we change temp sensor:
307 if (!dallas_sensors.getAddress(onShieldTemp, 0))
308 Serial.println("Error: Unable to find address for Device 0");
309 dallas_sensors.setResolution(onShieldTemp, 9);
312 unsigned int ir_time=IR_SAMPLE_DURATION;
313 unsigned int ir_count=0;
314 boolean pb_last_state=0;
316 boolean pb_postth_state=0;
317 unsigned int pb_time=0;
319 void sensorEchoCommand(char command)
321 Serial.print("Sensor ");
322 Serial.print(command);
329 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
331 if (pb_time < PB_TRESHOLD)
333 pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
337 if (ir_count >= IR_TRESHOLD)
340 Serial.println("movement");
342 ir_time=IR_SAMPLE_DURATION;
346 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
348 if (pb_state && ! pb_postth_state)
351 Serial.println("PanicButton");
357 else if (pb_state != pb_last_state)
360 pb_last_state=pb_state;
363 updateLightLevel(PHOTO_ANALOGPIN);
364 calculate_led_level(BLUELED_PWM_PIN);
366 if(Serial.available()) {
367 char command = Serial.read();
370 send_frame(words[A1_ON]);
371 else if(command == 'a')
372 send_frame(words[A1_OFF]);
373 else if(command == 'B')
374 send_frame(words[A2_ON]);
375 else if(command == 'b')
376 send_frame(words[A2_OFF]);
378 else if(command == 'C')
379 send_frame(words[B1_ON]);
380 else if(command == 'c')
381 send_frame(words[B1_OFF]);
382 else if(command == 'D')
383 send_frame(words[B2_ON]);
384 else if(command == 'd')
385 send_frame(words[B2_OFF]);
387 else if(command == 'E')
388 send_frame(words[C1_ON]);
389 else if(command == 'e')
390 send_frame(words[C1_OFF]);
391 else if(command == 'F')
392 send_frame(words[C2_ON]);
393 else if(command == 'f')
394 send_frame(words[C2_OFF]);
396 else if(command == 'G')
397 send_frame(words[D1_ON]);
398 else if(command == 'g')
399 send_frame(words[D1_OFF]);
400 else if(command == 'H')
401 send_frame(words[D2_ON]);
402 else if(command == 'h')
403 send_frame(words[D2_OFF]);
404 else if(command == 'T')
406 sensorEchoCommand(command);
407 printTemperature(onShieldTemp);
409 else if(command == 'P')
411 sensorEchoCommand(command);
415 Serial.println("Error: unknown command");