Hi,
This project, I aimed to have my door bell system connected to my home automation system. This was for two reasons. 1) I wanted a way to know if anyone was at my door without me being home ex. delivery truck driver. Alternatively, I play to place some Wifi cameras outside, and it would be nice to get a snapshot of whoever opens the door. The code is based off @petewill Doorbell Automation Hack (http://forum.mysensors.org/topic/2064/how-to-doorbell-automation-hack), and has been added a second door bell/relay and gw.send commands to the controller.
This is my very first Arduino project outside of just download and go from the site so if there are any bugs please leave a detailed report and I will see what I can do. I just finished this on a breadboard, and plan to install it before tomorrow night (halloween) to see how many ghouls I get . I will take some pictures of the completed build. See wiring diagram below as well.
All was tested using MySensors Library V1.5 on Domoticz v2.3530
Version 1.0 - Initial Release
Here is the code.
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* REVISION HISTORY
* *
* Version 2.0 - ResentedPoet
*
* Based on original concept/code by @petewill for 1 Door bell chime. See original thread
* http://forum.mysensors.org/topic/2064/how-to-doorbell-automation-hack
* This sketch is used to control a front and back doorbell ring with relays as well as send an
* alert when the buttons are pressed. For front door, Connect the button to ground and digital
* pin 3. The relay controlling the doorbell is conntected to pin 4. For rear door bell
* connect second button to ground and digital pin 5. The relay controlling that pin goes
* to pin 6.
*/
#include <MySensor.h>
#include <SPI.h>
#include <Bounce2.h>
#define NODE_ID AUTO // or set to AUTO if you want gw to assign a NODE_ID for you.
#define DOORBELLF_PIN 3 // Arduino Digital I/O pin number for the front doorbell button
#define RELAYF_PIN 4 // Arduino Digital I/O pin number for the front door chime relay
#define DOORBELLF_CHILD_ID 0 //ID of the front doorbell
#define SWITCHF_CHILD_ID 1 // Id of the switch that will control front doorbell sound
#define RELAYF_ON 1
#define RELAYF_OFF 0
#define DOORBELLB_PIN 5 // Arduino Digital I/O pin number for the back doorbell button
#define RELAYB_PIN 6 // Arduino Digital I/O pin number for the back door chime relay
#define DOORBELLB_CHILD_ID 2 //ID of the back doorbell
#define SWITCHB_CHILD_ID 3 // Id of the switch that will control front doorbell sound
#define RELAYB_ON 1
#define RELAYB_OFF 0
Bounce debouncerF = Bounce();
Bounce debouncerB = Bounce();
MySensor gw;
MyMessage switchMsgF(SWITCHF_CHILD_ID, V_LIGHT);
MyMessage doorbellMsgF(DOORBELLF_CHILD_ID, V_TRIPPED);
MyMessage switchMsgB(SWITCHB_CHILD_ID, V_LIGHT);
MyMessage doorbellMsgB(DOORBELLB_CHILD_ID, V_TRIPPED);
unsigned int doorbellFDelay = 1000; // interval at which to keep the front doorbell button sensor triggered (milliseconds). This is used to stop people (kids) from pressing it too often
unsigned int ringFTime = 450; //How long the front doorbell relay is on (in milliseconds)
unsigned long doorbellFMillis; //Used to keep track of the last front doorbell button press
unsigned long doorbellFTimer; //Used to keep track of front doorbell ring time
byte doorbellFPreviousVal; //Used to keep track of front doorbell button pressed state
boolean ringDoorbellF; //Used to initiate the ring front doorbell if statement
boolean doorbellFSound; //Used to keep track if the front doorbell should sound or be silent. Value recieved from doorbell on/off switch
boolean doorbellFOff = true; //Used to keep track of front doorbell ring state
unsigned int doorbellBDelay = 1000; // interval at which to keep the back doorbell button sensor triggered (milliseconds). This is used to stop people (kids) from pressing it too often
unsigned int ringBTime = 450; //How long the back doorbell relay is on (in milliseconds)
unsigned long doorbellBMillis; //Used to keep track of the last back doorbell button press
unsigned long doorbellBTimer; //Used to keep track of back doorbell ring time
byte doorbellBPreviousVal; //Used to keep track of back doorbell button pressed state
boolean ringDoorbellB; //Used to initiate the ring back doorbell if statement
boolean doorbellBSound; //Used to keep track if the back doorbell should sound or be silent. Value recieved from doorbell on/off switch
boolean doorbellBOff = true; //Used to keep track of back doorbell ring state
void setup()
{
gw.begin(incomingMessage, NODE_ID);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("2 Door bell/chime Monitor", "1.0");
// Setup the button and activate internal pull-up
pinMode(DOORBELLF_PIN, INPUT_PULLUP);
pinMode(DOORBELLB_PIN, INPUT_PULLUP);
// After setting up the button, setup debouncer
debouncerF.attach(DOORBELLF_PIN);
debouncerB.attach(DOORBELLB_PIN);
debouncerF.interval(5);
debouncerB.interval(5);
// Register all sensors to gw (they will be created as child devices)
gw.present(SWITCHF_CHILD_ID, S_LIGHT);
gw.present(DOORBELLF_CHILD_ID, S_MOTION);
gw.present(SWITCHB_CHILD_ID, S_LIGHT);
gw.present(DOORBELLB_CHILD_ID, S_MOTION);
// Make sure relays are off when starting up
digitalWrite(RELAYF_PIN, RELAYF_OFF);
digitalWrite(RELAYB_PIN, RELAYB_OFF);
// Then set relay pins in output mode
pinMode(RELAYF_PIN, OUTPUT);
pinMode(RELAYB_PIN, OUTPUT);
// Set doorbellSound to last known state (using eeprom storage)
doorbellFSound = gw.loadState(SWITCHF_CHILD_ID);
doorbellBSound = gw.loadState(SWITCHB_CHILD_ID);
}
void loop()
{
gw.process();
unsigned long currentMillis = millis();
//Check to see if front doorbell button was pushed.
if (currentMillis - doorbellFMillis > doorbellFDelay) //used to stop front doorbell from being pressed too frequently
{
debouncerF.update();
// Read doorbell button value
byte doorbellFDetect = !debouncerF.read();//read, then reverse the value so it will send correct trigger state to controller
if (doorbellFDetect != doorbellFPreviousVal)
{
//Serial.print("doorbellFDetect Value: ");
//Serial.println(doorbellFDetect);
if (doorbellFDetect == 1)
{
ringDoorbellF = true;
doorbellFTimer = currentMillis;
gw.send(doorbellMsgF.set(doorbellFDetect?"1":"0")); // Send tripped value to gw
}
doorbellFMillis = currentMillis;
doorbellFPreviousVal = doorbellFDetect;
}
}
if (ringDoorbellF)
{
if (doorbellFSound)
{
if (doorbellFOff)
{
digitalWrite(RELAYF_PIN, RELAYF_ON);
//Serial.println("Front Doorbell sounded.");
doorbellFOff = false;
}
else
{
if (currentMillis - doorbellFTimer > ringFTime)
{
ringDoorbellF = false;
digitalWrite(RELAYF_PIN, RELAYF_OFF);
//Serial.println("Front Doorbell off.");
doorbellFOff = true;
}
}
}
}
//Check to see if back doorbell button was pushed.
if (currentMillis - doorbellBMillis > doorbellBDelay) //used to stop back doorbell from being pressed too frequently
{
debouncerB.update();
// Read doorbell button value
byte doorbellBDetect = !debouncerB.read();//read, then reverse the value so it will send correct trigger state to controller
if (doorbellBDetect != doorbellBPreviousVal)
{
//Serial.print("doorbellBDetect Value: ");
//Serial.println(doorbellBDetect);
if (doorbellBDetect == 1)
{
ringDoorbellB = true;
doorbellBTimer = currentMillis;
gw.send(doorbellMsgB.set(doorbellBDetect?"1":"0")); // Send tripped value to gw
}
doorbellBMillis = currentMillis;
doorbellBPreviousVal = doorbellBDetect;
}
}
if (ringDoorbellB)
{
if (doorbellBSound)
{
if (doorbellBOff)
{
digitalWrite(RELAYB_PIN, RELAYB_ON);
//Serial.println("Back Doorbell sounded.");
doorbellBOff = false;
}
else
{
if (currentMillis - doorbellBTimer > ringBTime)
{
ringDoorbellB = false;
digitalWrite(RELAYB_PIN, RELAYB_OFF);
//Serial.println("Back Doorbell off.");
doorbellBOff = true;
}
}
}
}
}
void incomingMessage(const MyMessage & message) {
// We only expect one type of message from controller. But we better check anyway.
if (message.isAck()) {
Serial.println("This is an ack from gateway");
}
if (message.type == V_LIGHT) {
// Change relay state
doorbellFSound = message.getBool();
// Store state in eeprom
gw.saveState(SWITCHF_CHILD_ID, doorbellFSound);
if (message.type == V_LIGHT) {
// Change relay state
doorbellBSound = message.getBool();
// Store state in eeprom
gw.saveState(SWITCHB_CHILD_ID, doorbellBSound);
// Write some debug info
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
}
}
}