Triggering Actions on Smart Home Devices with Arduino

details

It’s time to crack open this blog with a post dedicated to my first home automation mini-project – opening and closing my garage doors by replacing the original RF (Radio Frequency) remote control with my mobile phone.

For this I’ve decided to use an Arduino with Ethernet Shield:

Arduino

Idea and Approach

DSC_9158

The idea initially came up when I wanted to replace my central heating system control with Nest, which would not work in my case because the only way to control the heating system is by a RF remote control.

Then I saw Bradley’s SwitchIt video which gave me another idea – to capture the RF signal from the remote and then replicate it by using Arduino and RF Transmitter/Receiver. Having one remote to control all the different settings for the heating system seemed a bit complex (it must be very long and variable signal) for a first project, which led to this simpler use case to begin with, where the remote has a fixed RF code – the garage remote!

I know, I’m a little bit late in the game, though I still found it a bit challenging and wanted to share my solution. Every case is unique and there is no right or wrong solution nor there is an example out there that will work 100% for your idea or project without having to adjust bits and pieces.

Solution

Overall

I didn’t want to build a mobile app specifically for this idea, I could leverage the Salesforce1 App and build just a VisualForce page so that was an easy decision. The interesting part was how to connect the Arduino to the SF1 app…

I also didn’t want to open ports on my router at home, so it had to be some service that the Arduino can connect to, from behind the router. Ideally the Arduino would subscribe to a push notification channel (using some online service that supports web sockets) and the VF page will trigger an event on a click of a button on the same channel to which the Arduino is subscribed to receive notifications.

The ideal service would offer support for both, Arduino and JavaScript. After a bit of a research I discovered PubNub, who offered a free account and both have Arduino and JavaScript libraries. The reason I went with PubNub is because I found their JavaScript library easier to use, as well as better overall support (Stephen Blum instantly offered help on twitter).

Arduino

The most challenging part was to find the RF code from the garage remote using a RF receiver module. This 433.92MHz transmitter/receiver module from eBay ($1 including postage) proved to be sufficient.

DSC_8890

Basically what I had to do was to listen to the incoming signal from the original garage remote, capture the highs and lows and their frequencies. There are a few libraries that can do that (VirtualWireRCSwitch and others) but they all have their own patterns and ways of encoding data, so that wouldn’t cut the mustard.

The quickest (I’m not saying the cleanest) way was to listen on one of the analog ports on the Arduino and determine whether a high or low signal was received and measure the frequency. I found a really good tutorial on how to do that and also visually represent the signal so that it’s easier to replicate it later – credit goes to Arduino Basics. Once I found the code, it was easy to re-transmit. So this is what the final code on my Arduino looks like:

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

#define rfTransmitPin 10 // digital pin 10
#define ledPin 13
const int rearGarageCodeSize = 40; // code length for rear garage
const int frontGarageCodeSize = 38; // code length for front garage
int rearGarageCode[] = {1,4,1,2,1,1,4,3,1,2,1,1,1,1,1,5,1,1,4,1,1,1,1,1,2,1,1,1,4,1,1,2,1,4,2,5,4,1,2,3}; // rear garage code
int frontGarageCode[] = {3,4,2,1,4,1,1,1,2,4,2,1,1,1,1,4,1,1,1,2,2,4,1,1,1,5,2,5,1,1,4,1,4,2,5,1,3,2}; // front garage code
const int timeDelay = 440; // The variable used to calibrate the RF signal lengths.

char pubkey[] = "pub-c-XXXX-XXXX-XXXX-XXXX-XXXX";
char subkey[] = "sub-c-XXXX-XXXX-XXXX-XXXX-XXXX";
char channel[] = "homeAutomation";

IPAddress ip(192,168,1,123);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
PubSubClient *client;

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

void setup() 
{
	Serial.begin(9600);
	pinMode(13, OUTPUT);
	Serial.println(F("Starting ethernet..."));
	Ethernet.begin(mac, ip, gateway, gateway, subnet);
	Serial.println(Ethernet.localIP());
	delay(2000);
	Serial.println(F("Ready"));

	PubNub.begin(pubkey, subkey);
}

