IoT_watering project - watering unit

Dependencies:   DHT11 mbed-rtos mbed ssWi

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;
+}