Simple Weather Station. Data Logger and gives primitive weather predictions.

Dependencies:   BMP180 N5110 PowerControl beep mbed

main.cpp

Committer:
el13nsp
Date:
2015-05-11
Revision:
7:b92507a1a1e5
Parent:
6:7271c1e8e348

File content as of revision 7:b92507a1a1e5:

/**
@file main.cpp
 
@brief Program implementation
 
*/

#include "main.h"

// Interrupt Service Routine

void timerExpired()
{
    timerFlag = 1;
}

void stateTimerExpired()
{
    stateTimerFlag = 1;
}

void alarmTimerExpired()
{
    alarmTimerFlag = 1;
}

void writingTimerExpired()
{
    writingTimerFlag = 1;
}

void graphTimerExpired()
{
    graphTimerFlag = 1;
}

void buttonAPressed()
{
    leds = 15;
    wait(1.0);
    buttonAFlag = 1; //set flag
}

void buttonBPressed()
{
    leds = 15;
    wait(1.0);
    buttonBFlag = 1; //set flag
}

void buttonCPressed()
{
    leds = 15;
    wait(1.0);
    buttonCFlag = 1; //set flag
}

void buttonDPressed() //Toggle unit in ISR
{
    leds = 15;
    unit = !unit; // unti switches between celsius and fahrenheit and mb and hpa
}

