IoT_watering project - watering unit
Dependencies: DHT11 mbed-rtos mbed ssWi
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 }
Generated on Sun Jul 17 2022 17:54:38 by 1.7.2