My Pre-wired House Project using Arduino, Reed Sensors, and the ThingShield

arduino
thingshield
project_security

(Chris Etheridge) #1

So I would have to say that this is the largest automation/electronic project I have done so far, and I came out of it thinking that it wasn’t so bad. Wasn’t necessarily cheap, wasn’t necessarily hard, and a lot of things were in place already for me that made the project easier, but I am happy with the outcome and the price I paid.

My Problem.
I wanted a security system that I didn’t have to pay monthly for, but I also didn’t want to use a wireless solution. A) Because wireless is way more expensive than wired. B) Wireless can be defeated/interfered with using simple electronics. C) My house was already wired, so why not use what I already had and D) it was a fun learning experience. I have 9 windows and 3 doors that I wanted to monitor the status of and eventually use the “Smart Home Monitor” on the dashboard of the ST app.

My Background.
I am kind of an all around Geek. I love devices, computers, and just about anything that goes beep. I work in IT, mostly with networking, and am an amateur programmer. My first languages were C and BASIC (dating myself a bit here), but I have done more extensive work with Visual Basic, Visual C#, Powershell, ObjectPAL, Labview, Python, and a tiny bit of java script. I am by no means an expert programmer. However, I do know concepts and even though groovy is completely new to me, I do see where they have borrowed some ideas and concepts from other languages. Also, I did go to college for electronic engineering, however, I never really used the knowledge in 15 years outside of a couple small projects and have since lost most all of it. I mention all of this not to pop my collar or anything, but someone going into a project like this may need some of these fundamentals and concepts before getting started.

Assumptions, errata, and all the dumb things I did.
So, let me start off saying that what I ended up with may not be the cheapest solution, the best solution, or even the right solution. I may burn my house down with what I have done. However, if you see something I did wrong or stupid, definitely tell me. However, let’s all be nice and civil like as we are all here to help each other. That is why I am writing all of this up. If someone comes along and needs help like I did, maybe there is something I did that could help someone else. Having said that, I am not liable if you decide to do the same dumb things I did. This will serve as your only warning. :smile:

Parts. Parts. Parts
I did cite cost as one of the main reasons I did this and essentially it was. However, that doesn’t mean I am above spending money. I also cited that I didn’t want to use wireless, but in a way, I still ended up with a wireless solution. So, yeah, there is a bit of a contradiction, but it is what it is.

The parts I used are:
Arduino with the ThingShield
Reed sensors from Amazon
Three terminal blocks
Some pre-made jumper wires and solid strand hookup wire
One large electrical junction box
One small electrical in-wall cut in box (is that the right name?)
Various screws, grommets, nuts, bolts, and stuff

First things first.
I discovered that all of the windows were wired to a temporary plug that I thought were sensors. Ha! So after posting in another thread asking if anyone knew what the hell they were, and after finally ripping them out, I found out that they were just plugs to hold the wires that were already run in my house. So after about 80 dollars in sensors from Amazon, I was good to go. Here are some pictures of the steps. I think they are pretty straight forward so I won’t explain all of the steps, except for the first picture. The first picture is the plug I was referring to that were holding the wires.





Hopefully you get the idea.

Problem Number 1!
I guess in an effort to save money, wiring, whatever, some of the windows were wired together. In other words, one window would have a wire going to another window, before going back to where the panel should be. So I decided to wire them together in series. Since the sensors are normally closed with magnet, one opening would still trigger the circuit open. So basically on one window, you will have one pair of wires, in the next window, you will have two pair. All you have to do is expose the wire on the window with one pair. On the window with two, expose the wire and then short one of the pairs.

Using a multi-meter, set it to the ‘beep’ on continuity setting and see if you have continuity on the window with only one pair. If not, short the other pair and see. Once you have identified the pair that goes to the single pair window, you can take the negative lead of the pair going back to the panel and the positive lead of the pair going to the other window and short those together. Giving you something that looks like this:

Next, I just used a crimp connector to splice the two wires together which leaves you with a single positive and negative pair, like this:

Finally, I used some shrink tubing and wired the sensor up:

