Created
August 19, 2014 23:44
-
-
Save lbt/2b5e9a25e9585c7b9d8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "application.h" | |
// Define the pins we're going to call pinMode on | |
int PIR_PIN = D0; | |
int BUTTON_PIN = D1; | |
int DOOR_PIN = D2; | |
int LOCK_PIN = D3; // Note that on zuul this pin seems not to do INPUT_PULLDOWN | |
int DOORBELL_PIN = D4; | |
int LED_PIN = D7; // This one is the built-in tiny one to the right of the USB jack | |
///////////////////////////////////////////////////////// PIR | |
volatile int pir_activated = 0; | |
int pir_poweron_time; | |
int pir_settle_time = 5; | |
int do_lock(String arg); | |
int get_door_opening(); | |
#define DOOR_CLOSED 0 | |
#define DOOR_OPEN 1 | |
// PIR interrupt handler | |
void pir_notice_i(){ | |
if (Time.now() - pir_poweron_time < pir_settle_time) | |
return; // PIR takes time for sensor to settle | |
int state = digitalRead(PIR_PIN); | |
digitalWrite(LED_PIN, state); | |
if (state == HIGH) | |
pir_activated = 1; | |
} | |
void loop_pir_handle(){ | |
if (pir_activated == 1) { | |
Spark.publish("porch-pir", NULL, 60, PRIVATE); | |
pir_activated = 0 ; | |
} | |
} | |
void setup_pir() { | |
pinMode(PIR_PIN, INPUT_PULLDOWN); | |
pinMode(LED_PIN, OUTPUT); | |
pir_poweron_time = Time.now(); | |
attachInterrupt(PIR_PIN, pir_notice_i, CHANGE); | |
} | |
///////////////////////////////////////////////////////// Open button | |
volatile bool button_being_touched = false; | |
volatile bool button_was_touched = false; | |
volatile bool button_was_long_touched = false; | |
unsigned long button_first_touch_time = 0; | |
int button_pulse_count = 0; | |
// Button interrupt handler | |
// http://www.arvydas.co.uk/2012/08/arduino-touch-sensor-ky036/ | |
// This touch sensor pulses @50hz 1 per 20ms | |
// Callback on 'touch' | |
// Callback on 'long-touch' | |
// State: touched / not touched | |
void button_notice_i(){ | |
unsigned long now = millis(); | |
if ((button_pulse_count > 0) and | |
(now - button_first_touch_time > 40)) { // Pulse stream stopped for too long | |
button_pulse_count = 0; | |
button_being_touched = false; | |
return; | |
} | |
button_first_touch_time = now; | |
button_pulse_count++; | |
if (button_pulse_count == 25) { | |
button_was_touched = true; | |
button_being_touched = true; | |
} | |
if (button_pulse_count == 200) { | |
button_was_long_touched = true; | |
} | |
} | |
void loop_button_handle(){ | |
// Serial.print("Button count "); | |
// Serial.print(button_pulse_count); | |
// Serial.print(" time "); | |
// Serial.println(button_first_touch_time); | |
if (button_was_long_touched) { | |
// Serial.println("Button long touch"); | |
button_was_long_touched = false ; // discard the activation | |
} | |
if (button_was_touched) { | |
// Serial.println("Button touch"); | |
Spark.publish("front-door-button",NULL, 60, PRIVATE); | |
if (get_door_opening() == DOOR_CLOSED) | |
do_lock("unlock"); // This logic will move to the server to allow managing | |
button_was_touched = false ; // discard the activation | |
} | |
} | |
void setup_button() { | |
pinMode(BUTTON_PIN, INPUT_PULLDOWN); | |
attachInterrupt(BUTTON_PIN, button_notice_i, RISING); | |
} | |
///////////////////////////////////////////////////////// Door reed | |
bool door_changed = false; | |
int door_opening = DOOR_CLOSED; | |
int get_door_opening() { | |
return (digitalRead(DOOR_PIN) == LOW) ? DOOR_OPEN : DOOR_CLOSED; | |
} | |
// Door interrupt handler - notice that the door reed is N/C so a LOW means the door opened. | |
void door_notice_i(){ | |
door_changed = true; | |
} | |
void loop_door_handle(){ | |
door_opening = get_door_opening(); | |
if (door_changed) { | |
Spark.publish("front-door", | |
(door_opening == DOOR_OPEN) ? "open":"closed", | |
60, PRIVATE); | |
door_changed = false ; | |
if (door_opening == DOOR_OPEN) | |
do_lock("lock"); // This logic is local. The lock should stop buzzing open when the door opens. | |
} | |
} | |
void setup_door() { | |
pinMode(DOOR_PIN, INPUT_PULLDOWN); | |
attachInterrupt(DOOR_PIN, door_notice_i, CHANGE); | |
Spark.variable("door_open", &door_opening, INT); | |
} | |
///////////////////////////////////////////////////////// Lock | |
int lock_open_at; | |
enum lock_state_t {LOCKED, UNLOCKED}; | |
lock_state_t lock_state; | |
int LOCK_DURATION = 3; | |
int do_lock(String arg) { | |
if (arg.equals("unlock")) { | |
lock_open_at = Time.now(); | |
return 0; | |
} | |
if (arg.equals("lock")) { | |
lock_open_at = 0; | |
return 0; | |
} | |
} | |
void loop_lock_handle() { | |
if ((Time.now() - lock_open_at) > LOCK_DURATION) { | |
if (lock_state == UNLOCKED) { | |
digitalWrite(LOCK_PIN, 0); | |
lock_state = LOCKED; | |
Spark.publish("front-door-lock","locked", 60, PRIVATE); | |
} | |
} else { | |
if (lock_state == LOCKED) { | |
digitalWrite(LOCK_PIN, 1); | |
lock_state = UNLOCKED; | |
Spark.publish("front-door-lock","unlocked", 60, PRIVATE); | |
} | |
} | |
} | |
void setup_lock(){ | |
lock_open_at = 0; | |
pinMode(LOCK_PIN, OUTPUT); | |
digitalWrite(LOCK_PIN, 0); | |
lock_state = LOCKED; // Lock the door by default | |
Spark.function("do_lock", do_lock); | |
Spark.variable("lock", &lock_state, INT); | |
} | |
// This routine runs only once upon reset | |
void setup() { | |
// Serial.begin(115200); | |
setup_pir(); | |
setup_button(); | |
setup_door(); | |
setup_lock(); | |
Spark.publish("zuul","online", 60, PRIVATE); | |
} | |
// This routine gets called repeatedly, like once every 5-15 milliseconds. | |
// Spark firmware interleaves background CPU activity associated with WiFi + Cloud activity with your code. | |
// Make sure none of your code delays or blocks for too long (like more than 5 seconds), or weird things can happen. | |
void loop() { | |
loop_pir_handle(); | |
loop_button_handle(); | |
loop_door_handle(); | |
loop_lock_handle(); | |
delay(200); // Wait for 0.2 second in off mode | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment