Menu

Easy modular home automation

Attention

This solution is given as it is, and I can/will not guarantee that it can not be hacked or abused by others. So use your common sense if you put it into use, and let me know if you got some security/stability improvements. 🙂

What is this?

This is a cheap way of making some simple home automation, so far this system can only switch relays/pins on and off, and control PWM channels.

What does make this system so genious?

It uses cheap RF modules (4-6£ per set)

It can use all arduino versions as receivers (sender does require a version that can interface with Ethernet)

It can use cheap pre-assembled relay boards that can handle 230V and are op-to isolated from the controller

It is very easy to add additional receivers to the system

It is easy to have something like PHP interface with it to control stuff from a website

It is free and opensource 🙂

How to use it?

I got the sender and receiver ready, how to I use it?

First you need the sender’s ip.

To turn a pin on, you then call http://sender-ip/_ident-pin-status_

ident is the ident in the receiver you gave it in the top of the sketch

pin is the pin number on the arduino you want to turn on

status is what you want that pin to do, 1 turns a digital pin HIGH and 0 turns it LOW

But I want to use it to control something that just needs an inpulse!

To do that, you add one extra value to it, so it will be http://sender-ip/_ident-pin-pulses-delay_

ident is the ident in the receiver you gave it in the top of the sketch

pulses is how many times you want it to pulse that pin

delay is how long a delay you want between changing the pin

Sender

When calling http://192.168.1.88/_gar-12-0_ this will send gar-12-0 over RF. “gar” is the identifier for the receiver, 12 is the pin number, and 0 is the value the pin will be set to.

Receiver

This expects a message from the sender like identifier–pin-value, and will then set the defined pin to the defined value

