IoT_watering project - watering unit
Dependencies: DHT11 mbed-rtos mbed ssWi
Diff: main.cpp
- Revision:
- 0:51143a026e2b
- Child:
- 1:7f4af0d73836
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jan 19 23:29:42 2017 +0000 @@ -0,0 +1,279 @@ +#include "mbed.h" +#include "rtos.h" + +#include "config.hpp" + +#include "DHT11.h" + +#include "xbee.hpp" +#include "ssWiSocket.hpp" + +LocalFileSystem local("local"); + +watering_unit_config_t global_config; + +void thread_sensing_fcn(); +void thread_watering_fcn(); + +ssWiSocket* socket_moisture = NULL; +ssWiSocket* socket_temperature = NULL; +ssWiSocket* socket_humidity = NULL; +ssWiSocket* socket_response = NULL; +ssWiSocket* socket_water = NULL; +ssWiSocket* socket_command = NULL; + +bool read_from_port(ssWiSocket *socket, int *value); + +int main() { + Timer t; + t.start(); + + // read configuration +#ifdef DEBUG + printf("\r\nMAIN - configuration\r\n"); +#endif + + FILE *fp = fopen("/local/cfg.txt", "r"); + if (fp == NULL) + error("missing configuration file\r\n"); + fscanf(fp, "%d", &global_config.address); + fclose(fp); + global_config.moisture_port = GET_MOISTURE_PORT(global_config); + global_config.temperature_port = GET_TEMPERATURE_PORT(global_config); + global_config.humidity_port = GET_HUMIDITY_PORT(global_config); + global_config.response_port = GET_RESPONSE_PORT(global_config); + global_config.water_port = GET_WATER_PORT(global_config); + + // configure network + XBeeModule xbee(p9, p10, 102, 14); + xbee.init(5, 10); + socket_moisture = ssWiSocket::createSocket(global_config.moisture_port); + socket_temperature = + ssWiSocket::createSocket(global_config.temperature_port); + socket_humidity = ssWiSocket::createSocket(global_config.humidity_port); + socket_response = ssWiSocket::createSocket(global_config.response_port); + socket_water = ssWiSocket::createSocket(global_config.water_port); + socket_command = ssWiSocket::createSocket(PORT_COMMANDS); + + // threads + Thread thread_sensing(osPriorityAboveNormal); + thread_sensing.start(&thread_sensing_fcn); + Thread thread_watering(osPriorityHigh); + thread_watering.start(&thread_watering_fcn); + + // wait 10 seconds since the board started + while(t.read() < TIMEOUT_CONF); + t.stop(); + +#ifdef DEBUG + printf("MAIN - board ready\r\n"); +#endif + + // handle messages + bool recv_start_sampling = false; + bool recv_stop_sampling = false; + bool recv_watering = false; + int msg = COMM_NO_VALUE; + while(true) { + if (!read_from_port(socket_command, &msg)) + continue; + if (!recv_start_sampling && msg == COMM_START_SAMPLING) { + recv_start_sampling = true; +#ifdef DEBUG + printf("MAIN - sampling start command\r\n"); +#endif + thread_sensing.signal_set(SIGNAL_START_ARRIVED); + continue; + } + if (!recv_stop_sampling && msg == COMM_STOP_SAMPLING) { + recv_stop_sampling = true; +#ifdef DEBUG + printf("MAIN - sampling stop command\r\n"); +#endif + thread_sensing.signal_set(SIGNAL_STOP_ARRIVED); + continue; + } + if (!recv_watering && msg == GET_WATERING_COMMAND(global_config)) { + recv_watering = true; +#ifdef DEBUG + printf("MAIN - watering start command\r\n"); +#endif + thread_watering.signal_set(SIGNAL_WATERING_ARRIVED); + continue; + } + if (msg == COMM_SHUTDOWN) { +#ifdef DEBUG + printf("MAIN - shutdown command\r\n"); +#endif + recv_start_sampling = false; + recv_stop_sampling = false; + recv_watering = false; + /* + socket_moisture->write(COMM_NO_VALUE); + socket_temperature->write(COMM_NO_VALUE); + socket_humidity->write(COMM_NO_VALUE); + */ + socket_response->write(COMM_NO_VALUE); + continue; + } + if (msg == COMM_EXIT) { +#ifdef DEBUG + printf("MAIN - exit command\r\n"); +#endif +/* + socket_moisture->write(COMM_NO_VALUE); + socket_temperature->write(COMM_NO_VALUE); + socket_humidity->write(COMM_NO_VALUE); + */ + socket_response->write(COMM_NO_VALUE); + break; + } + } + +#ifdef DEBUG + printf("MAIN - join threads and end\r\n"); +#endif + + thread_sensing.join(); + thread_watering.join(); + + return 0; +} + +void thread_sensing_fcn() { + AnalogIn sensor_moisture(HW_PIN_MOISTURE); + + while (1) { + int msg = COMM_SAMPLING_OK; + DHT11 sensor_dht(HW_PIN_TEMPERATURE); +#ifdef DEBUG + printf("SAMP - waiting...\r\n"); +#endif + // wait supervisor message + Thread::signal_wait(SIGNAL_START_ARRIVED); + +#ifdef DEBUG + printf("SAMP - start\r\n"); +#endif + Timer t; + t.start(); + // wait two seconds for HDT sensor + wait(2.0); + + // sample values + double sens_moisture = 0.0; + double sens_temperature = 0.0; + double sens_humidity = 0.0; + int num_dht_samples = 0; + for (int i = 0; i < NUM_SAMPLES; i++) { + int error = sensor_dht.readData(); + if (error != 0) { + printf("SAMP - error %d\r\n", error); + msg = COMM_SAMPLING_KO; + } else { + sens_temperature += sensor_dht.readTemperature(); + sens_humidity += sensor_dht.readHumidity(); + num_dht_samples += 1; + } + sens_moisture += sensor_moisture.read() * 100; + // if timeout is expired, exit + if (t.read() > TIMEOUT_SAMPLING) { + msg = COMM_SAMPLING_OUT; + break; + } + Thread::wait(INTERVAL_SAMPLING); + } + t.stop(); + + // compute averages + sens_moisture = (sens_moisture / NUM_SAMPLES) * 10; + if (num_dht_samples > 0) { + sens_temperature = (sens_temperature / num_dht_samples) * 10; + sens_humidity = (sens_humidity / num_dht_samples) * 10; + } +#ifdef DEBUG + printf("SAMP - %f, %f, %f\r\n", sens_moisture, sens_temperature, + sens_humidity); +#endif + // wait supervisor stop message + Thread::signal_wait(SIGNAL_STOP_ARRIVED); + + // write averages and response + int value = (int)sens_moisture; + socket_moisture->write(value == 0 ? 1 : value); + value = (int)sens_temperature; + socket_temperature->write(value == 0 ? 1 : value); + value = (int)sens_humidity; + socket_humidity->write(value == 0 ? 1 : value); + socket_response->write(msg); +#ifdef DEBUG + printf("SAMP - end\r\n"); +#endif + } +} + +void thread_watering_fcn() { + DigitalOut pump(HW_PIN_PUMP); + DigitalIn level_sens(HW_PIN_LOW_WATER_LEVEL); + + while (1) { + pump = 0; +#ifdef DEBUG + printf("WATR - waiting...\r\n"); +#endif + Thread::signal_wait(SIGNAL_WATERING_ARRIVED); +#ifdef DEBUG + printf("WATR - start\r\n"); +#endif + Timer t; + t.start(); + + // read total second to water + int seconds = COMM_NO_VALUE; + while(!read_from_port(socket_water, &seconds) && + t.read()<TIMEOUT_WATERING); + t.stop(); + if (t.read() >= TIMEOUT_WATERING) { + socket_response->write(COMM_WATERING_KO); + continue; + } +#ifdef DEBUG + printf("WATR - required time %ds\r\n", seconds); +#endif + int msg = COMM_WATERING_OK; + double actual_seconds = 0.0; + while (actual_seconds < seconds) { + if (!level_sens) { + pump = 0; +#ifdef DEBUG + printf("WATR - watering level error\r\n"); +#endif + msg = COMM_LOW_WATER_LEVEL; + t.stop(); + break; + } + t.reset(); + t.start(); + double scale = seconds > (actual_seconds + 1.0) ? 1.0 : seconds - + actual_seconds; + pump = 1; + Thread::wait((unsigned int)(scale * INTERVAL_WATERING)); + t.stop(); + actual_seconds += t.read(); + } + pump = 0; +#ifdef DEBUG + printf("WATR - elapsed time %fs\r\n", actual_seconds); +#endif + socket_response->write(msg); +#ifdef DEBUG + printf("WATR - end\r\n"); +#endif + } +} + +bool read_from_port(ssWiSocket *socket, int *value) { + int prev = *value; + *value = socket->read(); + return (*value) != prev; +}