For the doors I just used some Honeywell Form A SPST Reeds. Hardest part was drilling the hole.

Mock it Up!
So after I learned how to use the Arduino and ThingShield:

I decided how I wanted to mount all of this in the box. The box is just a large junction box that seemed to fit what I wanted to do. It was pretty much all I could find that would work at Home Depot and Lowe’s, but I am happy with the outcome. I then mounted the Arduino to an in-wall cut-in box just to give it a little elevation so it would make wiring a little easier. It’s a little large but I have large hands and didn’t want too much difficulty wiring.


After it was all mocked up and how I wanted it, I got to wiring:

So basically what you have here is that all of the reed sensors are switches and since they are normally closed with magnet switches, you have to have something going down the wire at all times to detect whether the circuit is complete or not. If it’s not, we let the hub know about it. So forgive me for not giving a wiring diagram as I am lazy and think I can explain it just as well. Since all of the sensors are the same, and all need 5v, I took the terminal block you see on the left of the picture, and shorted all of the connections together with some hookup wire. I then connected the 5v pin on the Arduino on the bottom left connector, and then wired the positive side of the sensor to each individual screw. The negative side of the sensor is connected to the block on the right. The other side of that block is connected to the pin I am monitoring on the Arduino AND ground with a 220k resistor soldered inline. So the block at the top is similar to the 5v side. All of the connectors are shorted with the top left connection going to the GND connector on the Arduino.

The flow is kinda like this: Arduino 5v --> Positive Red Wire --> Sensor --> Negative Black Wire --> Arduino PIN AND 220k resistor --> from resistor only --> Arduino GND. If this is too confusing I may draw something up later. (This is long!)
Could I have done end of line resistors and also detected tampering? Yeah, but then I would only have 4 analog PINs and I am only using an UNO. So that might be another addition to the project down the road.

And after everything was working, mounted I it:

The Code!
Oh the humanity. :smile:

I say that because the documentation is VERY sparse. Shame on Samsung for releasing this with very limited documentation. However, some thanks and credits are due. I can’t thank everyone because I can’t remember the hundred or so pages and posts I read and youtube videos I watched to cobble this all together. However, the main thanks goes to stevesell, Dan “ogiewon”, and lailoken on the message board here. Without you guys, I would have had A LOT lot harder time.

On the Ardiuno side I used mostly what lailoken came up with on the ‘Arduino SmartShield Garage Controller’ post of this board. I modified it for my connections and also added a polling feature. I added it because every time I install my SmartApp it doesn’t seem to update the state on the first go. So I have the SmartApp send a poll() and the Arduino responds with the current state of the pins.

/**
 *  Arduino Contact Sensor Monitor 
 *
 */

//*****************************************************************************
#include <SoftwareSerial.h>
#include <SmartThings.h>

//*****************************************************************************
// Pin Definitions
//*****************************************************************************
#define PIN_THING_RX                3
#define PIN_THING_TX                2
#define PIN_RESERVED                6     

#define PIN_OFFICE_CONTACT          4     // input
#define PIN_DININGROOM_CONTACT      5     // input
#define PIN_BEDROOM_CONTACT         7     // input
#define PIN_LIVINGROOM_CONTACT      8     // input
#define PIN_KITCHEN_CONTACT         9     // input
#define PIN_FRONTDOOR_CONTACT       10    // input
#define PIN_BACKDOOR_CONTACT        11    // input
#define PIN_GARAGEDOOR_CONTACT      12    // input

#define OPEN                  1     // HIGH
#define CLOSED                0     // LOW
#define UNKNOWN               2     // --- reset / force update

//*****************************************************************************
// Global Variables
//*****************************************************************************
SmartThingsCallout_t messageCallout;    // call out function forward decalaration
SmartThings smartthing(PIN_THING_RX, PIN_THING_TX, messageCallout);  // constructor

int officeStatus  = UNKNOWN;
int diningRoomStatus = UNKNOWN;
int bedroomStatus = UNKNOWN;
int livingRoomStatus = UNKNOWN;
int kitchenStatus = UNKNOWN;
int frontDoorStatus = UNKNOWN;
int backDoorStatus = UNKNOWN;
int garageDoorStatus = UNKNOWN;