void loop()
{
		Ethernet.maintain();
		
		Serial.println(F("Waiting for a message (subscribe)"));
		
		client = PubNub.subscribe(channel, 30);
		
		if (!client) 
		{
			Serial.println(F("Subscription Error"));
			delay(1000);
			return;
		}
		
		Serial.println(F("Received: "));

		String msg;
		
		while (client->wait_for_data()) 
		{
			char c = client->read();
			msg += c;
		}

		action(msg);

		client->stop();
		Serial.println();
		
		delay(200);
}

void action(const String& eventName) 
{
	Serial.println(eventName);
	
	if (eventName == "[\"front\"]")
	{
		transmitCode("front"); // transmit the front garage door code
	}
	else if (eventName == "[\"rear\"]")
	{
		transmitCode("rear"); // transmit the the rear garage door code
	}

	delay(2000);
}

void transmitCode(const String& action)
{
	Serial.println(F("Tramsmitting Start"));
	
	// The LED will be turned on to create a visual signal transmission indicator.
	digitalWrite(ledPin, HIGH);

	//initialise the variables 
	int highLength = 0;
	int lowLength = 0;
		
	// Switch if there are more
	int codeSize = action == "front" ? frontGarageCodeSize : rearGarageCodeSize;
	int codeToTransmit[codeSize]; 
	
	for(int i = 0; i < codeSize; i++)
	{
		codeToTransmit[i] = action == "front" ? frontGarageCode[i] : rearGarageCode[i];
	}
	
	
	// Transmit 3 times in a row (The signal repeats, so we only keep the code for 1 sequence and repeat it X times)
	for(int j = 0; j < 3; j++)
	{
		for(int i = 0; i < codeSize; i++)
		{ 
			switch(codeToTransmit[i])
			{
				case 1:
					highLength = 2;
					lowLength = 2;
					break;
				case 2:
					highLength = 2;
					lowLength = 4;
					break;
				case 3:
					highLength = 2;
					lowLength = 81;
					break;
				case 4:
					highLength = 4;
					lowLength = 2;
					break;
				case 5:
					highLength = 4;
					lowLength = 4;
					break;
			}

			// Transmit a HIGH signal - the duration of transmission will be determined by the highLength and timeDelay variables 
			digitalWrite(rfTransmitPin, HIGH);
			delayMicroseconds(highLength * timeDelay);

			// Transmit a LOW signal - the duration of transmission will be determined by the lowLength and timeDelay variables 
			digitalWrite(rfTransmitPin, LOW);
			delayMicroseconds(lowLength * timeDelay);
		}
	}
	
	Serial.println(F("Tramsmitting End"));
	
	//Turn the LED off after the code has been transmitted.
	digitalWrite(ledPin, LOW); 
}

VisualForce

As I mentioned above, this was the easiest part of this mini-project. Just a page with a couple of buttons and a few lines of JavaScript code in order to trigger an event to the PubNub channel to which the Arduino is subscribed to and listening for events:

<apex:page showHeader="true" sidebar="true" controller="ArduinoToggleGarage">
	<script src="http://cdn.pubnub.com/pubnub.min.js"></script>
	<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" /> 

	<script type="text/javascript">
		// publish key and subscribe key are stored in the ArduinoToggleGarage controller
		var pubnub = PUBNUB.init({
			publish_key: '{!publishKey}',
			subscribe_key: '{!subscribeKey}',
			origin : 'pubsub.pubnub.com',
			ssl : true
		});

		function toggleGarage(whichGarage)
		{
			pubnub.publish({
				channel: "homeAutomation",
				message: whichGarage
			});
		}
	</script>
	<div class="btn-group-vertical btn-group-lg btn-block">
		<button type="button" class="btn btn-lg btn-default" onclick="toggleGarage('rear');">Toggle Rear Garage</button>
		<button type="button" class="btn btn-lg btn-default" onclick="toggleGarage('front');">Toggle Front Garage</button>
	</div>
</apex:page>

That’s it! Check out the video below for real-life demo:

My next step is to write a pebble app for the scenario above, as well as add functionality to arm/disarm the alarm on my house, so watch this space!

Source : http://www.pubnub.com/blog/triggering-actions-home-devices-arduino/

