This article proposes a method for controlling your device from a web page or automatizing openings or closures of all your VELUX roller shutters in your home.
Hardware list
Here is the hardware list for this project :
Raspberry Pi board
The Raspberry Pi is a famous credit-card-sized single-board computer than can be purchased for around 30$ (www.raspberrypi.org).
You will also need an Ethernet cable (or WiFi USB dongle) to connect your Raspberry Pi to your LAN.
Velux IO-HomeControl remote controller
This remote controller is required to transmit OPEN / CLOSE commands to IO-HomeControl devices.
You can buy this type of spare remote controller on Ebay market for around 10 $.
Using dedicated procedure, you can easily control several roller-shutters using this single remote controller.
In order to connect this remote controller to your Raspberry Pi and Relay board, you will have to solder some wires:
- 3 wires (grey) for OPEN / CLOSE / STOP buttons. These wires will be connected to 3 independant relay switches. Each command is triggered by a Low state (Ground) pulse (pulse duration is about 500 ms).
- 2 Power wires (red and black). These wires will be connected to +3.3v and GND pins of Raspberry Pi GPIO connector.
Relay-Switch board
Relays will be controlled by RaspBerry Pi GPIO and will be connected to the remote controller OPEN/CLOSE/STOP switches. Only three relays are required for this project.
Wiring overview
GPIO mapping :
Software
Raspbian
Your Raspberry needs to run a Linux systems including all drivers for GPIO an network interface (WiFi or Ethernet).
The latest version of Raspbian Linux distribution is definitely a good choice (www.raspbian.org).
WebIOPi framework
The software part of this project is based on WebIOPi framework (https://code.google.com/p/webiopi/).
This framework is written in Python and also includes javascript/HTML library for designing web User Interfaces.
Please refer to WebIOPi website for installation and Python/javascript script / source customization instructions.
Web UI Snapshots
Once WebIOPi service is correctly started on your Raspbery
This Web UI is accessible on the following :
Velux UP time : Set opening hours
Velux DOWN time : Set closure hour
Automatic UP/DOWN mode : Indicates AUTO mode state
Set Hours : Latch Opening/Closure hours defined in upper fields.
Set mode : Toggles AUTO mode (0=OFF / 1=ON)
Up : Asynchronous OPEN command
Stop : Asynchronous STOP command
Down : Asynchronous DOWN command
Customized source code
Python server script :
downloadimport webiopi
import datetime
GPIO = webiopi.GPIO
VELUX_UP = 17 # GPIO pin using BCM numbering
VELUX_DOWN = 18 # GPIO pin using BCM numbering
VELUX_STOP = 27 # GPIO pin using BCM numbering
VELUX_STATE = 0 # DOWN
AUTO_MODE = 1
HOUR_UP = 9 # Turn Velux UP at
HOUR_DOWN = 19 # Turn Velux Down at
# setup function is automatically called at WebIOPi startup
def setup():
global VELUX_STATE, AUTO_MODE
# set the GPIO used for VELUX command to output
GPIO.setFunction(VELUX_UP, GPIO.OUT)
GPIO.setFunction(VELUX_DOWN, GPIO.OUT)
# STOP function not used at this time
GPIO.setFunction(VELUX_STOP, GPIO.OUT)
GPIO.digitalWrite(VELUX_STOP, GPIO.LOW)
# retrieve current datetime
now = datetime.datetime.now()
if (AUTO_MODE==1):
# test time
if ((now.hour >= HOUR_UP) and (now.hour < HOUR_DOWN)):
GPIO.digitalWrite(VELUX_UP, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
VELUX_STATE = 1
else:
GPIO.digitalWrite(VELUX_DOWN, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
VELUX_STATE = 0
# loop function is repeatedly called by WebIOPi
def loop():
global VELUX_STATE, AUTO_MODE
# retrieve current datetime
now = datetime.datetime.now()
if (AUTO_MODE==1):
# toggle VELUX UP all days at the correct time
if ((now.hour == HOUR_UP) and (now.minute == 0) and (VELUX_STATE == 0)):
GPIO.digitalWrite(VELUX_UP, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
VELUX_STATE = 1 #UP
# toggle VELUX DOWN all days at the correct time
if ((now.hour == HOUR_DOWN) and (now.minute == 0) and (VELUX_STATE == 1)):
GPIO.digitalWrite(VELUX_DOWN, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
VELUX_STATE = 0 #DOWN
# gives CPU some time before looping again
webiopi.sleep(1)
# destroy function is called at WebIOPi shutdown
def destroy():
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
GPIO.digitalWrite(VELUX_STOP, GPIO.LOW)
@webiopi.macro
def getHours():
return "%d;%d" % (HOUR_UP, HOUR_DOWN)
@webiopi.macro
def setHours(on, off):
global HOUR_UP, HOUR_DOWN
HOUR_UP = int(on)
HOUR_DOWN = int(off)
return getHours()
@webiopi.macro
def getAutoMode():
return "%d" % (AUTO_MODE)
@webiopi.macro
def setAutoMode():
global AUTO_MODE
if AUTO_MODE:
AUTO_MODE=0
else:
AUTO_MODE=1
return getAutoMode()
def destroy():
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
GPIO.digitalWrite(VELUX_STOP, GPIO.LOW)
@webiopi.macro
def getHours():
return "%d;%d" % (HOUR_UP, HOUR_DOWN)
@webiopi.macro
def setHours(on, off):
global HOUR_UP, HOUR_DOWN
HOUR_UP = int(on)
HOUR_DOWN = int(off)
return getHours()
@webiopi.macro
def getAutoMode():
return "%d" % (AUTO_MODE)
@webiopi.macro
def setAutoMode():
global AUTO_MODE
if AUTO_MODE:
AUTO_MODE=0
else:
AUTO_MODE=1
return getAutoMode()
HTML code for Web UI :
download<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>VELUX Control</title>
<script type="text/javascript" src="/webiopi.js"></script>
<script type="text/javascript">
webiopi().ready(function() {
// Following function will process data received from set/getHours macro.
var updateHours = function(macro, args, response) {
var hours = response.split(";");
// Following lines use jQuery functions
$("#inputOn").val(hours[0]);
$("#inputOff").val(hours[1]);
}
// Following function will process data received from getAutoMode macro.
var updateAutoMode = function(macro, args, response) {
var tmp = response.split(";");
// Following lines use jQuery functions
$("#AutoMode").val(tmp[0]);
}
// Immediately call getHours macro to update the UI with current values
webiopi().callMacro("getHours", [], updateHours);
// Immediately call getAutoMode macro to update the UI with current values
webiopi().callMacro("getAutoMode", [], updateAutoMode);
// Create a button to call setLightHours macro
var sendButton = webiopi().createButton("sendButton", "Set Hours", function() {
// Arguments sent to the macro
var hours = [$("#inputOn").val(), $("#inputOff").val()];
// Call the macro
webiopi().callMacro("setHours", hours, updateHours);
// Append the button to the controls box using a jQuery function
$("#controls").append(sendButton);
// Create a button to call setAutoMode macro
var automodeButton = webiopi().createButton("automodeButton", "Set Mode", function() {
// Call the macro
webiopi().callMacro("setAutoMode",[], updateAutoMode);
});
// Append the button to the controls box using a jQuery function
$("#controls").append(automodeButton);
// create a "UP" button that output a single pulse on GPIO 17
//var button_up = webiopi().createPulseButton("up", "Up", 17);
var button_up = webiopi().createSequenceButton("up","Up",17,100,"011110");
$("#controls").append(button_up); // append button to content div
// create a "STOP" button that output a single pulse on GPIO 27
var button_stop = webiopi().createSequenceButton("stop","Stop",27,200,"011110");
$("#controls").append(button_stop); // append button to content div
// create a "DOWN" button that output a single pulse on GPIO 18
//var button_down = webiopi().createPulseButton("down", "Down", 18);
var button_down = webiopi().createSequenceButton("down","Down",18,100,"011110");
$("#controls").append(button_down); // append button to content div
// Refresh GPIO buttons
// pass true to refresh repeatedly of false to refresh once
webiopi().refreshGPIO(true);
});
</script>
<style type="text/css">
button {
display: block;
margin: 5px 5px 5px 5px;
width: 160px;
height: 45px;
font-size: 24pt;
font-weight: bold;
color: white;
}
</style>
</head>
<body>
<div align="center">
Velux UP time (hour):<input type="text" id="inputOn" /><br/>
Velux DOWN time (hour): <input type="text" id="inputOff" /><br/>
Automatic UP/DOWN mode: <input type="text" id="AutoMode" /><br/>
<HR>
<div id="controls"></div>
</div>
</body>
</html>