bool isDebugEnabled=true;    // enable or disable debug in this example
int stateLED;           // state to track last set value of LED
int stateNetwork;       // state of the network

//*****************************************************************************
// Logic
//*****************************************************************************

int contactState(int pin)
{
  // LOW  -> closed
  // HIGH -> open
  return (digitalRead(pin) == HIGH)?CLOSED:OPEN;
}

void updateContactStatus()
{
  int currentStatus;
  char* msg = NULL;

  currentStatus = contactState(PIN_OFFICE_CONTACT);
  if (officeStatus != currentStatus)
  {
    officeStatus = currentStatus;
    if(officeStatus == CLOSED) msg = "office closed";
    else                     msg = "office open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }

  currentStatus = contactState(PIN_DININGROOM_CONTACT);
  if (diningRoomStatus != currentStatus)
  {
    diningRoomStatus = currentStatus;
    if(diningRoomStatus == CLOSED) msg = "diningroom closed";
    else                     msg = "diningroom open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  
  currentStatus = contactState(PIN_BEDROOM_CONTACT);
  if (bedroomStatus != currentStatus)
  {
    bedroomStatus = currentStatus;
    if(bedroomStatus == CLOSED) msg = "bedroom closed";
    else                     msg = "bedroom open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
    
  currentStatus = contactState(PIN_LIVINGROOM_CONTACT);
  if (livingRoomStatus != currentStatus)
  {
    livingRoomStatus = currentStatus;
    if(livingRoomStatus == CLOSED) msg = "livingroom closed";
    else                     msg = "livingroom open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  
  currentStatus = contactState(PIN_KITCHEN_CONTACT);
  if (kitchenStatus != currentStatus)
  {
    kitchenStatus = currentStatus;
    if(kitchenStatus == CLOSED) msg = "kitchen closed";
    else                     msg = "kitchen open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  
  currentStatus = contactState(PIN_FRONTDOOR_CONTACT);
  if (frontDoorStatus != currentStatus)
  {
    frontDoorStatus = currentStatus;
    if(frontDoorStatus == CLOSED) msg = "frontdoor closed";
    else                     msg = "frontdoor open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  
  currentStatus = contactState(PIN_BACKDOOR_CONTACT);
  if (backDoorStatus != currentStatus)
  {
    backDoorStatus = currentStatus;
    if(backDoorStatus == CLOSED) msg = "backdoor closed";
    else                     msg = "backdoor open";
    
    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  
  currentStatus = contactState(PIN_GARAGEDOOR_CONTACT);
  if (garageDoorStatus != currentStatus)
  {
    garageDoorStatus = currentStatus;
    if(garageDoorStatus == CLOSED) msg = "garagedoor closed";
    else                     msg = "garagedoor open";

    smartthing.shieldSetLED(0, 2, 0); // green
    smartthing.send(msg);
    if(isDebugEnabled) Serial.println(msg);
    return; // only one message per loop
  }
  

}

//*****************************************************************************
void setNetworkStateLED()
{
  SmartThingsNetworkState_t tempState = smartthing.shieldGetLastNetworkState();
  if (tempState != stateNetwork)
  {
    switch (tempState)
    {
      case STATE_NO_NETWORK:
        if (isDebugEnabled) Serial.println("ST Network State is : NO_NETWORK");
          smartthing.shieldSetLED(2, 2, 0); // red
          break;
      case STATE_JOINING:
        if (isDebugEnabled) Serial.println("ST Network State is : JOINING");
          smartthing.shieldSetLED(2, 2, 0); // yellow
          break;
      case STATE_JOINED:
        if (isDebugEnabled) Serial.println("ST Network State is : JOINED");
          smartthing.shieldSetLED(0, 0, 2); // blue

          // force report of current door state
          officeStatus  = UNKNOWN;
          diningRoomStatus = UNKNOWN;
          bedroomStatus = UNKNOWN;
          livingRoomStatus = UNKNOWN;
          kitchenStatus = UNKNOWN;
          frontDoorStatus = UNKNOWN;
          backDoorStatus = UNKNOWN;
          garageDoorStatus = UNKNOWN;
  
          break;
      case STATE_JOINED_NOPARENT:
        if (isDebugEnabled) Serial.println("ST Network State is : JOINED_NOPARENT");
          smartthing.shieldSetLED(2, 0, 2); // purple
          break;
      case STATE_LEAVING:
        if (isDebugEnabled) Serial.println("ST Network State is : LEAVING");
          smartthing.shieldSetLED(2, 2, 0); // yellow
          break;
      default:
      case STATE_UNKNOWN:
        if (isDebugEnabled) Serial.println("ST Network State is : UNKNOWN");
          smartthing.shieldSetLED(2, 0, 0); // red
          break;
    }
    stateNetwork = tempState;
  }
}

//*****************************************************************************
// API Functions    | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
//                  V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
//*****************************************************************************
void setup()
{
  // setup default state of global variables
  isDebugEnabled = true;
  stateNetwork = STATE_JOINED;  // set to joined to keep state off if off

  // setup hardware pins
  
  pinMode(PIN_OFFICE_CONTACT, INPUT);
  pinMode(PIN_DININGROOM_CONTACT, INPUT);
  pinMode(PIN_BEDROOM_CONTACT, INPUT);
  pinMode(PIN_LIVINGROOM_CONTACT, INPUT);
  pinMode(PIN_KITCHEN_CONTACT, INPUT);
  pinMode(PIN_FRONTDOOR_CONTACT, INPUT);
  pinMode(PIN_BACKDOOR_CONTACT, INPUT);
  pinMode(PIN_GARAGEDOOR_CONTACT, INPUT);

  if(isDebugEnabled)
  { // setup debug serial port
    Serial.begin(9600);         // setup serial with a baud rate of 9600
    Serial.println("Starting up..");  // print out 'setup..' on start
  }

}

//*****************************************************************************
void loop()
{
  // run smartthing logic
  smartthing.run();

  // Check network connections (and send initial states on Join)
  setNetworkStateLED();

  if(stateNetwork == STATE_JOINED)
  {
    // Check the open/closed state of the doors
    updateContactStatus();
  }
}

//*****************************************************************************
void messageCallout(String message)
{
  smartthing.shieldSetLED(2, 2, 2); // white

  // if debug is enabled print out the received message
  if(isDebugEnabled)
  {
    Serial.print("Received message: '");
    Serial.print(message);
    Serial.println("' ");
  }

  if(message.equals("poll"))
  {
    // if asked for polling update then force update by setting all devices to unknown.
    officeStatus  = UNKNOWN;
    diningRoomStatus = UNKNOWN;
    bedroomStatus = UNKNOWN;
    livingRoomStatus = UNKNOWN;
    kitchenStatus = UNKNOWN;
    frontDoorStatus = UNKNOWN;
    backDoorStatus = UNKNOWN;
    garageDoorStatus = UNKNOWN;
  }

  smartthing.shieldSetLED(0, 0, 0); // off
}

Next, I needed to set up my Device Type code. To interact with the Arduino:

/**
 *  Arduino Contact Sensor Monitor
 *
 */

metadata {

    definition (name: "Arduino Contact Sensor Monitor", author: "Chrisotpher Etheridge") {
        
        fingerprint profileId: "0104", deviceId: "0138", inClusters: "0000"
        
        // capability "Sensor"
        // capability "Contact Sensor"

        attribute "office",   "string"
        attribute "diningroom",  "string"
        attribute "bedroom", "string"
        attribute "livingroom", "string"
        attribute "kitchen", "string"
        attribute "frontdoor", "string"
        attribute "backdoor",  "string"
        attribute "garagedoor", "string"

        command "poll"

    }

    simulator {
    }

    // Preferences

    // tile definitions
    tiles {

        standardTile("office", "device.office", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }
        
       	standardTile("diningroom", "device.diningroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        standardTile("bedroom", "device.bedroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        standardTile("livingroom", "device.livingroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        standardTile("kitchen", "device.kitchen", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        standardTile("frontdoor", "device.frontdoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }

        standardTile("backdoor", "device.backdoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        standardTile("garagedoor", "device.garagedoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
            state "closed",  label: "Closed",  icon: "st.contact.contact.closed",      backgroundColor: "#79b821"
            state "open",    label: "Open",    icon: "st.contact.contact.open",        backgroundColor: "#ffa81e"
        }


        main(["office","diningroom","bedroom","livingroom","kitchen","frontdoor","backdoor","garagedoor"])

        details(["office","diningroom","bedroom","livingroom","kitchen","frontdoor","backdoor","garagedoor"])
    }

}

def parse(String description) {
    def msg = zigbee.parse(description)?.text
    log.debug "Parse got '${msg}'"

    def parts = msg.split(" ")
    def name  = parts.length>0?parts[0].trim():null
    def value = parts.length>1?parts[1].trim():null

    name = value != "ping" ? name : null

    def result = createEvent(name: name, value: value)

    log.debug result

    return result
}

def poll() {
    log.debug "Polling requested"
    zigbee.smartShield(text: "poll").format()
}

(Chris Etheridge) #2

Next, I needed to create the ‘Simulated’ contact sensors. Basically, the Arduino is seen as a singular device with multiple functions or features. Similarly to how the ST multi sensor has temp, angle, acceleration, etc… BUT, we want each of those functions on the Arduino to act like independent devices so we can monitor them individually. So just going to +New Device and selecting the device type as the ‘Simulated Contact Sensor’ worked a treat but there was one huge problem. The pre-built ‘Simulated Contact Sensor’ would allow you to change the state of the sensor by tapping on the tile… So, I modified the pre-built code to remove the ‘action’:

/**
 * Simulated Contact Sensor without interaction
 *
 */
metadata {
	// Automatically generated. Make future change here.
	definition (name: "Simulated Contact Sensor - No interaction", namespace: "cetheridge30", author: "Christopher Etheridge") {
		capability "Contact Sensor"

	}

	simulator {
		status "open": "contact:open"
		status "closed": "contact:closed"
	}

	tiles {
		standardTile("contact", "device.contact", width: 2, height: 2) {
			state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
			state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
		}
		main "contact"
		details "contact"
	}
}

def parse(String description) {
	def pair = description.split(":")
	createEvent(name: pair[0].trim(), value: pair[1].trim())
}

def open() {
	log.trace "open()"
	sendEvent(name: "contact", value: "open")
}

def close() {
	log.trace "close()"
    sendEvent(name: "contact", value: "closed")
}

Finally, I needed a SmartApp to tie the Arduino connected devices to the Simulated devices:

/**
 *
 *  Subscribe Simulated Device to Arduino
 *
 */
definition(
	name: "Subscribe Simulated Device to Arduino",
	namespace: "cetheridge30",
	author: "Christopher Etheridge",
	description: "Subscribes and Updates Simulated Device Based on Arduino PINs",
	category: "My Apps",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"

)

preferences {
	section("Select arduino that sensors are connected to.") {
		input "arduino", "capability.contactSensor", title: "Select...", required: true
    }
	section("Select the simulated sensor you would like to attach to Office Windows.") {
        input "office", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to Dining Room Windows.") {
        input "diningroom", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to Bedroom Windows.") {
        input "bedroom", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to Livingroom Windows.") {
        input "livingroom", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to Kitchen Windows.") {
        input "kitchen", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to the Front Door.") {
        input "frontdoor", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to the Back Door.") {
        input "backdoor", title: "Select...", "capability.contactSensor"
	}
	section("Select the simulated sensor you would like to attach to the Garage Door.") {
        input "garagedoor", title: "Select...", "capability.contactSensor"
	}   
}

def installed()
{   
	subscribe()
    log.debug "Sending poll to update status on inital install"
    arduino.poll()
}

def updated()
{
	unsubscribe()
   	subscribe()
}

def subscribe()
{

		subscribe(arduino, "office.open", officeOpenHandler)
        subscribe(arduino, "office.closed", officeClosedHandler)
        subscribe(arduino, "diningroom.open", diningroomOpenHandler)
        subscribe(arduino, "diningroom.closed", diningroomClosedHandler)
        subscribe(arduino, "bedroom.open", bedroomOpenHandler)
        subscribe(arduino, "bedroom.closed", bedroomClosedHandler)
        subscribe(arduino, "livingroom.open", livingroomOpenHandler)
        subscribe(arduino, "livingroom.closed", livingroomClosedHandler)
        subscribe(arduino, "kitchen.open", kitchenOpenHandler)
        subscribe(arduino, "kitchen.closed", kitchenClosedHandler)
        subscribe(arduino, "frontdoor.open", frontdoorOpenHandler)
        subscribe(arduino, "frontdoor.closed", frontdoorClosedHandler)
        subscribe(arduino, "backdoor.open", backdoorOpenHandler)
        subscribe(arduino, "backdoor.closed", backdoorClosedHandler)
        subscribe(arduino, "garagedoor.open", garagedoorOpenHandler)
        subscribe(arduino, "garagedoor.closed", garagedoorClosedHandler)
        
 }

def officeOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    office.open()
}

def officeClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    office.close()
}

def diningroomOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    diningroom.open()
}

def diningroomClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    diningroom.close()
}
def bedroomOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    bedroom.open()
}

def bedroomClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    bedroom.close()
}
def livingroomOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    livingroom.open()
}

def livingroomClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    livingroom.close()
}
def kitchenOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    kitchen.open()
}

def kitchenClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    kitchen.close()
}
def frontdoorOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    frontdoor.open()
}

def frontdoorClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    frontdoor.close()
}
def backdoorOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    backdoor.open()
}

def backdoorClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    backdoor.close()
}
def garagedoorOpenHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    garagedoor.open()
}

def garagedoorClosedHandler(evt) {
    log.debug "arduinoevent($evt.name: $evt.value: $evt.deviceId)"
    garagedoor.close()
}

And that’s pretty much it folks. As much as I want to go through and explain every little detail that I discovered about the code. I sadly don’t have time and it would make this post WAY longer that it already is. However, if you have any questions, concerns, or comments. Please let me know!

I think some future additions to the project will be some led lights on the outside of the front panel to see status and because OoOoOo pretty lights! Also, I have seen some pretty cool looking dashboards on here so I could cut a hole in the front panel and put a touch panel on there to control… I dunno, stuff!!! Anyway, enjoy folks!


(Dan) #3

Nice work Chris! Thanks for sharing with the community!


#4

This is exactly what I want to do! Great project, and very nicely built. I like how you organized the wiring.

I don’t have any wiring in my house, but I have been playing with RF24 Wireless radios, and I think your code will be easy to convert to wireless messages between multiple boards.


(Chris Etheridge) #5

