IoT_watering project - watering unit

Dependencies:   DHT11 mbed-rtos mbed ssWi

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 
00004 #include "config.hpp"
00005 
00006 #include "DHT11.h"
00007 
00008 #include "xbee.hpp"
00009 #include "ssWiSocket.hpp"
00010 
00011 #ifndef DEBUG
00012 #define     printf(fmt,...)     
00013 #endif
00014 
00015 LocalFileSystem local("local");
00016 
00017 // global configuration
00018 watering_unit_config_t global_config;
00019 
00020 // ssWi sockets
00021 ssWiSocket* socket_moisture = NULL;
00022 ssWiSocket* socket_temperature = NULL;
00023 ssWiSocket* socket_humidity = NULL;
00024 ssWiSocket* socket_response = NULL;
00025 ssWiSocket* socket_water = NULL;
00026 ssWiSocket* socket_command = NULL;
00027 
00028 // thread functions
00029 void thread_sensing_fcn();
00030 void thread_watering_fcn();
00031 
00032 // return true if a new message has been received, false otherwise
00033 bool read_from_port(ssWiSocket *socket, int *value);
00034 
00035 int main() {
00036     Timer t;
00037     t.start();
00038     
00039     printf("MAIN - configuration\r\n");
00040     
00041     // read configuration    
00042     FILE *fp = fopen("/local/cfg.txt", "r");
00043     if (fp == NULL)
00044         error("missing configuration file\r\n");
00045     fscanf(fp, "%d", &global_config.address);
00046     fclose(fp);
00047     global_config.moisture_port = GET_MOISTURE_PORT(global_config);
00048     global_config.temperature_port = GET_TEMPERATURE_PORT(global_config);
00049     global_config.humidity_port = GET_HUMIDITY_PORT(global_config);
00050     global_config.response_port = GET_RESPONSE_PORT(global_config);
00051     global_config.water_port = GET_WATER_PORT(global_config);
00052 
00053     // configure network
00054     XBeeModule xbee(XBEE_PIN_TX, XBEE_PIN_RX, PAN_ID, CHANNEL_ID);
00055     xbee.init(XBEE_TX_PER_SECOND, XBEE_RX_PER_SECOND);
00056     socket_moisture = ssWiSocket::createSocket(global_config.moisture_port);
00057     socket_temperature = 
00058                        ssWiSocket::createSocket(global_config.temperature_port);
00059     socket_humidity = ssWiSocket::createSocket(global_config.humidity_port);
00060     socket_response = ssWiSocket::createSocket(global_config.response_port);
00061     socket_water = ssWiSocket::createSocket(global_config.water_port);
00062     socket_command = ssWiSocket::createSocket(PORT_COMMANDS);
00063 
00064     // threads
00065     Thread thread_sensing(osPriorityAboveNormal);
00066     thread_sensing.start(&thread_sensing_fcn);
00067     Thread thread_watering(osPriorityHigh);
00068     thread_watering.start(&thread_watering_fcn);
00069 
00070     // wait 10 seconds since the board started
00071     while(t.read() < TIMEOUT_CONF);
00072     t.stop();
00073 
00074     printf("MAIN - board ready\r\n");
00075 
00076     // handle messages
00077     bool recv_start_sampling = false;
00078     bool recv_stop_sampling = false;
00079     bool recv_watering = false;
00080     int msg = COMM_NO_VALUE;
00081     while(true) {
00082         if (!read_from_port(socket_command, &msg))
00083             continue;
00084         if (!recv_start_sampling && msg == COMM_START_SAMPLING) {
00085             recv_start_sampling = true;
00086             printf("MAIN - sampling start command\r\n");
00087             thread_sensing.signal_set(SIGNAL_START_ARRIVED);
00088             continue;
00089         }
00090         if (!recv_stop_sampling && msg == COMM_STOP_SAMPLING) {
00091             recv_stop_sampling = true;
00092             printf("MAIN - sampling stop command\r\n");
00093             thread_sensing.signal_set(SIGNAL_STOP_ARRIVED);
00094             continue;
00095         }
00096         if (!recv_watering &&  msg == GET_WATERING_COMMAND(global_config)) {
00097             recv_watering = true;
00098             printf("MAIN - watering start command\r\n");
00099             thread_watering.signal_set(SIGNAL_WATERING_ARRIVED);
00100             continue;
00101         }
00102         if (msg == COMM_SHUTDOWN) {
00103             printf("MAIN - shutdown command\r\n");
00104             recv_start_sampling = false;
00105             recv_stop_sampling = false;
00106             recv_watering = false;
00107             socket_moisture->write(COMM_NO_VALUE);
00108             socket_temperature->write(COMM_NO_VALUE);
00109             socket_humidity->write(COMM_NO_VALUE);
00110             socket_response->write(COMM_NO_VALUE);
00111             continue;
00112         }
00113     }
00114 
00115     printf("MAIN - join threads and end\r\n");
00116 
00117     thread_sensing.join();
00118     thread_watering.join();
00119 
00120     return 0;
00121 }
00122 
00123 void thread_sensing_fcn () {
00124     AnalogIn sensor_moisture(HW_PIN_MOISTURE);
00125 
00126     while (1) {
00127         int msg = COMM_SAMPLING_OK;
00128         DHT11 sensor_dht(HW_PIN_TEMPERATURE);
00129         printf("SAMP - waiting...\r\n");
00130 
00131         // wait supervisor message
00132         Thread::signal_wait(SIGNAL_START_ARRIVED);
00133         printf("SAMP - start\r\n");
00134 
00135         DigitalOut l(LED3);
00136         l = 1;
00137 
00138         Timer t;
00139         t.start();
00140         // wait two seconds for HDT sensor
00141         wait(2.0);
00142         
00143         // sample values
00144         double sens_mois = 0.0;
00145         double sens_temp = 0.0;
00146         double sens_humi = 0.0;
00147         for (int i = 0; i < NUM_SAMPLES; i++) {
00148             if (sensor_dht.readData() != 0) {
00149                 printf("SAMP - error %d\r\n", error);
00150                 msg = COMM_SAMPLING_KO;
00151                 break;
00152             }
00153             sens_temp += sensor_dht.readTemperature();
00154             sens_humi += sensor_dht.readHumidity();
00155             sens_mois += sensor_moisture.read() * 100;
00156             if (t.read() > TIMEOUT_SAMPLING) {
00157                 // timeout expired, exit
00158                 msg = COMM_SAMPLING_OUT;
00159                 break;
00160             }
00161             Thread::wait(INTERVAL_SAMPLING);
00162         }
00163         t.stop();
00164         
00165         // compute averages
00166         sens_mois = (sens_mois / NUM_SAMPLES) * 10.0;
00167         sens_temp = (sens_temp / NUM_SAMPLES) * 10.0;
00168         sens_humi = (sens_humi / NUM_SAMPLES) * 10.0;
00169         printf("SAMP - %f, %f, %f\r\n", sens_mois, sens_temp, sens_humi);
00170 
00171         // wait supervisor stop message
00172         Thread::signal_wait(SIGNAL_STOP_ARRIVED);
00173 
00174         // write averages and response
00175         int value = (int)sens_mois;
00176         socket_moisture->write(value == 0 ? 1 : value);
00177         value = (int)sens_temp;
00178         socket_temperature->write(value == 0 ? 1 : value);
00179         value = (int)sens_humi;
00180         socket_humidity->write(value == 0 ? 1 : value);
00181         socket_response->write(msg);
00182         printf("SAMP - end\r\n");
00183         
00184         l = 0;
00185     }
00186 }
00187 
00188 void thread_watering_fcn() {
00189     DigitalOut pump(HW_PIN_PUMP);
00190     DigitalIn level_sens(HW_PIN_LOW_WATER_LEVEL);
00191 
00192     while (1) {
00193         pump = 0;
00194         printf("WATR - waiting...\r\n");
00195 
00196         // wait watering command
00197         Thread::signal_wait(SIGNAL_WATERING_ARRIVED);
00198         printf("WATR - start\r\n");
00199         Timer t;
00200         t.start();
00201 
00202         DigitalOut l(LED2);
00203         l = 1;
00204 
00205         // read total second to water
00206         int seconds = COMM_NO_VALUE;
00207         while(!read_from_port(socket_water, &seconds) &&
00208                                                      t.read()<TIMEOUT_WATERING);
00209         t.stop();
00210         if (t.read() >= TIMEOUT_WATERING) {
00211             socket_response->write(COMM_WATERING_KO);
00212             continue;
00213         }
00214         printf("WATR - required time %ds\r\n", seconds);
00215 
00216         // start watering
00217         int msg = COMM_WATERING_OK;
00218         double actual_seconds = 0.0;
00219         while (actual_seconds < seconds) {
00220             if (!level_sens) {
00221                 // low water, stop pump and exit
00222                 pump = 0;
00223                 printf("WATR - watering level error\r\n");
00224                 msg = COMM_LOW_WATER_LEVEL;
00225                 break;
00226             }
00227             // water for 1 second
00228             t.reset(); t.start();
00229             double scale = seconds > (actual_seconds + 1.0) ? 1.0 : seconds -
00230                                                                  actual_seconds;
00231             pump = 1;
00232             Thread::wait((unsigned int)(scale * INTERVAL_WATERING));
00233             t.stop();
00234             actual_seconds += t.read();
00235         }
00236         pump = 0;
00237         printf("WATR - elapsed time %fs\r\n", actual_seconds);
00238         socket_response->write(msg);
00239         
00240         l = 0;
00241     }
00242 }
00243 
00244 bool read_from_port(ssWiSocket *socket, int *value) {
00245     int prev = *value;
00246     *value = socket->read();
00247     return (*value) != prev;
00248 }