int main()
{

    leds = 15;

    timer.attach(&timerExpired,2.0); // Call ISR every 2 seconds
    stateTimer.attach(&stateTimerExpired,300.0); // Call ISR every 5 minutes
    alarmTimer.attach(&alarmTimerExpired,10.0); // Call ISR every 10 seconds
    writingTimer.attach(&writingTimerExpired,1800.0); // Call ISR every 30 minutes
    graphTimer.attach(&graphTimerExpired,600.0); // Call ISR every 10 minutes

    serial.attach(&serialISR); // attach serial ISR

    char timebuffer[30]; // buffer used to store time string
    char datebuffer[30]; // buffer used to store time string

    //set_time(0); // initialise time to 1st January 1970

    PHY_PowerDown();
    //int result = semihost_powerdown();
    
    //Sets button to pull up mode
    buttonB.mode(PullUp);
    buttonC.mode(PullUp);
    buttonD.mode(PullUp);

    // initiliase barometer
    bmp180.init();

    // first need to initialise display
    lcd.init();

    // these are default settings so not strictly needed
    lcd.normalMode();      // normal colour mode
    lcd.setBrightness(0.5); // put LED backlight on full

    lcd.printString("ELEC 2645",15,0);
    lcd.printString("WeatherStation",1,2);
    lcd.printString("Nikhil Pillai",1,4);
    lcd.printString("200800623",15,5);

    wait(5.0);

    leds = 0;

    buttonA.rise(&buttonAPressed); // event generated on rising edge
    buttonB.rise(&buttonBPressed); // event generated on rising edge
    buttonC.rise(&buttonCPressed); // event generated on rising edge
    buttonD.rise(&buttonDPressed); // event generated on rising edge

    Measurement measurement;  // measurement structure declared in BMP180 class

    float pressureChange = 0; // Initializes the pressure change variable to 0

    while(1) {

        lcd.setBrightness(POT1); // put LED backlight on full

        float potValue = POT1;

        char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
        // so can display a string of a maximum 14 characters in length
        
        //If-else statement to switch the LCD ON or OFF based on potentiometer value
        if(potValue<0.1) {

            lcd.turnOff();
            Sleep();
            initFlag=1;

        } else if((initFlag == 1) && (potValue >= 0.1)) {

            initFlag = 0;
            lcd.init();

        }
        
        //If state timer flag is set
        if(stateTimerFlag) {

            stateTimerFlag = 0; //reset flag

            // read values (T in Celsius and P in mb) and print over serial port
            measurement = bmp180.readValues();
            
            //Sets pressure reading in an array to compare over the hour
            if(j==12) {
                for (int n = 0; n < 11; n++) {
                    presscompare[n] = presscompare[n+1];
                }
                j=11;
            }

            presscompare[j] = measurement.pressure;
            j++;
            
            //If-else statement to check if prediction is possible or not
            if( presscompare[11] == 0) {
                prediction = 0;
            } else
                prediction = 1;

            pressureChange = presscompare[11] - presscompare[0]; //Gets pressure change over the hour
            
            //If-else if statements to set the state based on pressure change
            if((pressureChange < 0.1) &&  (pressureChange > -0.1))
                state = 0;
            else if((pressureChange > 0.1) &&  (pressureChange <= 0.5))
                state = 1;
            else if((pressureChange > 0.5) &&  (pressureChange <= 1.17))
                state = 2;
            else if((pressureChange > 1.17) &&  (pressureChange <= 2.0))
                state = 3;
            else if(pressureChange > 2.0)
                state = 4;
            else if((pressureChange < -0.1) &&  (pressureChange >= -0.5))
                state = 5;
            else if((pressureChange < -0.5) &&  (pressureChange >= -1.17))
                state = 6;
            else if((pressureChange < -1.17) &&  (pressureChange >= -2.0))
                state = 7;
            else if(pressureChange < -2.0)
                state = 8;
            
            //Turns alarm ON if weather prediction is stormy
            if((state == 8) && (prediction == 1))
                alarm = 1;
            else
                alarm = 0;

        }
        
        //If timer flag is set
        if(timerFlag) {

            timerFlag = 0; //reset flag

            // read values (T in Celsius and P in mb) and print over serial port
            measurement = bmp180.readValues();

            lcd.clear();            // clear display

            leds = 0;

            if(unit == celcius) {  //If unit is celcius

                int length = sprintf(buffer,"T = %.2f C",measurement.temperature); // print formatted data to buffer
                // it is important the format specifier ensures the length will fit in the buffer
                if (length <= 14)  // if string will fit on display
                    lcd.printString(buffer,0,1);           // display on screen

                length = sprintf(buffer,"P = %.2f mb",measurement.pressure); // print formatted data to buffer
                if (length <= 14)
                    lcd.printString(buffer,0,2);           // display on screen

            }

            else if(unit == fahrenheit) {  //If unit is fahrenheit

                int length = sprintf(buffer,"T = %.2f F",(((measurement.temperature*9)/5)+32)); // print formatted data to buffer
                // it is important the format specifier ensures the length will fit in the buffer
                if (length <= 14)  // if string will fit on display
                    lcd.printString(buffer,0,1);           // display on screen

                length = sprintf(buffer,"P = %.1f hpa",measurement.pressure); // print formatted data to buffer
                if (length <= 14)
                    lcd.printString(buffer,0,2);           // display on screen

            }

            time_t seconds = time(NULL); // get current time

            // format time into a string (time and date)
            strftime(timebuffer, 14 , "%T", localtime(&seconds));
            strftime(datebuffer, 14 , "%D", localtime(&seconds));

            // Display on LCD
            lcd.printString(timebuffer,20,4);
            lcd.printString(datebuffer,20,5);

            // need to refresh display after setting pixels
            lcd.refresh();

            // format time into a string (time and date)
            strftime(buffer, 30 , "%X %D", localtime(&seconds));
            strftime(timebuffer, 30 , "%X %D", localtime(&seconds));
            
            // print over serial
            serial.printf("Time = %s\n",buffer);

        }
        
        //If alarm timer flag is set
        if(alarmTimerFlag) {
            alarmTimerFlag = 0; //reset flag

            if(alarm==1) {  //If alarm is set
                buzzer.beep(1000,0.5); // Buzzer beeps
                redled = 1; // Red led is turned ON
            } else
                redled =0; //Red led is turned OFF

        }
        
        //If writing timer flag is set
        if(writingTimerFlag) {  

            writingTimerFlag = 0; //reset flag

            // read values (T in Celsius and P in mb) and print over serial port
            measurement = bmp180.readValues();

            if(logSwitch) { // If data logging switch is turned ON
                writeDataToFile(measurement.temperature, measurement.pressure, timebuffer); // write current value to disk
            }

        }
        
        //If graph timer flag is set
        if(graphTimerFlag) {

            graphTimerFlag = 0; // reset flag
            
            //Sets temperature and pressure reading into arrays to display as graphs
            if(i==84) {
                for (int n = 0; n < 83; n++) {
                    temparray[n] = temparray[n+1];
                    pressarray[n] = pressarray[n+1];
                }
                i=83;
            }

            temparray[i] = measurement.temperature/65;
            pressarray[i] = (measurement.pressure-975)/50;
            i++;

        }

        if (buttonAFlag) { // if flag A is set
            lcd.clear();
            lcd.printString("T",0,0);
            lcd.plotArray(temparray); // Display graph of temperature
            lcd.refresh();
            wait(5.0);
            buttonAFlag = 0; //reset flag
        }

        if (buttonBFlag) { // if flag B is set
            lcd.clear();
            lcd.printString("P",0,0);
            lcd.plotArray(pressarray); // Display graph if pressure
            lcd.refresh();
            wait(5.0);
            buttonBFlag = 0; //reset flag
        }

        if(buttonCFlag) { // if flag C is set

            lcd.clear();
            
            if(prediction == 0) { // If prediction is not possible

                lcd.printString("PREDICTION",10,1);
                lcd.printString("UNAVAILABLE",8,2);
                lcd.printString("INSUFFICIENT",5,4);
                lcd.printString("DATA",28,5);

            } else {
                setState(); //Calls function to give prediciton
            }

            lcd.refresh();

            wait(5.0);
            
            buttonCFlag = 0; // reset flag
        }

        if (setTimeFlag) { // if updated time has been sent
            setTimeFlag = 0; // clear flag
            setTime(); // update time
        }
    }
}