This is what I love about this community. I would love to see what you come up with!


(Steven Weinstein) #6

I’m very new to Arduino. Can you explain the wiring a little bit more. I understand the positive side but I’m confused on the negative and ground side. I don’t see the resistor in the picture. Great work on this project. I’m looking to do the same exact thing.

Thanks


(Chris Etheridge) #7

Not a problem. I will try to get a diagram up tomorrow.


#8

Just wondering if you thought of using the internal pull-up resistors? You could then connect one side of the switch to ground, and the other to the pin? that way when the window is closed, it would ground the input pin, and when it opens, it would have 5V, then you could eliminate any external resistors?

My switches are closed when the magnet is near, so maybe it works better with mine that way since the window is normally shut, the pin would normally be grounded. If you did it with a pull-up resistor and switches that are open when the window is shut, you would always have 5V running through the board. I don’t know if that would cause issues or not, but probably better to not have that.

If my thinking is correct, it would simplify the circuit if you have switched that are closed when the magnet is near (NO and NC designation is kind of confusing with reed switches I think).

I also assume you are using the SmartThings Library that came directly from SmartThings, and not the one that Dan uses for his ST_ANYTHING project?


(Chris Etheridge) #9

I am in no way an expert at electronics so everything I say here could be wrong.

My thinking of using a pull down resistor was that since there is 5v applied to all of the sensors, since they are normally closed with magnet, and what I am really reading is when the line goes to 0v, I wanted to ensure that the line was in fact 0v. Using a pull up resistor pretty much has the same effect, but the particular articles I read across the interwebs showed using pull down resistors. So is there a real concrete reason as to why? No. And yes, what I did added a little complexity since I had to solder several resistors inline. However…

