Done

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /****************************************************************************************/
00002 /*                               INTERNET OF THINGS ASSIGNMENT 7                        */
00003 /*This assignment implements a thermostat which turns ON/OFF depending on the set and   */
00004 /*current temperature. The thermostat can be turned ON/OFF by following ways:           */
00005 /*                    1. Joustick up button on the application board.                   */
00006 /*                    2. Depending on if there is movement or not                       */
00007 /*                    3. Remotely through xively                                        */
00008 /*The program also updates following things on xively:                                  */
00009 /*                    1. Current Temperature                                            */
00010 /*                    2. Movement detection                                             */
00011 /****************************************************************************************/
00012 
00013 #include "mbed.h"
00014 #include "rtos.h"
00015 #include "C12832_lcd.h"
00016 #include "EthernetInterface.h"
00017 
00018 #include "xively.h"
00019 #include "xi_err.h"
00020 #include "LM75B.h"
00021 #include "DebouncedIn.h"
00022 #include "MMA7660.h"
00023 
00024 #define XI_FEED_ID 1443794017 // set Xively Feed ID (numerical, no quoutes)
00025 #define XI_API_KEY "iydtzKtHKHNpc4mQqq5Quv8jhi5nMwg6EKXSN6UkspZcXTrI" 
00026                                  // set Xively API key (double-quoted string)
00027 
00028 #define SEC 1000                //macro for no. of msec in sec
00029 #define MIN 60*SEC              //macro for no. of msec in min
00030 #define hys 3
00031 #define TIME 20            //Time after which system should turn OFF if
00032                            //no movement detected
00033 #define OFF 0
00034 #define ON 1
00035 
00036 Mutex LCD;
00037 C12832_LCD lcd;
00038 Serial pc (USBTX,USBRX);
00039 //LM75B current(p28,p27);
00040 MMA7660 MMA(p28,p27);
00041 
00042 BusOut move(p23,p24,p25);
00043 
00044 //System ON/OFF
00045 BusIn heat_on (p16,p13); 
00046                                       
00047 //Increase Temperature
00048 DebouncedIn temp_up (p15); 
00049 
00050 //Decrease Temperature                                    
00051 DebouncedIn temp_down (p12);                                   
00052 
00053 //System ON/OFF LED
00054 DigitalOut thermostat (LED1);
00055 
00056 //Heater ON/OFF LED. This can be furthur connected to the relay                                  
00057 DigitalOut heater (LED2);                                  
00058 
00059 
00060 int temp = 10;
00061 bool status = 0;
00062 bool remote_state = ON;
00063 
00064 void update_lcd(void const *args);       //Thread 1
00065 void Thermostat_logic (void const *args);      //Thread 2
00066 void check_movement(void const *args);      //Thread 3
00067 
00068 bool no_move;
00069 float acc_x = MMA.x();
00070 float acc_y = MMA.y();
00071 float acc_z = MMA.z();
00072 float acc_x_old,acc_y_old,acc_z_old;
00073 
00074 /****************************************************************************************/
00075 /*Thread update_lcd: This thread is used to update the lcd. The LCD will dispaly current*/
00076 /*time, Set temperature and the actual temperature. If the system is OFF lcd will show  */
00077 /*current time and message 'System OFF'                                                 */
00078 /****************************************************************************************/
00079 void update_lcd(void const *args)
00080 {
00081     set_time(1391739990); 
00082     while (true) {
00083     time_t seconds = time(NULL);
00084     LCD.lock();
00085     lcd.locate(0,0);
00086     lcd.printf("%s",ctime(&seconds));
00087     lcd.locate(0,10);
00088     if (status) {                                          
00089             lcd.printf("Current: %.2f",current.read());
00090             lcd.locate(1,20);
00091             lcd.printf("Set: %d",temp);
00092         } else {   
00093             lcd.cls();               
00094             lcd.locate(0,0);
00095                         lcd.printf("%s",ctime(&seconds));               
00096             lcd.locate(0,10);                   
00097             lcd.printf("System OFF");
00098         }     
00099     LCD.unlock();
00100     Thread::wait(200);     //wait for 200 msec
00101     }
00102 }
00103 /****************************************************************************************/
00104 
00105 
00106 /****************************************************************************************/
00107 /*Thread: thermostat logic: This thread implements the logic of the thermostat. It turns*/
00108 /*ON/OFF the thermostat depending on temperature, movement and the web control. It also */
00109 /*allows the user to set the temperature from the push button switches. The setting of  */
00110 /*temperature can also be done remotely through xively. Currently the program just      */
00111 /*controls turning ON/OFF the system remotely.                                          */
00112 /****************************************************************************************/
00113 void Thermostat_logic(void const *args)
00114 {
00115     while (true) {
00116         if (heat_on == 0x2 ||  (/*!no_move ||*/ remote_state == ON))
00117         {
00118             thermostat = 1;                                    
00119             status = 1;                                        
00120         } else if (heat_on == 0x1 || /*no_move ||*/ remote_state == OFF) {                                                 
00121             thermostat = 0;                                    
00122             heater = 0;                                       
00123             status = 0;                                       
00124         }
00125         
00126         /*If the joystick is pushed upwards increase set temperature by 2
00127         And print the set temperature on LCD.*/
00128         if (temp_up.rising()) {                                
00129             temp = temp + 0x2;                                                      
00130         }
00131         
00132         /*else if the joystick is pushed downwards decrease set temperature by 2
00133         And print the set temperature on LCD.*/ 
00134         
00135         else if (temp_down.rising()) {                       
00136             temp = temp - 0x2;                                 
00137         }
00138 
00139         //Comparison logic and turn Heater ON/OFF
00140         if ((temp > (current.read()+ hys)) & thermostat == 1)
00141             heater =  1;
00142         else if ((temp < (current.read()- hys)) | thermostat == 0)
00143             heater = 0;
00144             
00145         if (acc_x_old != MMA.x() || acc_y_old != MMA.y() || acc_z_old != MMA.x())
00146        {
00147            no_move = 0;
00148        }
00149          
00150         Thread::wait(100);      //wait for 100 msec
00151     }
00152 }
00153 /****************************************************************************************/
00154 
00155 
00156 /****************************************************************************************/
00157 /*Thread check movement: This thread detects if there is movement nearby the thermostat.*/
00158 /*If there is no movement this thread sets a variable called no_move which is furthur   */
00159 /*used to turn ON/OFF the system. Logic implemented for movement detection is as follows*/
00160 /*This thread is executed once every minute. Every time this thread is executed it      */
00161 /*compares the accelerometer reading with its previous value. If the reading is same    */
00162 /*(no movement detected) it increments a counter. When this counter reaches 20 (which   */
00163 /*means there is no movement for 20 mins) it sets the variable no_move to turn OFF the  */
00164 /*system. When a different accelerometer value is detected(movement present) it resets  */
00165 /*the variable which will in turn turn the system ON.                                   */
00166 /****************************************************************************************/
00167 
00168 void check_movement(void const *args)
00169 {
00170     static int move_cntr = 0;
00171     while (true) {
00172     acc_x_old = acc_x;
00173     acc_y_old = acc_y;
00174     acc_z_old = acc_z;
00175     acc_x = MMA.x();
00176     acc_y = MMA.y();
00177     acc_z = MMA.z();
00178     if (acc_x_old == acc_x && acc_y_old == acc_y && acc_z_old == acc_z)
00179     {
00180         move_cntr++;
00181         pc.printf("Value of move_cntr = %d\r\n",move_cntr);
00182         move = 011;
00183     }
00184     else {
00185         move_cntr = 0;
00186         pc.printf("Move_cntr reset\r\n");}
00187          //If the Accelerometer value remains constant for 20 mins no movement detected
00188     if (move_cntr >= TIME)   
00189         no_move = 1;
00190     else
00191         no_move = 0;
00192     Thread::wait(1*MIN);
00193     } 
00194 }
00195 /****************************************************************************************/
00196 
00197 
00198 /****************************************************************************************/
00199 /*Thread main: This is the main thread which instantiates all other threads. This thread*/
00200 /*is also used to communicate with xively. It updates xively with the current temoerature*/
00201 /*and the movement status. It also reads the status command from xively and turns ON/OFF */
00202 /*the system accordingly. This thread is also used for setting up ethernet connection    */
00203 /****************************************************************************************/
00204 
00205 int main() {
00206     
00207     Thread lcd_display(update_lcd,NULL,  osPriorityAboveNormal);
00208     Thread thermostat_thread(Thermostat_logic,NULL,  osPriorityAboveNormal);
00209     Thread accel_thread(check_movement,NULL,osPriorityAboveNormal);
00210     
00211     EthernetInterface eth;
00212     
00213     int s = eth.init(); //Use DHCP
00214     if( s != NULL )
00215     {
00216         pc.printf( "Could not initialise. Will halt!\n" );        
00217         exit( 0 );
00218     }    
00219         
00220     s = eth.connect();
00221     
00222     if( s != NULL )
00223     {
00224         pc.printf( "Could not connect. Will halt!\n" );
00225         exit( 0 );
00226     }
00227     else 
00228     {
00229         pc.printf( "IP: %s\n", eth.getIPAddress() );    
00230     }
00231         
00232         xi_feed_t feed;
00233         memset( &feed, NULL, sizeof( xi_feed_t ) );
00234     
00235         feed.feed_id = XI_FEED_ID;
00236         feed.datastream_count = 4;
00237     
00238         /*Data stream for temperature*/
00239         feed.datastreams[0].datapoint_count = 1;
00240         xi_datastream_t* temperature_datastream = &feed.datastreams[0];
00241         strcpy( temperature_datastream->datastream_id, "Temperature" );
00242         xi_datapoint_t* current_temperature = &temperature_datastream->datapoints[0];
00243         
00244         /*Data stream for movement*/
00245         feed.datastreams[1].datapoint_count = 1;
00246         xi_datastream_t* orientation_datastream = &feed.datastreams[1];
00247         strcpy( orientation_datastream->datastream_id, "Movement" );
00248         xi_datapoint_t* current_orientation = &orientation_datastream->datapoints[0];
00249 
00250         /*Data stream for status control (Input datastream)*/
00251         feed.datastreams[2].datapoint_count = 1;
00252         xi_datastream_t* control_datastream = &feed.datastreams[2];
00253         strcpy( control_datastream->datastream_id, "System" );
00254         xi_datapoint_t* current_state = &control_datastream->datapoints[0];
00255                        
00256     // create the cosm library context
00257         xi_context_t* xi_context
00258             = xi_create_context( XI_HTTP, XI_API_KEY, feed.feed_id );
00259         if( xi_context == NULL )
00260         {
00261             pc.printf("Error in Xi_Context\r\n");
00262             exit (0);
00263         }
00264 
00265         while (true) {
00266             xi_set_value_f32( current_temperature, current.read() ); 
00267             if (no_move == 1) 
00268             {
00269                 xi_set_value_str( current_orientation, "No movement" );
00270             }
00271             else
00272             {
00273                 xi_set_value_str( current_orientation, "Movement Present" );
00274             }
00275             // read remote value
00276             xi_datastream_get( xi_context, feed.feed_id
00277                     , control_datastream->datastream_id
00278                     , control_datastream->datapoints);      
00279                         current_state = &control_datastream->datapoints[0];   
00280             int system_status = current_state->value.i32_value;
00281             if (system_status == 0)
00282             {
00283                 remote_state = OFF;
00284             }
00285             else
00286             {
00287                 remote_state = ON;
00288             }
00289         
00290             pc.printf("Status value is %d\r\n",system_status); 
00291             pc.printf("Done\r\n"); 
00292             xi_feed_update( xi_context, &feed );
00293             Thread::wait(15*SEC);
00294         }
00295 }
00296 /****************************************************************************************/