//Function to display weather prediction
void setState()
{

    switch(state) { // Displays prediction based on state

        case 0:
            cloudySun();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("< 4",0,5);
            break;
        case 1:
            sunny();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("< 4",0,5);
            break;
        case 2:
            sunny();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("4-5",0,5);
            break;
        case 3:
            sunny();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("5-7",0,5);
            break;
        case 4:
            sunny();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("> 6",0,5);
            break;
        case 5:
            cloudySun();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("< 4",0,5);
            break;
        case 6:
            clouds();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("4-5",0,5);
            break;
        case 7:
            rainy();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("5-7",0,5);
            break;
        case 8:
            stormy();
            lcd.printString("BeaufortNumber",0,4);
            lcd.printString("> 6",0,5);
            break;

    }

}

//Function for setting RTC
void setTime()
{
// print time for debugging
    serial.printf("set_time - %s",rxString);
// atoi() converts a string to an integer
    int time = atoi(rxString);
// update the time
    set_time(time);
}

void serialISR()
{
// when a serial interrupt occurs, read rx string into buffer
    serial.gets(rxString,16);
// set flag
    setTimeFlag = 1;
}


void writeDataToFile(float temp,float press,char* time) // Function for logging data into a csv file
{
    greenled = 1; // turn on LEDs for feedback
    FILE *fp = fopen("/local/Datalog.csv", "a"); // open 'log.txt' for appending
    // if the file doesn't exist it is created, if it exists, data is appended to the end
    fprintf(fp,"T = %f C, P = %f mb, Time = %s\n",temp, press, time); // print string to file
    fclose(fp); // close file
    greenled = 0; // turn off LEDs to signify file access has finished
}

//Functions to set pixels for displaying various weather predictions

void sunny()
{

    lcd.drawCircle(WIDTH/2,(HEIGHT/2)-10,8,0);  // x,y,radius,white fill
    lcd.drawLine(42,1,42,4,1);
    lcd.drawLine(42,24,42,27,1);
    lcd.drawLine(29,14,32,14,1);
    lcd.drawLine(52,14,55,14,1);
    lcd.drawLine(32,4,35,7,1);
    lcd.drawLine(52,4,49,7,1);
    lcd.drawLine(32,24,35,21,1);
    lcd.drawLine(52,24,49,21,1);

}

void clouds()
{

    lcd.drawLine(29,14,55,14,1);
    lcd.setPixel(28,13);
    lcd.setPixel(27,12);
    lcd.setPixel(27,11);
    lcd.setPixel(28,10);
    lcd.setPixel(29,9);
    lcd.setPixel(30,9);
    lcd.setPixel(31,10);
    lcd.setPixel(29,8);
    lcd.setPixel(29,7);
    lcd.setPixel(29,6);
    lcd.setPixel(30,5);
    lcd.setPixel(31,4);
    lcd.setPixel(32,3);
    lcd.setPixel(33,2);
    lcd.setPixel(34,2);
    lcd.setPixel(35,1);
    lcd.setPixel(36,1);
    lcd.setPixel(37,1);
    lcd.setPixel(38,1);
    lcd.setPixel(39,1);
    lcd.setPixel(40,2);
    lcd.setPixel(41,3);
    lcd.setPixel(41,4);
    lcd.setPixel(42,5);
    lcd.setPixel(42,6);
    lcd.setPixel(42,7);
    lcd.setPixel(43,6);
    lcd.setPixel(44,6);
    lcd.setPixel(45,7);
    lcd.setPixel(45,8);
    lcd.setPixel(45,9);
    lcd.setPixel(45,10);
    lcd.setPixel(46,9);
    lcd.setPixel(47,8);
    lcd.setPixel(48,8);
    lcd.setPixel(49,8);
    lcd.setPixel(50,8);
    lcd.setPixel(51,9);
    lcd.setPixel(52,9);
    lcd.setPixel(53,10);
    lcd.setPixel(54,11);
    lcd.setPixel(54,12);
    lcd.setPixel(54,13);

}

void rainy()
{
    clouds();
    lcd.drawLine(37,19,32,24,1);
    lcd.drawLine(42,19,37,24,1);
    lcd.drawLine(47,19,42,24,1);

}

void stormy()
{

    clouds();
    lcd.drawLine(38,16,45,16,1);
    lcd.drawLine(38,16,36,18,1);
    lcd.drawLine(36,18,41,23,1);
    lcd.setPixel(40,24);
    lcd.drawLine(40,25,39,26,1);
    lcd.drawLine(45,16,42,19,1);
    lcd.drawLine(42,19,44,21,1);
    lcd.drawLine(44,21,41,24,1);

}

void cloudySun()
{
    clouds();
    lcd.setPixel(27,13);
    lcd.setPixel(26,13);
    lcd.setPixel(25,12);
    lcd.setPixel(24,11);
    lcd.setPixel(24,10);
    lcd.setPixel(24,9);
    lcd.setPixel(24,8);
    lcd.setPixel(25,7);
    lcd.setPixel(26,6);
    lcd.setPixel(27,5);
    lcd.setPixel(28,5);
    lcd.setPixel(29,5);
    lcd.drawLine(28,3,28,1,1);
    lcd.drawLine(24,5,22,3,1);
    lcd.drawLine(22,9,20,9,1);
    lcd.drawLine(23,13,21,15,1);
    lcd.drawLine(28,15,28,17,1);

}