App Note 1227 - Room Temperature Controller

From NearWiki
Jump to: navigation, search

This App Note introduces an experimental way to control the room temperature in a more efficient way.


Contents

Overview


In contrast with the traditional system where the temperature is controlled by a local device, this system works under the NearBus paradigm, this means that every sensed signal will be transmitted to the Cloud for its processing. No processing is accomplished in the remote device that works in a transparent way, controlling the sensors and actuators through the NearBios functions

The following picture shows an implementation of a simple controller (using only one temperature sensor) using two Arduino Ethernet boards.


Temperature controller.png


Note: It is important to remark that under the NearBus architecture it is possible to implement this solution using another microcontroller platform in a transparent way (for example a Wi-Fi board from OpenPicus in order to simplify the system deployment thanks to the Wi-Fi connectivity).



How does it work?


The system shown works as a traditional digital controller. The temperature sensor is sampled each 2000 ms for example (a configurable value) and feed it to a proportional controller (with hysteresis to avoid a flapping output). The controller compare the sensed signal with its internal setting and decides to turn on or off the electrical heater in order to maintain the room's temperature as near as possible to the configured value.

In this example we used two Arduino Ethernet boards (one for the temperature sensor an another for the power relay) in order to show you the way in which the NearBus system works (of course it can be implemented using only one Arduino Ethernet board).




Close Control Loop


As a traditional control system this example works as a close control loop. The temperature is sensed at sampling time (eg. each 2000 ms) and then compared against the setting reference value (eg. 22 deg. C ). This resulting signal is used to control the power relay output. As usual in this type of ON/OFF controllers, a hysteresis module is mandatory in order to avoid a flapping output (eg. 1 deg. C).

When the sensed signal drops below the bottom setting value in the hysteresis block (below 21,5 deg. C) , the output will be UP (turning ON the heater). In turn when the temperature rises over the top setting value in the hysteresis block ( over 22,5 deg. C) the output will go DOWN (turning OFF the heater).


Hysteresis window.png



System components


The system is composed by three main components:

  • The power switch: Arduino Ethernet board + Relay driver
  • The temperature sensor: Arduino Ethernet + temperature sensor ( LM35 lineal IC)
  • The controller: a software code written in PHP and running over an Internet Apache Web Server.

The controller code basically consist of a simple state machine implemented into the PHP code working as a callback function. This function will be called each time that the remote temperature sensor updates a new value in the NearBus system.



System Benefits


Although at first this temperature controller system looks like a Rube Goldberg machine [1], the NearBus system offers some improvements when it is configured in a more complex way:


- PIR Detector: One of the main features of a NearBus architecture is that it allows to integrate additional sensors and actuators in an easy way. Adding a PIR sensor for example will enable the system to turn off (or reduce the setting temperature) when there are no people in the room.

- Spot Temperature Control: Another interesting feature is the ability to deploy multiple Wi-Fi temperature sensors and Wi-Fi heater switches, allowing to define different spot zones and control them in a more energy-efficient way.


If you are interested in knowing more about this App Note please contact us at: info@nearbus.net



System Implementation


This JavaScript code (running from a browser) will allows you to implement a simple control loop to maintain the room temperature at the set point.

Required Componets
In order to implement this example under an Arduino + Grove platform you can use the following components:



JavaScript Code


Note: In order to run this code you should copy the following code into a file, save it with html extension and run it in your browser. Additionally you should replace the device_ID, user and password in this file.