/*
Home Automation Node by bld @ http://captain-slow.dk/
Version 0.2
*/
static String ident = "gar"; // Identification for this device
#include <VirtualWire.h>
#define rxPin 7
#define DEBUG 2 //Define to include serial communication
const int ledPin = 13; // The number of the LED pin, LED used to indicate we got a message
long onMillis = 0; // Will store last time LED was updated
#define startPin 3 // The first pin we connect a relay to
#define stopPin 6 // The last pin we connect a relay to
int stepsLeft[(stopPin-startPin)+1]; //Array to store how many times it should flash the pin
int stepDelay[(stopPin-startPin)+1]; //Array to store how long a delay there should be between the pin state changing
unsigned long lastStep[(stopPin-startPin)+1]; //Array to store when the pin was changed last
void rf_start()
{
//Set-up the RF receiver
vw_rx_stop(); // Stop it in case it is already running
vw_set_rx_pin(rxPin); // We will be receiving on pin 2 ie the RX pin from the module connects to this pin.
vw_setup(1000); // Bits per sec
vw_rx_start(); // Start the receiver
}
void setup()
{
#ifdef DEBUG
Serial.begin(9600);
#endif
pinMode(ledPin, OUTPUT);
//Set-up the RF receiver
rf_start();
for (int i = startPin; i <= stopPin; i++) // We need to set the pins that control the relays to OUTPUT
{
#ifdef DEBUG
Serial.print("Setting pinMode on pin: ");
Serial.println(i);
#endif
pinMode(i, OUTPUT);
digitalWrite(i, LOW); // We set the pin to LOW because pulling it HIGH will turn the relay on
}
#ifdef DEBUG
Serial.println("Ready to receive!");
#endif
}
void loop()
{
for (int i = 0; i <= stopPin-startPin; i++) // Run through the arrays to see if any pin should be changed
{
if (stepsLeft[i] > 0) // Do we have to do any steps on this pin?
{
if (millis() - lastStep[i] > stepDelay[i]) // Is it time to change the pin?
{
#ifdef DEBUG && DEBUG == 2
Serial.print("Pin: ");
Serial.print(stopPin-i);
Serial.print(" - stepsLeft: ");
Serial.print(stepsLeft[i]);
Serial.print(" - lastStep: ");
Serial.print(lastStep[i]);
Serial.print(" - stepDelay: ");
Serial.print(stepDelay[i]);
Serial.print(" - arrayPos: ");
Serial.print(i);
Serial.print(" - digitalRead: ");
Serial.println(!digitalRead(stopPin-i));
#endif
lastStep[i] = millis(); // Set when we last changed the pin
digitalWrite(stopPin-i, !digitalRead(stopPin-i)); // Set the pin to the opposite of what it just was
stepsLeft[i]--; // Remove one step
if (stepsLeft[i] < 1) digitalWrite(stopPin-i, LOW); // Set the pin to LOW, just to be sure.
}
}
}
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Check to see if anything has been received
{
String message((char *)buf); //Store the message received
#ifdef DEBUG && DEBUG == 2
Serial.print("RF incomming: ");
Serial.print(message);
#endif
if (message.substring(0,ident.length()) == ident) // Check if this message was for us
{
digitalWrite(ledPin, HIGH); // Turn led on to indicate we received something, and is going to look more at it
onMillis = millis(); // Save when led was turned on so we remember to turn it off again later
message = message.substring(ident.length()+1); // Remove the identifier from the message
int startCommand = message.indexOf('-'); // Find where we split pin number from pin status
String getPinNum = message.substring(0, startCommand); // Save a String with the pin number
String getPinSet = message.substring(startCommand + 1, message.length()); // Save a String with the value we are going to send to the pin
int delayCommand = message.indexOf('-', startCommand + 2); // Check if there is added a delay for the pin to be turned off again
char tempNum[10]; //Char to hold the message before converting it to an integer
int pinDelay = 0;
if (delayCommand > 0)
{
getPinSet = message.substring(startCommand + 1, delayCommand); // Save a String with the value we are going to flash the pin
String getPinDel = message.substring(delayCommand + 1, message.length()); // Save a String with the value we are going to delay the flash
tempNum[getPinDel.length() + 1]; // Temp save pin value
getPinDel.toCharArray(tempNum, 10);
pinDelay = atoi(tempNum); // Convert char array to an integer
}
else
{
pinDelay = 0;
}
tempNum[getPinNum.length() + 1]; // Temp save pin number
getPinNum.toCharArray(tempNum, 10);
int pinNum = atoi(tempNum); // Convert char array to an integer
tempNum[getPinSet.length() + 1]; // Temp save pin value
getPinSet.toCharArray(tempNum, 10);
int pinSet = atoi(tempNum); // Convert char array to an integer
#ifdef DEBUG
Serial.print("Pin num: ");
Serial.print(pinNum);
#endif
if (pinNum != rxPin) //Make sure it won't be possible to accidently diable communication
{
if (pinDelay > 0)
{
#ifdef DEBUG
Serial.print(" - Cycles: ");
Serial.print(pinSet);
Serial.print(" - Delay: ");
Serial.println(pinDelay);
#endif
stepsLeft[stopPin-pinNum] = pinSet*2; //Store how many times the pin should flash, it is changing state for each pass, so it should be done twice for 1 on/off cycle
stepDelay[stopPin-pinNum] = pinDelay; //Store the delay between pin changes
lastStep[stopPin-pinNum] = 0; //Set the last time it changed to 0 so it will happen on next loop
}
else
{
#ifdef DEBUG
Serial.print(" - Pin status: ");
Serial.println(pinSet);
#endif
digitalWrite(pinNum, pinSet); // Set the pin defined earlier
}
}
#ifdef DEBUG
else
{
Serial.println(" - WARNING: Can not change RX pin!");
}
#endif
}
}
buf[buflen] = '\0'; //Empty String message again
if (millis() - onMillis > 250 && onMillis > 0) // Check if it is time to turn the led off
{
onMillis = 0;
digitalWrite(ledPin, LOW);
}
}

To add multiple receivers, you simply just change ident, and it is then possible to send a message to each controller.