Done

Dependencies:   C12832_lcd EthernetInterface LM75B MMA7660 NTPClient libxively mbed-rtos mbed

main.cpp

Committer:
bhakti08
Date:
2014-06-03
Revision:
0:8f6eb1fedc58

File content as of revision 0:8f6eb1fedc58:

/****************************************************************************************/
/*                               INTERNET OF THINGS ASSIGNMENT 7                        */
/*This assignment implements a thermostat which turns ON/OFF depending on the set and   */
/*current temperature. The thermostat can be turned ON/OFF by following ways:           */
/*                    1. Joustick up button on the application board.                   */
/*                    2. Depending on if there is movement or not                       */
/*                    3. Remotely through xively                                        */
/*The program also updates following things on xively:                                  */
/*                    1. Current Temperature                                            */
/*                    2. Movement detection                                             */
/****************************************************************************************/

#include "mbed.h"
#include "rtos.h"
#include "C12832_lcd.h"
#include "EthernetInterface.h"

#include "xively.h"
#include "xi_err.h"
#include "LM75B.h"
#include "DebouncedIn.h"
#include "MMA7660.h"

#define XI_FEED_ID 1443794017 // set Xively Feed ID (numerical, no quoutes)
#define XI_API_KEY "iydtzKtHKHNpc4mQqq5Quv8jhi5nMwg6EKXSN6UkspZcXTrI" 
                                 // set Xively API key (double-quoted string)

#define SEC 1000                //macro for no. of msec in sec
#define MIN 60*SEC              //macro for no. of msec in min
#define hys 3
#define TIME 20            //Time after which system should turn OFF if
                           //no movement detected
#define OFF 0
#define ON 1

Mutex LCD;
C12832_LCD lcd;
Serial pc (USBTX,USBRX);
//LM75B current(p28,p27);
MMA7660 MMA(p28,p27);

BusOut move(p23,p24,p25);

//System ON/OFF
BusIn heat_on (p16,p13); 
                                      
//Increase Temperature
DebouncedIn temp_up (p15); 

//Decrease Temperature                                    
DebouncedIn temp_down (p12);                                   

//System ON/OFF LED
DigitalOut thermostat (LED1);

//Heater ON/OFF LED. This can be furthur connected to the relay                                  
DigitalOut heater (LED2);                                  


int temp = 10;
bool status = 0;
bool remote_state = ON;

void update_lcd(void const *args);       //Thread 1
void Thermostat_logic (void const *args);      //Thread 2
void check_movement(void const *args);      //Thread 3

bool no_move;
float acc_x = MMA.x();
float acc_y = MMA.y();
float acc_z = MMA.z();
float acc_x_old,acc_y_old,acc_z_old;

/****************************************************************************************/
/*Thread update_lcd: This thread is used to update the lcd. The LCD will dispaly current*/
/*time, Set temperature and the actual temperature. If the system is OFF lcd will show  */
/*current time and message 'System OFF'                                                 */
/****************************************************************************************/
void update_lcd(void const *args)
{
    set_time(1391739990); 
    while (true) {
    time_t seconds = time(NULL);
    LCD.lock();
    lcd.locate(0,0);
    lcd.printf("%s",ctime(&seconds));
    lcd.locate(0,10);
    if (status) {                                          
            lcd.printf("Current: %.2f",current.read());
            lcd.locate(1,20);
            lcd.printf("Set: %d",temp);
        } else {   
            lcd.cls();               
            lcd.locate(0,0);
                        lcd.printf("%s",ctime(&seconds));               
            lcd.locate(0,10);                   
            lcd.printf("System OFF");
        }     
    LCD.unlock();
    Thread::wait(200);     //wait for 200 msec
    }
}
/****************************************************************************************/


/****************************************************************************************/
/*Thread: thermostat logic: This thread implements the logic of the thermostat. It turns*/
/*ON/OFF the thermostat depending on temperature, movement and the web control. It also */
/*allows the user to set the temperature from the push button switches. The setting of  */
/*temperature can also be done remotely through xively. Currently the program just      */
/*controls turning ON/OFF the system remotely.                                          */
/****************************************************************************************/
void Thermostat_logic(void const *args)
{
    while (true) {
        if (heat_on == 0x2 ||  (/*!no_move ||*/ remote_state == ON))
        {
            thermostat = 1;                                    
            status = 1;                                        
        } else if (heat_on == 0x1 || /*no_move ||*/ remote_state == OFF) {                                                 
            thermostat = 0;                                    
            heater = 0;                                       
            status = 0;                                       
        }
        
        /*If the joystick is pushed upwards increase set temperature by 2
        And print the set temperature on LCD.*/
        if (temp_up.rising()) {                                
            temp = temp + 0x2;                                                      
        }
        
        /*else if the joystick is pushed downwards decrease set temperature by 2
        And print the set temperature on LCD.*/ 
        
        else if (temp_down.rising()) {                       
            temp = temp - 0x2;                                 
        }

        //Comparison logic and turn Heater ON/OFF
        if ((temp > (current.read()+ hys)) & thermostat == 1)
            heater =  1;
        else if ((temp < (current.read()- hys)) | thermostat == 0)
            heater = 0;
            
        if (acc_x_old != MMA.x() || acc_y_old != MMA.y() || acc_z_old != MMA.x())
       {
           no_move = 0;
       }
         
        Thread::wait(100);      //wait for 100 msec
    }
}
/****************************************************************************************/