It’s time to crack open this blog with a post dedicated to my first home automation mini-project – opening and closing my garage doors by replacing the original RF (Radio Frequency) remote control with my mobile phone.

For this I’ve decided to use an Arduino with Ethernet Shield:

Arduino

Idea and Approach

DSC_9158

The idea initially came up when I wanted to replace my central heating system control with Nest, which would not work in my case because the only way to control the heating system is by a RF remote control.

Then I saw Bradley’s SwitchIt video which gave me another idea – to capture the RF signal from the remote and then replicate it by using Arduino and RF Transmitter/Receiver. Having one remote to control all the different settings for the heating system seemed a bit complex (it must be very long and variable signal) for a first project, which led to this simpler use case to begin with, where the remote has a fixed RF code – the garage remote!

I know, I’m a little bit late in the game, though I still found it a bit challenging and wanted to share my solution. Every case is unique and there is no right or wrong solution nor there is an example out there that will work 100% for your idea or project without having to adjust bits and pieces.

Solution

Overall

I didn’t want to build a mobile app specifically for this idea, I could leverage the Salesforce1 App and build just a VisualForce page so that was an easy decision. The interesting part was how to connect the Arduino to the SF1 app…

I also didn’t want to open ports on my router at home, so it had to be some service that the Arduino can connect to, from behind the router. Ideally the Arduino would subscribe to a push notification channel (using some online service that supports web sockets) and the VF page will trigger an event on a click of a button on the same channel to which the Arduino is subscribed to receive notifications.

The ideal service would offer support for both, Arduino and JavaScript. After a bit of a research I discovered PubNub, who offered a free account and both have Arduino and JavaScript libraries. The reason I went with PubNub is because I found their JavaScript library easier to use, as well as better overall support (Stephen Blum instantly offered help on twitter).

Arduino

The most challenging part was to find the RF code from the garage remote using a RF receiver module. This 433.92MHz transmitter/receiver module from eBay ($1 including postage) proved to be sufficient.

DSC_8890

Basically what I had to do was to listen to the incoming signal from the original garage remote, capture the highs and lows and their frequencies. There are a few libraries that can do that (VirtualWireRCSwitch and others) but they all have their own patterns and ways of encoding data, so that wouldn’t cut the mustard.

The quickest (I’m not saying the cleanest) way was to listen on one of the analog ports on the Arduino and determine whether a high or low signal was received and measure the frequency. I found a really good tutorial on how to do that and also visually represent the signal so that it’s easier to replicate it later – credit goes to Arduino Basics. Once I found the code, it was easy to re-transmit. So this is what the final code on my Arduino looks like:

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

#define rfTransmitPin 10 // digital pin 10
#define ledPin 13
const int rearGarageCodeSize = 40; // code length for rear garage
const int frontGarageCodeSize = 38; // code length for front garage
int rearGarageCode[] = {1,4,1,2,1,1,4,3,1,2,1,1,1,1,1,5,1,1,4,1,1,1,1,1,2,1,1,1,4,1,1,2,1,4,2,5,4,1,2,3}; // rear garage code
int frontGarageCode[] = {3,4,2,1,4,1,1,1,2,4,2,1,1,1,1,4,1,1,1,2,2,4,1,1,1,5,2,5,1,1,4,1,4,2,5,1,3,2}; // front garage code
const int timeDelay = 440; // The variable used to calibrate the RF signal lengths.

char pubkey[] = "pub-c-XXXX-XXXX-XXXX-XXXX-XXXX";
char subkey[] = "sub-c-XXXX-XXXX-XXXX-XXXX-XXXX";
char channel[] = "homeAutomation";

IPAddress ip(192,168,1,123);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
PubSubClient *client;

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

void setup() 
{
	Serial.begin(9600);
	pinMode(13, OUTPUT);
	Serial.println(F("Starting ethernet..."));
	Ethernet.begin(mac, ip, gateway, gateway, subnet);
	Serial.println(Ethernet.localIP());
	delay(2000);
	Serial.println(F("Ready"));

	PubNub.begin(pubkey, subkey);
}