I came across an article where a guy was trying to have very minimal current draw and was wanting to use larger resistance values. I wanted to be as efficient as possible as well! I have seen conflicting stories about the internal pull up but the range of resistance was anywhere from 10k to 100k. I am using 220k. Why does current draw matter? Even if it costs just a few cents a year, why not? Also, I am powering the Ardunio using the USB port on the SmartThings hub. So, if I lose power, the current draw from the Ardiuno would hopefully be minimal as possible and the project still work under battery power.

I have no numbers to back up what I said, and I have no idea if it really is a good idea to power the Ardunio off of the hub. And would the system even be functional under battery power? Meaning that while I do have my modem and router on a battery backup, if I lost my cable connection due to a power outage would the system still work under battery? We have seen some strange behavior when we lose connection to the mothership, and I know they have moved some functionality from the cloud to the local hub but I don’t know. :smile:

As I said, I am far from an expert and there is a good possibility that I am wrong. However, after a few months, I can report no issues or problems and everything is still working great.

As far as the ST_Anything project goes.I started with it and man, its really impressive. However, the further I dug into it, the more I realized that it was doing way more than what I was trying to do. Again, I was going for efficiency and I couldn’t in good conscience add all of the handlers for things I wasn’t using. So, I started stripping out code like a wild animal (I am more of a programmer than an electronics expert, even though I don’t claim to be an expert at programming either!). The more I stripped the more I realized that I didn’t need so many functions and calls to other code files with headers. After stripping out everything that I didn’t need, it worked, but it was still kinda messy (my fault, not Dan’s!). I was about to just write it from scratch but that is when I discovered that the documentation was not that helpful. Thankfully that is also when I found what lailoken did in what I think was one of the earlier garage door posts. I really just needed the code to make the Thingshield work, but what lailoken did was exactly what I was doing for the most part so the changes were fairly minimal.


