Skip to content

Instantly share code, notes, and snippets.

@lbt
Created August 19, 2014 23:44
Show Gist options
  • Save lbt/2b5e9a25e9585c7b9d8b to your computer and use it in GitHub Desktop.
Save lbt/2b5e9a25e9585c7b9d8b to your computer and use it in GitHub Desktop.
#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