void loop()
{
		Ethernet.maintain();
		
		Serial.println(F("Waiting for a message (subscribe)"));
		
		client = PubNub.subscribe(channel, 30);
		
		if (!client) 
		{
			Serial.println(F("Subscription Error"));
			delay(1000);
			return;
		}
		
		Serial.println(F("Received: "));

		String msg;
		
		while (client->wait_for_data()) 
		{
			char c = client->read();
			msg += c;
		}

		action(msg);

		client->stop();
		Serial.println();
		
		delay(200);
}

void action(const String& eventName) 
{
	Serial.println(eventName);
	
	if (eventName == "[\"front\"]")
	{
		transmitCode("front"); // transmit the front garage door code
	}
	else if (eventName == "[\"rear\"]")
	{
		transmitCode("rear"); // transmit the the rear garage door code
	}

	delay(2000);
}

void transmitCode(const String& action)
{
	Serial.println(F("Tramsmitting Start"));
	
	// The LED will be turned on to create a visual signal transmission indicator.
	digitalWrite(ledPin, HIGH);

	//initialise the variables 
	int highLength = 0;
	int lowLength = 0;
		
	// Switch if there are more
	int codeSize = action == "front" ? frontGarageCodeSize : rearGarageCodeSize;
	int codeToTransmit[codeSize]; 
	
	for(int i = 0; i < codeSize; i++)
	{
		codeToTransmit[i] = action == "front" ? frontGarageCode[i] : rearGarageCode[i];
	}
	
	
	// Transmit 3 times in a row (The signal repeats, so we only keep the code for 1 sequence and repeat it X times)
	for(int j = 0; j < 3; j++)
	{
		for(int i = 0; i < codeSize; i++)
		{ 
			switch(codeToTransmit[i])
			{
				case 1:
					highLength = 2;
					lowLength = 2;
					break;
				case 2:
					highLength = 2;
					lowLength = 4;
					break;
				case 3:
					highLength = 2;
					lowLength = 81;
					break;
				case 4:
					highLength = 4;
					lowLength = 2;
					break;
				case 5:
					highLength = 4;
					lowLength = 4;
					break;
			}

			// Transmit a HIGH signal - the duration of transmission will be determined by the highLength and timeDelay variables 
			digitalWrite(rfTransmitPin, HIGH);
			delayMicroseconds(highLength * timeDelay);

			// Transmit a LOW signal - the duration of transmission will be determined by the lowLength and timeDelay variables 
			digitalWrite(rfTransmitPin, LOW);
			delayMicroseconds(lowLength * timeDelay);
		}
	}
	
	Serial.println(F("Tramsmitting End"));
	
	//Turn the LED off after the code has been transmitted.
	digitalWrite(ledPin, LOW); 
}

VisualForce

As I mentioned above, this was the easiest part of this mini-project. Just a page with a couple of buttons and a few lines of JavaScript code in order to trigger an event to the PubNub channel to which the Arduino is subscribed to and listening for events:

<apex:page showHeader="true" sidebar="true" controller="ArduinoToggleGarage">
	<script src="http://cdn.pubnub.com/pubnub.min.js"></script>
	<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" /> 

	<script type="text/javascript">
		// publish key and subscribe key are stored in the ArduinoToggleGarage controller
		var pubnub = PUBNUB.init({
			publish_key: '{!publishKey}',
			subscribe_key: '{!subscribeKey}',
			origin : 'pubsub.pubnub.com',
			ssl : true
		});

		function toggleGarage(whichGarage)
		{
			pubnub.publish({
				channel: "homeAutomation",
				message: whichGarage
			});
		}
	</script>
	<div class="btn-group-vertical btn-group-lg btn-block">
		<button type="button" class="btn btn-lg btn-default" onclick="toggleGarage('rear');">Toggle Rear Garage</button>
		<button type="button" class="btn btn-lg btn-default" onclick="toggleGarage('front');">Toggle Front Garage</button>
	</div>
</apex:page>

That’s it! Check out the video below for real-life demo:

My next step is to write a pebble app for the scenario above, as well as add functionality to arm/disarm the alarm on my house, so watch this space!

Source : http://www.pubnub.com/blog/triggering-actions-home-devices-arduino/

COMMENTS

Please Login to comment
  Subscribe  
Notify of