(Steven Weinstein) #10

By no means do I want to bother you, but I was wondering if I could get that diagram. I have all the parts now.

Thanks


(Steven Weinstein) #11

Really I’m just confused on where the resistor goes.


(Dan) #12

Personally, I prefer to use the Arduino’s internal pull-up resistor feature… However, external pull-up and pull down resistors work as well…

See the following for a wiring diagram…

http://playground.arduino.cc/CommonTopics/PullUpDownResistor


#13

Don’t really need a resistor if you update the code

Just add this to the setup function. You’ll need to change the zone names to match the code above.

// setup pinups
digitalWrite(PIN_ZONE1_CONTACT, HIGH);
digitalWrite(PIN_ZONE2_CONTACT, HIGH);
digitalWrite(PIN_ZONE3_CONTACT, HIGH);
digitalWrite(PIN_ZONE4_CONTACT, HIGH);
pinMode(PIN_ZONE1_CONTACT, HIGH);
pinMode(PIN_ZONE2_CONTACT, HIGH);
pinMode(PIN_ZONE3_CONTACT, HIGH);
pinMode(PIN_ZONE4_CONTACT, HIGH);

You’ll also find that you’ll need to swap the “open” “closed” status too. Its backwards.

Once you do this, you don’t need a resister in place.


(Steven Weinstein) #14

I’m sorry really new to Arduino. Do add your code at the bottom of the setup function? Thanks for all the help.


#15

Believe it or not, I’m only 40 hours in and started learning it over Christmas. I’ve already created 2 new devices: security system & a sprinkler system.

Below is the entire setup function.

void setup()
{
// setup default state of global variables
isDebugEnabled = true;
stateNetwork = STATE_JOINED; // set to joined to keep state off if off

// setup hardware pins

pinMode(PIN_ZONE1_CONTACT, INPUT);
pinMode(PIN_ZONE2_CONTACT, INPUT);
pinMode(PIN_ZONE3_CONTACT, INPUT);
pinMode(PIN_ZONE4_CONTACT, INPUT);

// setup pinups
digitalWrite(PIN_ZONE1_CONTACT, HIGH);
digitalWrite(PIN_ZONE2_CONTACT, HIGH);
digitalWrite(PIN_ZONE3_CONTACT, HIGH);
digitalWrite(PIN_ZONE4_CONTACT, HIGH);
pinMode(PIN_ZONE1_CONTACT, HIGH);
pinMode(PIN_ZONE2_CONTACT, HIGH);
pinMode(PIN_ZONE3_CONTACT, HIGH);
pinMode(PIN_ZONE4_CONTACT, HIGH);

if(isDebugEnabled)
{ // setup debug serial port
Serial.begin(9600); // setup serial with a baud rate of 9600
Serial.println(“Starting up…”); // print out ‘setup…’ on start
}

}


(Steven Weinstein) #16

Thanks for that. As for the swaping the open and closed are you talking about this line.

int contactState(int pin)
{
// LOW -> closed
// HIGH -> open
return (digitalRead(pin) == HIGH)?CLOSED:OPEN;
}

Should it be this

int contactState(int pin)
{
// LOW -> closed
// HIGH -> open
return (digitalRead(pin) == HIGH)?OPEN:CLOSED;
}


#17

No, you have to go to the “if” statements to do the swapping.

Below, is an example of my zone1.

So change right after the msg=

if (Zone1Status != currentStatus)
{
Zone1Status = currentStatus;
if(Zone1Status == CLOSED) msg = “zone1 open”;
else msg = “zone1 closed”;


#18

@cetheridge30

I spent the last 6 hour trying to get the simulated device working. I couldn’t understand how the code from the app was sending the open or closed commands.

I could see the functions in your custom device but I never could get the actions to work until I added the following under capability. Otherwise the open/close commands would never fire.

I’m not sure if others ever had this problem but it simply wouldn’t work without it.

   capability "Contact Sensor"
    command "open"
    command "close"

PS I appreciate the posting, I was able to create a new/different device for security based on your posting.


(Chris Etheridge) #19

Whew, the new year sure has brought about new challenges and this is the first time I have been able to check the posts. Thanks to Dan for posting the link with the wiring diagram. It is far better than anything I could come up with in the time frames I have been dealing with.

As far as the continued conversation about the internal pull-up resistor goes. I would agree that it would make the project simpler, however, as it was stated the highs and lows would be backwards. I am still trying to figure out if one way would be better or not, but I have not found anything to say one way or another other than what I stated about current draw. Forgive me if I am off on my calculations but what I have come up with is that if the Arduino uses a 10k internal pull-up that is about 0.5mA of current being used. This is a small amount but then you multiply that by the 8 sensors and that is an additional 4mA draw, which is on top of around the 30~40mA the Arduino pulls. Having said that the way I am doing it with the 220k resistors, well lets just say its a really really miniscule amount of current draw. Put 5/220,000 in a calculator to see for yourself. So in essence I am saving more than 3mA’s of current. So again, if saving power is not a concern and just want a simpler setup, by all means, use the internal pull-ups. :smile:

@DrHill, I am not sure that the commands for open and close are needed. As I understand it, when you add those commands you are setting up the ability to use the simulated sensor as a switch and you would be able to change the commands from the simulated sensor manually, say via a tile. That is actually what I removed because I found that it was allowing me to change state manually. At least in this instance I am trying to use it in the true sense of a sensor, i.e. it just “senses” changes, albeit virtually. The SmartApp is what forces the simulated sensor to change state.


#20

@cetheridge30

I would support the code side more rather than the external resister only because it makes the wiring that much easier to explain to everyone that is new.

command “open” allows you to call the method as part of the devices “open” function. This does not allow someone to change the state of the sensor from within the UI… not from my experience.

The action command I believe you are refering to that allows for changes in state is a line like this:
state “off”, label: ‘zone1’, action: “switch.on”, icon: “st.switches.switch.off”

This line of code exists within the title definition whereas the command is part of the device definition.