Project tutorial
Physical Home Automation Interface

Physical Home Automation Interface © CC BY-NC

A physical smart home interface. A mini-me for your house.

  • 13,191 views
  • 4 comments
  • 34 respects

Components and supplies

About this project

See the two videos below for a quick explanation of this project.

Physical Home Automation Interface
Interface with real world control

An interface conveys information and allows the user to control things. Most home automation platforms rely on a “virtual interface ”. You pull out a smart phone and open the app to see what’s going on with your house and turn lights on and off. That works OK when you’re away. But looking at a virtual representation and parsing the information on the display takes work. It requires focus, and doesn't feel intuitive.

I wanted to make a “physical interface” - a small model house that physically mimics the things I want to know about with my real house. So when the garage door is opened, I want the garage door on the model to also open. This model house could sit on my coffee table, and I can glance at it to see if the garage door has been left opened before going to bed. Or I can have this on my desk at work, connected to my home via VPN. When I’m at work, I can glance at it to see if the front door has been left opened. This physical interface can be as creative or as utilitarian as I make it.

So, in the following steps, I will

  1. Build a model house to display things like door position, energy usage, and whether a light has been left on.
  2. Build an energy monitor using the Open Energy Monitor Arduino library, and feed energy use information to the model house and to OpenHAB
  3. Provide a couple ways of sending door/window position to the model house. Show how the Wink Hub and the Wink "Tripper" contact sensor data can be utilized in a DIY home automation system.
  4. Use Wink and Arduino to perform outputs, like open/close the actual garage door or turn lights on and off.

The model house has some servos and LED's wired to an Arduino controller. This controller subscribes to MQTT messages that indicate door positions and energy usage, and actuates the servos accordingly. Same idea with the LED that indicates whether a light is on or off. There's a few options for getting this sensor information to the MQTT broker, so I'll detail that in later steps. In the middle of it all is a Raspberry Pi running a MQTT broker (Mosquitto) and OpenHAB. Although OpenHAB is not needed to run the model house, it is needed to provide the interface for the smart phone app, and allow remote monitoring and actuation. Just because I want to have a physical interface doesn't mean I'm ready to throw out the virtual one.



The model house also has two buttons. One of the buttons toggles a zigbee lightbulb on/off. The other button opens and closes the garage door (on the REAL house).


Part 1: House Construction

1) Construct model house

2) Control options, wiring, & code

Part 2: Inputs (Sensors)

3) Sensor: Energy monitor

4) Sensor: DIY sensor node option

5) Sensor: Wink Hub & Tripper contact sensor

Part 3: Outputs

6) Lights

7) Garage door opener


Step 1: Model House Construction

I don’t intend this step to be prescriptive. I’m pretty amature when it comes to arts and crafts, so I’ll just show how I built my model house. You’ll want to build it to resemble your own dwelling and reflect the things you care about. Lots of room for creativity here. Some of the components in this picture (like the current transformer) will be used in later steps.

Components:


Roof

I cut out one of the side flaps of the box and attached it to the other (still attached) side flap to form a roof. I used a small box to provide a structure for the right angle, and later supported it better with a Lego piece. You can probably just use whatever you have around the house to make this right angle.

Doors / Windows

Cut the holes for doors that you want to show. Attach a hinge or two on the door with double stick tape and attach to the house. I know, nothing fancy, so feel free to improvise with what you got around the house. I used 3M double sided foam adhesives, the kind that comes with hooks. I also used these foam adhesive strips to mount the servo motors. For the garage door, the servo motor arm moves the garage door open, and gravity closes the garage door. For the front door, I needed to attach a string on the hinged door so the servo arm can open the door. The yellow Lego piece you see is there to offset the servo from the hinge.

//www.youtube.com/embed/z-xyVXUSqNM

Energy Meter

Nothing fancy. Just cut out an arrow-looking thing and attach it to the servo arm. Cut out a vaguely shrub looking shape and mark it up with a kilowatt scale, and friction fit the servo motor onto the box with the shrub in between.

Above the energy consumption servo, I taped a red LED.

I also have two buttons to control lights and the garage door. These are momentary buttons. The buttons are threaded with a nut on the outside to hold it against the cardboard box wall. On the other side are the metal contacts for wires to be soldered on to.

