IoT_watering project - watering unit

Dependencies:   DHT11 mbed-rtos mbed ssWi

main.cpp

Committer:
mariob
Date:
2017-01-19
Revision:
0:51143a026e2b
Child:
1:7f4af0d73836

File content as of revision 0:51143a026e2b:

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