<!DOCTYPE html>
<!-- ****************************************************************************************************************************** -->  
<!-- * NEARBUS JAVASCRIPT EXAMPLE - www.nearbus.net                                                                               * --> 
<!-- * Description: This example shows how to implement a closed loop temperature controller in JavaSript                         * --> 
<!-- * This code is intended to run on a browser to control a room temperature in a experimental way.                             * --> 
<!-- * The system is configured to work with a LM35 (lineal Temp Sensor (ºC)	                                                  * --> 
<!-- * Support: info@nearbus.net                                                                                                  * --> 
<!-- ****************************************************************************************************************************** -->  
<!-- * REVISION HISTORY                                                                                                           * -->
<!-- * v0.1 - 09-08-13 - Initial Release                                                                                          * --> 
<!-- * v0.2 - 24-10-13 - Upgrade to support nearapi_v05.js                                                                        * --> 
<!-- ****************************************************************************************************************************** --> 

<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="PAGE" ></script>
<script type='text/javascript' src='http://nearbus.net/downloads/js_apps/nearapi_v05.js'></script>


<script>
// +------------------------------------------------------------------------------+
// |                                 WARNING                                      |
// | Be careful to avoid run more than one scripts simultaneously !!!             |
// | Don't forget CLOSE the running script before start a new or modified script. |
// | The NearBus system can run multiple scripts but the system output will be    |
// | the mix of all running sessions.                                             |    
// +------------------------------------------------------------------------------+ 

// +--------------------------------------------------------------------+
// | To run this example you should replace the following parameters    |
// | device_id         Your device ID, or.. devices ID :)               |
// | user              Your NearBus Web user                            |
// | pass              Your NearBus Web password                        |
// +--------------------------------------------------------------------+


//////////////////////////////////
// MAIN CONFIGURATION
//////////////////////////////////
var switch_device_id = "NB100xxx";
var temp_device_id   = "NB100xxx";

var user  = "***";                 // Your NearBus Web user
var pass  = "***";                 // Your NearBus Web password

var LOOP_DELAY  = 2000;            // Main Loop Delay in ms
var WATCH_DOG   = 51;              // Watch Dog TTL

//////////////////////////////////
// Persistent Variables
//////////////////////////////////
var step_pointer = 5;
var reset_system;
var enable_system;
var ret = 0;
var my_watch_dog = WATCH_DOG;
var state_log = "Waiting";
var heater = 0;
var error_flag = "";

var temp_reference = 22.5;

var temperature = 0;

///////////////////////////////////
// Function: sysStop()
///////////////////////////////////        
function sysStop() {
    reset_system  = 1;
    enable_system = 0;
}

///////////////////////////////////
// Function: sysStart()
///////////////////////////////////    
function sysStart() {
    enable_system = 1;
    reset_system  = 0;
}

///////////////////////////////////
// Function: refreshDisplay()
///////////////////////////////////    
function refreshDisplay() {

    $('#field_1').text( "STEP = " + step_pointer.toString() );    
    $('#field_2').text( "STATE = " + state_log + error_flag );
    $('#field_3').text( "NearAPI Ret = " + state_log_api );
    $('#field_4').text( "Watch_Dog = " + my_watch_dog.toString() );
    $('#field_5').text( "Heater = " + heater );
    $('#field_6').text( "Room Temp = " + temperature );            
}
    
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: Main
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////    
$(document).ready( function ()
{

    state_log = "Starting...";
    
    setInterval( function()
    {    
    
        //**************************************************
        // WATCH DOG CONTROL
        //**************************************************
        my_watch_dog--;
        if ( my_watch_dog <= 0 )    {
            my_watch_dog = WATCH_DOG;
            ResetNearAPIjs();
            step_pointer = 5;
        }

        //**************************************************
        // ERROR CHECK
        //**************************************************
        if ( ret == "ERROR" )    {
            error_flag = " - SYSTEM ERROR";
            ResetNearAPIjs();
            step_pointer = 5;
        }

        //**************************************************
        // DEVICE DOWN
        //**************************************************
        if ( ret == "DOWN" )    {
            error_flag = " - SYSTEM DOWN";
            ResetNearAPIjs();
            step_pointer = 5;
        }
        
        /////////////////////////////////////////////////////////////////////
        // STATE MACHINE
        /////////////////////////////////////////////////////////////////////
        if( reset_system == 1 ) {
            reset_system = 0;
            ResetNearAPIjs();
            step_pointer = 5;
        }

        refreshDisplay();
        
        switch ( step_pointer )
        {
                
            /////////////////////////////////////////////////////////////////////
            // [STEP 5] - SYSTEM RESET - TURN OFF HEATER
            /////////////////////////////////////////////////////////////////////
            case 5:
                state_log = "Resetting System... ( please wait )";
                refreshDisplay();
                
                ret = NearAPIjs( "DIG_OUTPUT", switch_device_id, 0, 0 );
                if( ret == "DONE" ) {
                    my_watch_dog = WATCH_DOG;
                    step_pointer = 10;                
                }
                break            
                
                
            /////////////////////////////////////////////////////////////////////
            // [STEP 10] - SYSTEM OFF
            /////////////////////////////////////////////////////////////////////
            case 10:
                state_log = "System READY";
                refreshDisplay();
                
                heater = "OFF";    
                my_watch_dog = WATCH_DOG;
                
                if( enable_system == 1 ) {        
                    enable_system = 0;
                    error_flag = "";
                    step_pointer = 20;
                }
                break;                        

                
            /////////////////////////////////////////////////////////////////////
            // [STEP 20] - SENSING TEMPERATURE
            /////////////////////////////////////////////////////////////////////    
            case 20:
                state_log = "Sensing Temperature...";                    
                refreshDisplay();    
                ret = NearAPIjs( "ADC_INPUT", temp_device_id , 0, 0 );
                if( ret != "WAIT" ) {
                    my_watch_dog = WATCH_DOG;

                    temp_reference =  parseFloat( document.getElementById("f_temperature").value );
                    
                    temperature = (ret * 2) / 10;                                  // LM35 10mV/ºC
                    if( temperature > ( temp_reference + 0.5) ) {
                        heater = 0;
                    }
                    else if ( temperature < (temp_reference - 0.5) ) {
                        heater = 1;
                    }
                    step_pointer = 30;
                }
                break;


            /////////////////////////////////////////////////////////////////////
            // [STEP 30] - TURN OFF HEATER 
            /////////////////////////////////////////////////////////////////////
            case 30:
                state_log = "Controlling Heater";                
                refreshDisplay();
                ret = NearAPIjs( "DIG_OUTPUT", switch_device_id , 0, heater );            
                if( ret == "DONE" )     {
                    my_watch_dog = WATCH_DOG;
                    service_run = "NO";
                    step_pointer = 20;
                }
                break;    
        }            
        
    }, LOOP_DELAY );    
} );

</script>

</head>
<body>

<!-- ****************************************************************************************************************************** -->  
<!-- *  HTML CODE                                                                                                                  * -->     
<!-- ****************************************************************************************************************************** --> 

<p><b> NEARBUS - ROOM TEMP. CONTROLLER </b></p>

<div id="field_1">Field_1</div>
<br />
<div id="field_2">Field_2</div>
<br />
<div id="field_3">Field_3</div>
<br />
<div id="field_4">Field_4</div>
<br />
<div id="field_5">Field_5</div>
<br />
<div id="field_6">Field_6</div>
<br />
<select  id="f_temperature">
<option> 22.0 </option>
<option selected> 22.5 </option>
<option> 23.0 </option>
<option> 23.5 </option>
<option> 24.0 </option>
<option> 24.5 </option>
<option> 25.0 </option>
<option> 25.5 </option>
<option> 26.0 </option>
<option> 27.0 </option>
<option> 28.0 </option>
<option> 29.0 </option>
</select>
<br />
<br />
<button onclick="sysStart()">START</button>
<br />
<br />
<button onclick="sysStop()">STOP</button>

</body>
</html>