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 };
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 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;
311 void echoCommand(char command)
313 Serial.print(command);
320 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
322 if (pb_time < PB_TRESHOLD)
324 pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
328 if (ir_count >= IR_TRESHOLD)
331 Serial.println("movement");
333 ir_time=IR_SAMPLE_DURATION;
337 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
339 if (pb_state && ! pb_postth_state)
342 Serial.println("PanicButton");
348 else if (pb_state != pb_last_state)
351 pb_last_state=pb_state;
354 updateLightLevel(PHOTO_ANALOGPIN);
355 calculate_led_level(BLUELED_PWM_PIN);
357 if(Serial.available()) {
358 char command = Serial.read();
361 send_frame(words[A1_ON]);
362 else if(command == 'a')
363 send_frame(words[A1_OFF]);
364 else if(command == 'B')
365 send_frame(words[A2_ON]);
366 else if(command == 'b')
367 send_frame(words[A2_OFF]);
369 else if(command == 'C')
370 send_frame(words[B1_ON]);
371 else if(command == 'c')
372 send_frame(words[B1_OFF]);
373 else if(command == 'D')
374 send_frame(words[B2_ON]);
375 else if(command == 'd')
376 send_frame(words[B2_OFF]);
378 else if(command == 'E')
379 send_frame(words[C1_ON]);
380 else if(command == 'e')
381 send_frame(words[C1_OFF]);
382 else if(command == 'F')
383 send_frame(words[C2_ON]);
384 else if(command == 'f')
385 send_frame(words[C2_OFF]);
387 else if(command == 'G')
388 send_frame(words[D1_ON]);
389 else if(command == 'g')
390 send_frame(words[D1_OFF]);
391 else if(command == 'H')
392 send_frame(words[D2_ON]);
393 else if(command == 'h')
394 send_frame(words[D2_OFF]);
395 else if(command == 'T')
397 echoCommand(command);
398 printTemperature(onShieldTemp);
400 else if(command == 'P')
402 echoCommand(command);
406 Serial.println("Error: unknown command");