/****************************************************************************************/
/*Thread check movement: This thread detects if there is movement nearby the thermostat.*/
/*If there is no movement this thread sets a variable called no_move which is furthur   */
/*used to turn ON/OFF the system. Logic implemented for movement detection is as follows*/
/*This thread is executed once every minute. Every time this thread is executed it      */
/*compares the accelerometer reading with its previous value. If the reading is same    */
/*(no movement detected) it increments a counter. When this counter reaches 20 (which   */
/*means there is no movement for 20 mins) it sets the variable no_move to turn OFF the  */
/*system. When a different accelerometer value is detected(movement present) it resets  */
/*the variable which will in turn turn the system ON.                                   */
/****************************************************************************************/

void check_movement(void const *args)
{
    static int move_cntr = 0;
    while (true) {
    acc_x_old = acc_x;
    acc_y_old = acc_y;
    acc_z_old = acc_z;
    acc_x = MMA.x();
    acc_y = MMA.y();
    acc_z = MMA.z();
    if (acc_x_old == acc_x && acc_y_old == acc_y && acc_z_old == acc_z)
    {
        move_cntr++;
        pc.printf("Value of move_cntr = %d\r\n",move_cntr);
        move = 011;
    }
    else {
        move_cntr = 0;
        pc.printf("Move_cntr reset\r\n");}
         //If the Accelerometer value remains constant for 20 mins no movement detected
    if (move_cntr >= TIME)   
        no_move = 1;
    else
        no_move = 0;
    Thread::wait(1*MIN);
    } 
}
/****************************************************************************************/


/****************************************************************************************/
/*Thread main: This is the main thread which instantiates all other threads. This thread*/
/*is also used to communicate with xively. It updates xively with the current temoerature*/
/*and the movement status. It also reads the status command from xively and turns ON/OFF */
/*the system accordingly. This thread is also used for setting up ethernet connection    */
/****************************************************************************************/

int main() {
    
    Thread lcd_display(update_lcd,NULL,  osPriorityAboveNormal);
    Thread thermostat_thread(Thermostat_logic,NULL,  osPriorityAboveNormal);
    Thread accel_thread(check_movement,NULL,osPriorityAboveNormal);
    
    EthernetInterface eth;
    
    int s = eth.init(); //Use DHCP
    if( s != NULL )
    {
        pc.printf( "Could not initialise. Will halt!\n" );        
        exit( 0 );
    }    
        
    s = eth.connect();
    
    if( s != NULL )
    {
        pc.printf( "Could not connect. Will halt!\n" );
        exit( 0 );
    }
    else 
    {
        pc.printf( "IP: %s\n", eth.getIPAddress() );    
    }
        
        xi_feed_t feed;
        memset( &feed, NULL, sizeof( xi_feed_t ) );
    
        feed.feed_id = XI_FEED_ID;
        feed.datastream_count = 4;
    
        /*Data stream for temperature*/
        feed.datastreams[0].datapoint_count = 1;
        xi_datastream_t* temperature_datastream = &feed.datastreams[0];
        strcpy( temperature_datastream->datastream_id, "Temperature" );
        xi_datapoint_t* current_temperature = &temperature_datastream->datapoints[0];
        
        /*Data stream for movement*/
        feed.datastreams[1].datapoint_count = 1;
        xi_datastream_t* orientation_datastream = &feed.datastreams[1];
        strcpy( orientation_datastream->datastream_id, "Movement" );
        xi_datapoint_t* current_orientation = &orientation_datastream->datapoints[0];

        /*Data stream for status control (Input datastream)*/
        feed.datastreams[2].datapoint_count = 1;
        xi_datastream_t* control_datastream = &feed.datastreams[2];
        strcpy( control_datastream->datastream_id, "System" );
        xi_datapoint_t* current_state = &control_datastream->datapoints[0];
                       
    // create the cosm library context
        xi_context_t* xi_context
            = xi_create_context( XI_HTTP, XI_API_KEY, feed.feed_id );
        if( xi_context == NULL )
        {
            pc.printf("Error in Xi_Context\r\n");
            exit (0);
        }

        while (true) {
            xi_set_value_f32( current_temperature, current.read() ); 
            if (no_move == 1) 
            {
                xi_set_value_str( current_orientation, "No movement" );
            }
            else
            {
                xi_set_value_str( current_orientation, "Movement Present" );
            }
            // read remote value
            xi_datastream_get( xi_context, feed.feed_id
                    , control_datastream->datastream_id
                    , control_datastream->datapoints);      
                        current_state = &control_datastream->datapoints[0];   
            int system_status = current_state->value.i32_value;
            if (system_status == 0)
            {
                remote_state = OFF;
            }
            else
            {
                remote_state = ON;
            }
        
            pc.printf("Status value is %d\r\n",system_status); 
            pc.printf("Done\r\n"); 
            xi_feed_update( xi_context, &feed );
            Thread::wait(15*SEC);
        }
}
/****************************************************************************************/