Step 2: House Construction - Wires & Code

Wiring

Here's the wiring diagram. I made a pretty big mess of the wiring inside the box. If you'd rather just know which wires are on what pins:

  • status pin LED: 7
  • lighting indicator LED: 4
  • Servo 1 (front door): 3
  • Servo 2 (garage door): 5
  • Servo 3 (shrub of energy use): 6
  • Button 1 (Lights on/off): 8
  • Button 2 (Garage door open/close): 9

Controller Options

You can use what you're comfortable with and what you have on hand. A less expensive ($20) option is to use an Arduino Uno clone and ethernet shield. I started with that, but that tethered me to the ethernet cable. So I switched it to an Arduino Yun ($65). Much more expensive, but also gave me the freedom to use wifi. The Yun was really easy to use. You basically:

  1. Connect the Yun to your router via ethernet
  2. Navigate to the Yun's webpage
  3. Setup passwords and static IP on your router
  4. Download the Yun sketch

Attached below are the sketches for both a Arduino Uno and Arduino Yun. They're pretty similar, and except for the ethernet bridge used in the Yun, you can pretty much copy the Yun code over to the Uno. After I made the switch to the Yun, I added the two control buttons. As a result, the Uno sketch doesn't have those buttons.

The video in the first step shows the Arduino Yun. Here's a video using the Uno and ethernet shield. When this video was made, I hadn't installed the two buttons yet, but everything else works the same.

//www.youtube.com/embed/7i6McpbU3Gs



Step 3: Sensor: Energy Monitor

Now that we have a physical interface capable of displaying the energy usage, we need to build a sensor node to read the energy consumption of the house and publish that consumption to the MQTT broker. There's a couple ways to do this. I'm using an Arduino Yun. It's the least complicated method, but not the least expensive. If you want, you can use an Arduino Uno, ethernet shield, and a wireless router to act as a wifi bridge. Or you can use a Pi with the Open Energy Monitor package. I'll just cover the Yun method.

I'm using a $7 current transformer from ebay. You can find the 100A version of the Yhdc SCT-013-000 here . Wire it up according to the wiring diagram above, and upload the Arduino Yun sketch at the bottom of this step. Be sure to modify the code with your MQTT broker IP address. This page for the Open Energy Monitor library is a good reference. Here's the ideal component values.

  • Burden Resistor = 33 ohm
  • Voltage Divider Resistor = 10k ohm
  • Capacitor = 10uF

The picture of my energy monitor doesn't really match the circuit diagram because I didn't have those exact components on hand. I had to use two 68 ohm resistor in parallel because I didn't have the 33 ohm burden resistor. And I didn't have a 10uF capacitor for the rectifier circuit, so I used two 22uF capacitors instead. The series equivalent capacitance is close enough.

Attach the current transformer on one of the incoming phases of your house. I only had a single 100A transformer, so I'm only monitoring one of the phases. Eventually, I'd like to get more transformers to monitor the other leg of the incoming power and also the branch circuits. Using an actual amp meter, my DIY setup always read 1 amp above the amp meter across different amp readings (see 5th image above). Pretty simple matter to just subtract that extra amp.


OpenHAB

Since we have the data coming in, we might as well also display it on OpenHAB so the data can be graphed. Here's the relevant OpenHAB configuration.

Item Definition

<p>Number itm_smarthome_energy_amps "Energy (amps) [%.1f]" {mqtt="<[mymosquitto:2853:state:default]"}</p><p>Number itm_smarthome_energy_watts "Energy (Watts) [%.1f]"  {mqtt="<[mymosquitto:2852:state:default]"}</p>

Sitemap

<p>Text label="Energy" icon="firstfloor"<br>{</p><p>	Frame label="Energy Usage"
	{
		Text item=itm_smarthome_energy_amps</p><p>		Text item=itm_smarthome_energy_watts</p><p>		Chart item=itm_smarthome_energy_watts period=h refresh=5000
	} //Frame energy usage</p><p>}//Text label="Energy"</p>

Persistence

Since we're using charts, we need to define some kind of persistence strategy for the energy use. RRD4J is easiest to use, so here's what I have for "/openhab/configurations/persistence/rrd4j.persist".

<p>Strategies {<br>	// for rrd charts, we need a cron strategy
	everyMinute : "0 * * * * ?"
}</p><p>Items {
	DemoSwitch,NoOfLights,Window_GF_Toilet,Heating* : strategy = everyChange, everyMinute, restoreOnStartup
	
	// let's only store temperature values in rrd
	Temperature*,Weather_Chart* : strategy = everyMinute, restoreOnStartup
	itm_smarthome_energy_watts : strategy = everyUpdate
}</p>

Energy Monitor Screen

Step 4: Sensor: DIY Wireless Sensor Nodes

There are a few options for wireless open/close sensors.

In one of my previous projects I used a $5 wireless transceiver to send sensor data over a MQTT gateway. I'm still using this project to get the garage door status to OpenHAB, and in the demo video, that's actually how the model house's garage door reflects my actual garage door status. The detailed code and circuit can be found in this step if you want to use it. It's kind of ugly, but it's in the garage where no one will likely notice.

There is also a light sensor that I'm using to indicate whether a light has been left on. This is also from that previous Instructable detailed in this step. It's part of the Uber sensor that uses a photo resistor to send brightness information wirelessly back to OpenHAB. In this case, I'm simply subscribing to the MQTT topic that indicates light level.

I've also made a battery powered reed switch sensor that uses the same wireless transceiver and gateway in that previous Instructable. However, it's not very good looking. I can't really use it on an interior door or window for aesthetic reasons. So, to over come this problem, I'm using nicer looking consumer-grade reed switch sensors from Wink. Which leads us to the next step.

//www.youtube.com/embed/uiD-HLezygI
//www.youtube.com/embed/VKniJzIVHsI

Step 5: Sensor: Wink Hub

I happened on this blog post from an early Wink Hub user who found a way to root the hub to gain access to a PHP exploit. This exploit allows you to run an "aprontest" utility to control things that have been paired with the Wink Hub. Using this method, I've been able to control lights from the OpenHAB interface.

The most interesting benefit to rooting the Wink Hub is that it gives you local control over lights and sensor status without having to access the Wink server. The Wink Hub and Wink API always needs to go to the internet to contact the Wink server to do lighting control or get sensor status. Now, with this PHP exploit, lighting and sensor operations can be kept to your local LAN. That's great.

I've included a PHP script at the bottom of this step. If you can't open this file, try this link. This script runs on the Raspberry Pi and polls the Wink Hub for the status of two Wink Tripper reed switches. This status is sent to OpenHAB via the REST API. OpenHAB will then publish MQTT topics for these door positions. The controller for the model house then opens or closes the doors by subscribing to these door position topics.

The three OpenHAB configuration files (items, sitemap, and rules) attached in this step are needed to make everything work. They define the contact items that the polling script interacts with via the REST interface. There's also an example script for controlling zigbee light bulb via OpenHAB.

//www.youtube.com/embed/tWKPcBOn1KM

Scripts and configuration files.


Step 6: Output: Lights

Because of the order that I've covered the configuration files, the previous steps pretty much provided everything needed to control a "connected light bulb" via both the physical interface and the OpenHAB interface. The lights can be any light that the Wink hub supports. Currently, I've tested this with the Cree Connected Bulb and the GE Wink lights. Both work as expected. I'll just throw this video here that better shows how the light sensor and buttons control the smart bulb.

//www.youtube.com/embed/KSDUEfro3Vo

Step 7: Output: Garage Door Opener

The configuration files provided in Step 5 includes most of the necessary OpenHAB items for controlling a garage door. But you still need the something to actually open and close the garage door. For that, I'm modifying parts of a previous Instructable. I made a garage door opener with these components:

The Arduino controls a reed relay by opening and closing the dry contacts. The button from the spare garage door opener is wired across the dry contact on the reed relay. Connect Pin 5 and GND from the Arduino to the two coil pins (two outer pins) of the reed relay, and the inner relay pins to the button on the garage door remote.

The Arduino subscribes to a MQTT topic and waits for the open/close command. When it sees this topic, it energizes the reed relay momentarily, closing the "button" on the spare garage door remote. The Arduino sketch is attached below. In addition, add the "garage_monitor_rules.txt" to your rules file. This is needed in addition to the rules attached in Step 5. If you don't use the ultrasonic sensor method that I used, this is the part you would need to change to suit your modification.

//www.youtube.com/embed/CqbRosfqM3c

If your garage door is pretty quite or you want some kind of audio announcement in another part of the house for when the garage door opens, the added rule above can play an audio file. You can hear it in the first video demo about a minute thirty in.

//www.youtube.com/embed/pdKfJtnpNzs



Step 8: Other Thoughts

The decisions made in this project reflect the tools I'm comfortable with, the parts I have on hand, and my priorities for how I want things to work. You probably have a different set of tools, and you have different hardware components readily available. You probably also have different ideas for how home automation should work.

There's lots of flexibility when using MQTT and OpenHAB, and you don't need to do things exactly as I've done it. The controller used to control the model house can be some flavor of Arduino, a Raspberry Pi, or even a Sparkcore. The DIY sensors can be an Arduino or a standalone ESP8266. The only constraint is that the sensor data needs to be published to the MQTT broker somehow. If you have a USB Z-wave stick on the OpenHAB installation, you can use OpenHAB as a Z-wave to MQTT bridge, and utilize Z-wave sensors for door sensing.

Even the Wink open/close sensors could be done differently. If you don't root the Wink Hub, you can use the Wink API to grab the sensor status and post them to OpenHAB, or post them directly via MQTT. This requires using the Wink Server, but it removes the constraint of a rooted hub.

So, lots of ways to do things differently. I tend towards using hardware that is the lowest common denominator, so Arduino and cardboard boxes.

Code

smarthome_yun.inoPlain text
// Eric Tsai
// 2015-04-13
// Arduino Yun code for controlling physical smart home interface
// Modify MQTT topic names to match your use
// Modify MQTT broker IP address

//new yun includes
#include <Bridge.h>
#include <yunclient.h>
#include <PubSubClient.h>

//old ethernet includes when using ethernet shield
/*
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
*/

#include <Servo.h>




//Ethernet shield setup
/*
IPAddress ip(192, 168, 2, 36);
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x0D, 0x43, 0x13 };
byte server[] = { 192, 168, 1, 101 };
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

*/
unsigned long keepalivetime=0;
unsigned long MQTT_reconnect=0;

//use yunclient to bridge to network
YunClient yun;          //equivalent of ethernet client
PubSubClient client("192.168.1.101", 1883, callback, yun);

bool conn_ok;

//use LED for indicating MQTT connection status.
int ledPin = 4;     //indicate lights on
int statusPin = 7;  //indicate MQTT conn status
//servo control
int servo1Pin = 3;  //front door
int servo2Pin = 5;  //garage door
int servo3Pin = 6;  //energy usage meter
Servo servo1;   //door
Servo servo2;   //garage door
Servo servo3;   //energy
int button1 = 8; //button over front door
int button2 = 9;  //button over garage door

//servo operation:  target positions for servos
int servo1_target = 5;  //door, closed
int servo2_target = 5;  //garage, closed
int servo3_target = 180;  //energy, 180 is "0" watts, motor mounted backwards
int servo1_pos_cur = 5;
int servo2_pos_cur = 5;
int servo3_pos_cur = 180; // 180 is "0" watts, motor mounted backwards
int servo1Opened = 5;
int servo1Closed = 130;
int servo2Opened = 5;
int servo2Closed = 150;
unsigned long servo1_time = 0;
unsigned long servo2_time = 0;
unsigned long servo3_time = 0;

//debounce on buttons, so you don't spam publish
unsigned long button1_db = 0;
unsigned long button2_db = 0;
int button=0;

int callback_flag = 0;
char buff_message[12];
//---------------------------------------------------------------
// MQTT call back
// react to MQTT messages here
//---------------------------------------------------------------
void callback(char* topic, byte* payload, unsigned int length) {

  
  //convert topic to int.
  int mytopic = atoi (topic);
  //Serial.print(mytopic);

  //convert payload to int
  payload[length] = '\0';   //add a line return so atof can parse correctly
  float mymsg = atof( (const char *) payload);

  
  //led
  if (mytopic == 2822)
  {
    if (mymsg == 1)
    {
      digitalWrite(ledPin, HIGH);
    }
    if (mymsg == 0)
    {
      digitalWrite(ledPin, LOW);
    }
  }

  
  //servo 1, front door
  if (mytopic == 2832)
  {
    if (mymsg == 1) //opened
    {
      //Serial.println("servo1 opened");
      servo1_target = servo1Opened;
    }
    if (mymsg == 0)  //closed
    {
      //Serial.println("servo1 closed");
      servo1_target = servo1Closed;
    }
    //Serial.println(servo1_target);
  }

  /*
  //second garage door signal

	"closed" = off = send 1
	"open" = on = send 0
  */
  //servo 2, garage door
  if (mytopic == 2842)
  {
    if (mymsg == 1) //opened
    {
      servo2_target = servo2Opened;
    }
    if (mymsg == 0)  //closed
    {
      servo2_target = servo2Closed;
    }
    //callback_flag=1;
    //servo3_target = mymsg;
  }

  
  //servo 3, energy meter
  if (mytopic == 2852)
  {
    //message = watts
    //bound watts to meter max & min
    
    if (mymsg > 6000)
    {
      mymsg = 6000;
    }
    if (mymsg < 0)
    {
      mymsg = 0;
    }
    
    //bias meter from 180 degrees to 0 degrees
    //180 deg to 0 deg = 0 watt to 6000 watts, for example
    //set max watts to what makes sense for you.
    servo3_target = 180-((1-((6000-mymsg)/6000))*180)-25;
    
    callback_flag=1;

  }
}//end callback


void setup() 
{
  
  pinMode(ledPin, OUTPUT);    //LED indicating light on
  pinMode(statusPin, OUTPUT);
  pinMode(button1, INPUT_PULLUP);  //use pull-up resistor, invert logic
  pinMode(button2, INPUT_PULLUP);  //use pull-up resistor, invert logic

  
  digitalWrite(ledPin, HIGH);

  //yun bridge
  Bridge.begin();

  //connect to MQTT broker
  client.connect("yun smarthome");
  client.publish("watch", "Smart Home Connected!");
  
  keepalivetime=millis();
  
  //Wire.onReceive (receiveEvent);

  
  MQTT_reconnect = millis();
  

  //client.subscribe("#");   //test subscribe
  client.subscribe("2822");   //LED
  client.subscribe("2832");   //servo 1 topic
  client.subscribe("2842");   //servo 2 topic
  client.subscribe("2852");   //servo 3 topic
  
  digitalWrite(ledPin, LOW);
  
  //servo
  servo1.attach(servo1Pin);
  servo1.write(90);
  servo2.attach(servo2Pin);
  servo2.write(90);
  servo3.attach(servo3Pin);
  servo3.write(5);
}  // end of setup



void loop() 
{

  client.loop();  //MQTT processing needs this to run

  //For servo positioning, don't want to move too fast.
  //Must crawl from current position to target position
  //but also avoid using "delay" cmd, that just freezes up microcontroller
  
  //servo 1
  if ((millis() - servo1_time) > 20)
  {
    if (servo1_pos_cur > servo1_target)
    {
      servo1_pos_cur = servo1_pos_cur - 1;
    }
    if (servo1_pos_cur < servo1_target)
    {
      servo1_pos_cur = servo1_pos_cur + 1;
    }
    servo1.write(servo1_pos_cur);
    servo1_time = millis();
  } //end servo 1 target control
  
  
  //servo 2
  if ((millis() - servo2_time) > 20)
  {
    if (servo2_pos_cur > servo2_target)
    {
      servo2_pos_cur = servo2_pos_cur - 1;
    }
    if (servo2_pos_cur < servo2_target)
    {
      servo2_pos_cur = servo2_pos_cur + 1;
    }
    servo2.write(servo2_pos_cur);
    servo2_time = millis();
  } //end servo 2 target control


  //servo 3
  if ((millis() - servo3_time) > 20)
  {
    if (servo3_pos_cur > servo3_target)
    {
      servo3_pos_cur = servo3_pos_cur - 1;
    }
    if (servo3_pos_cur < servo3_target)
    {
      servo3_pos_cur = servo3_pos_cur + 1;
    }
    servo3.write(servo3_pos_cur);
    servo3_time = millis();
  } //end servo 3 target control

  if (callback_flag == 1)
  {
    
     callback_flag = 0;
     
     dtostrf (servo3_target, 4, 5, buff_message);
     //client.publish("watch","ssaw call back)");
     client.publish("watch", buff_message);
  }

  
  //button 1
  button=digitalRead(button1);
  if (button==0)  //inverted logic
  {
	if ( ((millis() - button1_db)>3000) || (button1_db > millis()))
	{
		button1_db=millis();
		client.publish("2862", "button1 yaya");
	}
  }
  
  
  //button 2
  button=digitalRead(button2);
  if (button==0)  //inverted logic
  {
	if ( ((millis() - button2_db)>3000) || (button2_db > millis()))
	{
		button2_db=millis();
		client.publish("2872", "button2 yaya");
	}
  }
  
  //check network connection to MQTT broker every 60 seconds.
  //reconnect if no longer connected
  if ((millis() - MQTT_reconnect) > 60000)
  {
    conn_ok = client.connected();
    if (conn_ok==1)
    {
      digitalWrite(statusPin, HIGH);
      //Serial.println("MQTT connected OK");
    }
    else
    {
      digitalWrite(statusPin, LOW);
      //Serial.println("MQTT NOT connected OK");
    }

    //no connection, reconnect
    if (conn_ok == 0)
    {
      client.disconnect();
      delay(5000);
      while (client.connect("smarthouse") != 1)
      {
        digitalWrite(statusPin, LOW);
        //Serial.println("Error connecting to MQTT");
        delay(4000);
      }
      digitalWrite(statusPin, HIGH);
    }
    //Serial.println("reconnected to MQTT");
    MQTT_reconnect = millis();
    client.publish("watch","smart home heartbeat!"); 

  }//end Mosquitto connection check
}  // end of loop
smarthome_ethernet.inoPlain text
// Eric Tsai
// 2015-04-1
// Arduino Uno w/ Ethernet, code for controlling physical smart home interface
// Modify MQTT topic names to match your use
// Modify MQTT broker IP address

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

#include <Servo.h>

//Ethernet
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x0D, 0x43, 0x13 };
byte server[] = { 192, 168, 1, 101 };
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
unsigned long keepalivetime=0;
unsigned long MQTT_reconnect=0;



bool conn_ok;

//use LED for indicating MQTT connection status.
int ledPin = 4;     //indicate lights on
int statusPin = 7;  //indicate MQTT conn status
//servo control
int servo1Pin = 3;  //front door
int servo2Pin = 5;  //garage door
int servo3Pin = 6;  //energy usage meter
Servo servo1;   //door
Servo servo2;   //garage door
Servo servo3;   //energy

//servo operation:  target positions for servos
int servo1_target = 5;  //door, closed
int servo2_target = 5;  //garage, closed
int servo3_target = 180;  //energy, 180 is "0" watts, motor mounted backwards
int servo1_pos_cur = 5;
int servo2_pos_cur = 5;
int servo3_pos_cur = 180; // 180 is "0" watts, motor mounted backwards
int servo1Opened = 5;
int servo1Closed = 120;
int servo2Opened = 5;
int servo2Closed = 150;
unsigned long servo1_time = 0;
unsigned long servo2_time = 0;
unsigned long servo3_time = 0;

//---------------------------------------------------------------
// MQTT call back
// react to MQTT messages here
//---------------------------------------------------------------
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("received MQTT");
  
  //convert topic to int.
  int mytopic = atoi (topic);
  //Serial.print(mytopic);

  //convert payload to int
  payload[length] = '\0';   //add a line return so atof can parse correctly
  float mymsg = atof( (const char *) payload);

  //print MQTT message
  Serial.println("");
  Serial.print("(");
  Serial.print(mytopic);
  Serial.print(", ");
  Serial.print(mymsg);
  Serial.println(")");
  
  //led
  if (mytopic == 2822)
  {
    if (mymsg == 1)
    {
      digitalWrite(ledPin, HIGH);
    }
    if (mymsg == 0)
    {
      digitalWrite(ledPin, LOW);
    }
  }

  
  //servo 1, front door
  if (mytopic == 2832)
  {
    if (mymsg == 1) //opened
    {
      Serial.println("servo1 opened");
      servo1_target = servo1Opened;
    }
    if (mymsg == 0)  //closed
    {
      Serial.println("servo1 closed");
      servo1_target = servo1Closed;
    }
    Serial.println(servo1_target);
  }


  
  /*
  //second garage door signal

	"closed" = off = send 1
	"open" = on = send 0
  */
  //servo 2, garage door
  if (mytopic == 2842)
  {
    if (mymsg == 1) //opened
    {
      servo2_target = servo2Opened;
    }
    if (mymsg == 0)  //closed
    {
      servo2_target = servo2Closed;
    }
  }

  
  //servo 3, energy meter
  if (mytopic == 2852)
  {
    //message = watts
    //error check
    if (mymsg > 6000)
    {
      mymsg = 6000;
    }
    if (mymsg < 0)
    {
      mymsg = 0;
    }
    //bias meter from 180 degrees to 0 degrees
    //180 deg to 0 deg = 0 watt to 6000 watts, for example
    //set max watts to what makes sense for you.
    servo3_target = 180-((1-((6000-mymsg)/6000))*180);
    //servo3_target = mymsg;
  }
}//end callback


void setup() 
{
  //ethernet
  //Ethernet.begin(mac, ip);
  //Wire.begin (MY_ADDRESS);
  
  Serial.begin (9600);
  
  Serial.println("starting");
  
  pinMode(ledPin, OUTPUT);    //LED indicating light on
  pinMode(statusPin, OUTPUT);
  
  digitalWrite(ledPin, HIGH);
  //wait for IP address
  while (Ethernet.begin(mac) != 1)
  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(5000);
  }
  

  Serial.println("ethernet OK");
  keepalivetime=millis();
  


  while (client.connect("smarthouse") != 1)
  {
    Serial.println("Error connecting to MQTT");
    //delay(3000);
    delay(4000); 
  }
  MQTT_reconnect = millis();
  Serial.println("setup complete");
  client.publish("smarthouse","hello world");    //test publish
  //client.subscribe("#");   //test subscribe
  client.subscribe("2822");   //LED
  client.subscribe("2832");   //servo 1 topic
  client.subscribe("2842");   //servo 2 topic
  client.subscribe("2852");   //servo 2 topic
  
  digitalWrite(ledPin, LOW);
  
  //servo
  servo1.attach(servo1Pin);
  servo1.write(90);
  servo2.attach(servo2Pin);
  servo2.write(90);
  servo3.attach(servo3Pin);
  servo3.write(5);
}  // end of setup



void loop() 
{

  client.loop();  //MQTT processing needs this to run

  //For servo positioning, don't want to move too fast.
  //Must crawl from current position to target position
  //but also avoid using "delay" cmd, that just freezes up microcontroller
  
  //servo 1
  if ((millis() - servo1_time) > 20)
  {
    if (servo1_pos_cur > servo1_target)
    {
      servo1_pos_cur = servo1_pos_cur - 1;
    }
    if (servo1_pos_cur < servo1_target)
    {
      servo1_pos_cur = servo1_pos_cur + 1;
    }
    servo1.write(servo1_pos_cur);
    servo1_time = millis();
  } //end servo 1 target control
  
  
  //servo 2
  if ((millis() - servo2_time) > 20)
  {
    if (servo2_pos_cur > servo2_target)
    {
      servo2_pos_cur = servo2_pos_cur - 1;
    }
    if (servo2_pos_cur < servo2_target)
    {
      servo2_pos_cur = servo2_pos_cur + 1;
    }
    servo2.write(servo2_pos_cur);
    servo2_time = millis();
  } //end servo 2 target control


  //servo 3
  if ((millis() - servo3_time) > 20)
  {
    if (servo3_pos_cur > servo3_target)
    {
      servo3_pos_cur = servo3_pos_cur - 1;
    }
    if (servo3_pos_cur < servo3_target)
    {
      servo3_pos_cur = servo3_pos_cur + 1;
    }
    servo3.write(servo3_pos_cur);
    servo3_time = millis();
  } //end servo 3 target control

  
  //check network connection to MQTT broker every 60 seconds.
  //reconnect if no longer connected
  if ((millis() - MQTT_reconnect) > 60000)
  {
    conn_ok = client.connected();
    if (conn_ok==1)
    {
      digitalWrite(statusPin, HIGH);
      Serial.println("MQTT connected OK");
    }
    else
    {
      digitalWrite(statusPin, LOW);
      Serial.println("MQTT NOT connected OK");
    }

    //no connection, reconnect
    if (conn_ok == 0)
    {
      client.disconnect();
      delay(5000);
      while (client.connect("smarthouse") != 1)
      {
        digitalWrite(statusPin, LOW);
        Serial.println("Error connecting to MQTT");
        delay(4000);
      }
      digitalWrite(statusPin, HIGH);
    }
    //Serial.println("reconnected to MQTT");
    MQTT_reconnect = millis();
    client.publish("smarthouse","heartbeat every minute!"); 
  }//end Mosquitto connection check

}  // end of loop
energy_monitor_yun.inoPlain text
/*
Eric Tsai
2015-04-22
Arduino Yun code for publishing energy use to MQTT broker
Modify the "PubSubClient client" for your broker IP address
*/


#include <Bridge.h>
#include <yunclient.h>
#include <PubSubClient.h>
#include "EmonLib.h"                   // OpenEnergy Monitor project library


int LED = 3;
EnergyMonitor emon1;                   // open energy monitor
unsigned long MQTT_reconnect=0;
unsigned long read_energy=0;
double Irms;
bool conn_ok;
YunClient yun;          //equivalent of ethernet client


//really shouldn't need call back, but just in case it's needed.
void callback(char* topic, byte* payload, unsigned int length) {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);              // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
}



//use yunclient to bridge to network
PubSubClient client("192.168.1.101", 1883, callback, yun);


//**********************************************************************
void setup()
{
    // initialize digital pin 13 as an output.
  pinMode(LED, OUTPUT);

  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW

  Bridge.begin();

  client.connect("yun_energy");
  client.publish("watch", "Energy Monitor Connected!");
  client.subscribe("yun_energy");
  
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(3000);              // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW

  
  emon1.current(5, 60);             // Current: input pin, calibration.
}



//**********************************************************************
void loop()
{
  char buff_message[12];    //message buffer for MQTT publish
  float value;
  client.loop();    //run this every loop to maintain MQTT connection
  
  Irms = emon1.calcIrms(1480);  // Calculate Irms only, 1480 means read Irms.
  
  //publish current every 10 seconds.
  if (millis() - read_energy > 10000)
  {
    //amps
    value = Irms;
    dtostrf (value, 4, 5, buff_message);
    client.publish("2853", buff_message);
    read_energy = millis();
    
    //watts
    value = Irms*115;
    dtostrf (value, 4, 5, buff_message);
    client.publish("2852", buff_message);
  }

  
  //maintain MQTT connection
  if ((millis() - MQTT_reconnect) > 60000)
  {
    conn_ok = client.connected();
    if (conn_ok==1)
    {
      digitalWrite(LED, HIGH);
    }
    else
    {
      digitalWrite(LED, LOW);
    }
    
    //no connection, reconnect
    if (conn_ok == 0)
    {
      client.disconnect();
      delay(5000);
      while (client.connect("yun_energy") != 1)
      {
        delay(4000);
      }
      digitalWrite(LED, HIGH);
      client.publish("watch", "Energy Monitor reconnected");
    }
    
    MQTT_reconnect = millis();
  }//end Mosquitto connection check
  
}

Schematics

mini-house servo
Sche servo
mini-house buttons
Sche buttons
energy monitor
Sche energy

Comments

Similar projects you might like

Uber Home Automation

Project in progress by Eric Tsai

  • 34,501 views
  • 4 comments
  • 128 respects

AutoHome - Internet of Things (IoT) for Home Automation

Project showcase by Team AutoHome

  • 2,510 views
  • 0 comments
  • 5 respects

Android App-Based Home Automation System Using IOT

Project tutorial by Team Autoshack

  • 24,845 views
  • 17 comments
  • 75 respects

HBus Home Automation And Artik

Project tutorial by Vincenzo

  • 2,404 views
  • 0 comments
  • 6 respects

Home Smart Home

Project tutorial by Syed Sanoor

  • 68,551 views
  • 10 comments
  • 193 respects

WARAN - Home Automation

Project tutorial by Arjun Ganesan

  • 30,101 views
  • 13 comments
  • 77 respects
Add projectSign up / Login