Weather Station using an mBed microcontroller and a Windows CE Device

Dependencies:   TextLCD mbed HMC6352

main.cpp

Committer:
mafischl
Date:
2011-12-15
Revision:
0:75e6a2e50519

File content as of revision 0:75e6a2e50519:

#include "mbed.h"
#include "GPS.h"
#include "MODSERIAL.h"
#include "TextLCD.h"
#include "HMC6352.h"
#define MESSAGE_BUFFER_SIZE 2048
#define REVID 0x00    //ASIC Revision Number
#define OPSTATUS 0x04   //Operation Status
#define STATUS 0x07     //ASIC Status
#define START 0x0A      //Constant Readings
#define PRESSURE 0x1F   //Pressure 3 MSB
#define PRESSURE_LSB 0x20 //Pressure 16 LSB
#define TEMP 0x21       //16 bit temp


extern "C" void mbed_reset();                   // Allows for software resets

MODSERIAL serialIO(p28,p27);                    // RS-232 to PC (tx, rx)
GPS gps(p13,p14);                               // RS-232 to GPS (tx, rx)
TextLCD lcd(p23, p21, p22, p11, p12, p8);       // rs, e, d4-d7
HMC6352 compass(p9, p10);                       // I2C (sda, scl)
SPI spi(p5, p6, p7);                            // mosi, miso, sclk
DigitalOut cs(p25);                             // chip select
DigitalOut drdy(p26);                           // DRDY pin
AnalogIn humidity(p17);                         // Humidity Analog from Phidgets
AnalogIn temperature2(p20);                     // Temperature Analog from Phidgets
AnalogIn light(p15);                            // Light Analog Sensor
InterruptIn windSpeed(p18);                     // Anemometer for Wind Speed
AnalogIn windDirection(p19);                    // Wind Direction
InterruptIn rainGauge(p16);                     // Rain Gauge Click
DigitalOut wdtLED(LED4);                        // WatchDog Indicator
DigitalOut heartBeat(LED1);                     // Heartbeat
DigitalOut led2(LED2);                          // Test for message process
char messageBufferIncoming[MESSAGE_BUFFER_SIZE];
char messageBufferOutgoing[MESSAGE_BUFFER_SIZE];
LocalFileSystem local("local");
Timer t;
int timeCount;
int state;
int error;
int progressBarCount = 0;
int pressureDirection = 0;
int rainLevel = 0;                              // Rain Level (3 = heavy rain, 2 = moderate rain, 1 = light rain, 0 = no rain)
int rainInterval = 780;                         // Start at high count, as soon as the rain gauge clicks once, the level is based on the the rain interval.
int rainCount = 0;
int speedCount = 0;
int lightLevel = 0;                             // light level (3 = sunny, 2 = partly cloudy, 1 = mostly cloudy, 0 = night)
float lightCount = 0.0;
float lightValue;
int lightTimeCount = 1;
bool GPSlock = 0;
float prevLatitude = 0.0;
float prevLongitude = 0.0;
float prevPressure = 0.0;
float getHumidity;
float w_direction = 0.0;
float wSpeed = 0.0;
float getTemperature = 0.0;
float rainAmount = 0.0;
float temp_in;
unsigned long pressure_lsb;
unsigned long pressure_msb;
unsigned long temp_pressure;
unsigned long pressure;
char forecastOutput[14];                        // Forecast Output String
char outputString[161];                         // Output string for getWeather()


// WATCHDOG FUNCTION

class Watchdog {
public:
// Load timeout value in watchdog timer and enable
    void kick(float s) {
        LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
        uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
        LPC_WDT->WDTC = s * (float)clk;
        LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
        kick();
    }
// "kick" or "feed" the dog - reset the watchdog timer
// by writing this required bit pattern
    void kick() {
        LPC_WDT->WDFEED = 0xAA;
        LPC_WDT->WDFEED = 0x55;
    }
};

Watchdog wdt;

const float tbl_windvane[16][2] = {
    {0.0, 33000}, {22.5, 6570}, {45.0, 8200}, {67.5, 891},
    {90.0, 1000}, {112.5, 688}, {135.0, 2200}, {157.5, 1410},
    {180.0, 3900}, {202.5, 3140}, {225.0, 16000}, {247.5, 14120},
    {270.0, 120000}, {292.5, 42120}, {315.0, 64900}, {337.5, 21880}
};

char read_register(char register_name) {
    register_name <<=2;
    register_name &= 0xFC;
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    char register_value=spi.write(0x00);
    cs=1;
    return register_value;
}


void write_register(char register_name, char register_value) {
    register_name <<= 2;
    register_name |= 0x02; //le estamos diciendo que escriba
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    spi.write(register_value); //Send value to record into register
    cs=1;
}

float read_register16(char register_name) {
    register_name <<= 2;
    register_name &= 0xFC; //Read command
    cs=0; //Select SPI Device
    spi.write(register_name); //Write byte to device
    int in_byte1 = spi.write(0x00);
    int in_byte2 = spi.write(0x00);
    cs=1;
    float in_word= (in_byte1<<=8) | (in_byte2);
    return(in_word);
}

void w_rain() {
    rainCount++;
    if (rainInterval < 129) {
        rainLevel = 3;  // heavy rain
    } else if ((rainInterval >= 130) && (rainInterval < 390)) {
        rainLevel = 2;  // moderate rain
    } else if ((rainInterval >= 391) && (rainInterval < 780)) {
        rainLevel = 1;  // light rain
    } else {
        rainLevel = 0;  // no rain
    }
    rainInterval = 0;
}

void w_speed() {
    speedCount++;
}

float wdirection() {
    int i;
    float v;

    v = windDirection * 3.3f; // V
    v = v / ((3.3f - v) / 10000.0f); // ohm
    for (i = 0; i < 16; i ++) {
        if (v > tbl_windvane[i][1] * 0.9 && v < tbl_windvane[i][1] * 1.1) {
            return tbl_windvane[i][0];
        }
    }
    return 0;
}


void messageReceive(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *sys = q->serial;
    sys->move(messageBufferIncoming, MESSAGE_BUFFER_SIZE);



// Routines for Received Commands

    //Testing Routines
    if (!strncmp(messageBufferIncoming, "LED2:1", sizeof("LED2:1")-1)) led2 = 1;                 // For testing
    else if (!strncmp(messageBufferIncoming, "LED2:0", sizeof("LED2:0")-1)) led2 = 0;            // For testing
    else if (!strncmp(messageBufferIncoming, "LED2:2", sizeof("LED2:2")-1)) led2 = !led2;        // For testing

    // Reset mBed microcontroller
    else if (!strncmp(messageBufferIncoming, "reset", sizeof("reset")-1)) mbed_reset();          // Force Reset of mBed microcontroller

    // Set State of mbed microcontroller
    else if (!strncmp(messageBufferIncoming, "setState(Active)", sizeof("setState(Active)")-1)) {
        state = 1;                                                                               // Set State of Program
        serialIO.printf("State set to: Active\r\n");
    } else if (!strncmp(messageBufferIncoming, "setState(Paused)", sizeof("setState(Paused)")-1)) {
        state = 0;                                                                               // Set State of Program
        serialIO.printf("State set to: Paused\r\n");
    }

    // Status of mbed microcontroller
    else if (!strncmp(messageBufferIncoming, "getStatus()", sizeof("getStatus()")-1)) {
        if (state == 0) serialIO.printf("Paused\r\n");
        if (state == 1) serialIO.printf("Active\r\n");
        // Extra Messages
    }

    // Error Messages
    else if (!strncmp(messageBufferIncoming, "getErrorMsg()", sizeof("getErrorMsg()")-1)) {
        if (error == 0) serialIO.printf("No Errors\r\n");
        // Extra Messages
    }

    // GPS Location
    else if (!strncmp(messageBufferIncoming, "getLocation()", sizeof("getLocation()")-1)) {
        // Get Location
        if (state == 1) {
            if ((gps.lock)&&(GPSlock)) {
                serialIO.printf("Location = %.3f, %.3f\r\n", gps.latitude, gps.longitude);
            } else {
                serialIO.printf("Location = Not Locked\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // GPS Altitude
    else if (!strncmp(messageBufferIncoming, "getAltitude()", sizeof("getAltitude()")-1)) {
        // Get Altitude
        if (state == 1) {
            if ((gps.lock)&&(GPSlock)) {
                serialIO.printf("Altitude = %.3f meters (MSL)\r\n", gps.altitude);
            } else {
                serialIO.printf("Altitude = Not Locked\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // GPS Date
    else if (!strncmp(messageBufferIncoming, "getGPSDate()", sizeof("getGPSDate()")-1)) {
        // Get Date
        if (state == 1) {
            if ((gps.lock)&&(GPSlock)) {
                serialIO.printf("Date = %f\r\n", gps.GPSdate);
            } else {
                serialIO.printf("Date = Not Locked\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // GPS Time
    else if (!strncmp(messageBufferIncoming, "getGPSTime()", sizeof("getGPSTime()")-1)) {
        // Get Time
        if (state == 1) {
            if ((gps.lock)&&(GPSlock)) {
                serialIO.printf("Time = %.3f\r\n", gps.GPStime);
            } else {
                serialIO.printf("Time = Not Locked\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // GPS Lock
    else if (!strncmp(messageBufferIncoming, "getGPSLock()", sizeof("getGPSLock()")-1)) {
        // Get Lock
        if (state == 1) {
            if ((gps.lock)&&(GPSlock)) {
                serialIO.printf("Locked\r\n");
            } else {
                serialIO.printf("Not Locked\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // GPS Direction
    else if (!strncmp(messageBufferIncoming, "getDirection()", sizeof("getDirection()")-1)) {
        // Get Direction
        if (state == 1) {
            serialIO.printf("Direction = %.2f degrees\r\n", (compass.sample() / 10.0));
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Temperature
    else if (!strncmp(messageBufferIncoming, "getTemperature()", sizeof("getTemperature()")-1)) {
        if (state == 1) {
            // Get Temperature
            drdy = 1;
            wait(0.1);
            temp_in = read_register16(TEMP);
            wait(0.1);
            drdy = 0;
            wait(0.1);
            temp_in = (temp_in*3.3)/5;  // Calibration offset
            temp_in = ((temp_in*9) / 100) + 32;     // Convert to fahrenheit
            serialIO.printf("Temperature = %.2f degrees F\r\n", temp_in);
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Humidity
    else if (!strncmp(messageBufferIncoming, "getHumidity()", sizeof("getHumidity()")-1)) {
        if (state == 1) {
            // Get Humidity
            getHumidity = humidity;
            getHumidity = getHumidity*38.12f;
            serialIO.printf("Humidity = %.2f%%\r\n", getHumidity);
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Pressure
    else if (!strncmp(messageBufferIncoming, "getPressure()", sizeof("getPressure()")-1)) {
        // Get Pressure
        if (state == 1) {
            drdy = 1;
            wait(0.1);
            pressure_msb = read_register(PRESSURE);
            pressure_msb &= 0x07;
            pressure_lsb = read_register16(PRESSURE_LSB);
            wait(0.1);
            drdy = 0;
            wait(0.1);
            pressure = ((pressure_msb<<16)| pressure_lsb);
            if (pressure != prevPressure) {
                if (prevPressure < pressure - 2000) {
                    pressureDirection = 1;                      // Pressure is increasing
                    prevPressure = pressure;
                    pressure /= 4;      // Convert to pascals
                    pressure /= 3376.85f;  // Convert from pascals to inches of mercury (60 deg F)
                    serialIO.printf("Pressure = %.2u, increasing\r\n", pressure);
                } else if (prevPressure > pressure + 2000) {
                    pressureDirection = -1;                     // Pressure is decreasing
                    prevPressure = pressure;
                    pressure /= 4;      // Convert to pascals
                    pressure /= 3376.85f;  // Convert from pascals to inches of mercury (60 deg F)
                    serialIO.printf("Pressure = %.2u, decreasing\r\n", pressure);
                } else {
                    pressureDirection = 0;                 // Pressure is relatively unchanged
                    pressure /= 4;      // Convert to pascals
                    pressure /= 3376.85f;  // Convert from pascals to inches of mercury (60 deg F)
                    serialIO.printf("Pressure = %.2u, no change\r\n", pressure);
                }
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Light
    else if (!strncmp(messageBufferIncoming, "getLight()", sizeof("getLight()")-1)) {
        if (state == 1) {
            // Get Light
            serialIO.printf("Light = %.2f\r\n", lightValue);
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Light Level
    else if (!strncmp(messageBufferIncoming, "getLightLevel()", sizeof("getLightLevel()")-1)) {
        // Get Light Level
        if (state == 1) {
            switch (lightLevel) {
                case 0:
                    serialIO.printf("It is Dark Outside.\r\n");
                    break;
                case 1:
                    serialIO.printf("It is Mostly Cloudy.\r\n");
                    break;
                case 2:
                    serialIO.printf("It is Partly Cloudy.\r\n");
                    break;
                case 3:
                    serialIO.printf("It is Mostly Sunny.\r\n");
                    break;
                default:
                    serialIO.printf("Unknown.\r\n");
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Wind Direction
    else if (!strncmp(messageBufferIncoming, "getWindDirection()", sizeof("getWindDirection()")-1)) {
        // Get Wind Direction
        if (state == 1) {
            w_direction = wdirection();
            w_direction = w_direction + (compass.sample() / 10.0);  // Offset that the unit is no aligned by using compass
            if (w_direction > 360) w_direction = w_direction - 360;
            // Convert to cardinal direction
            if (w_direction < 22.5) serialIO.printf("Wind Direction = N\r\n");
            else if ((w_direction >= 22.5) && (w_direction < 67.5)) serialIO.printf("Wind Direction = NE\r\n");
            else if ((w_direction >= 67.5) && (w_direction < 112.5)) serialIO.printf("Wind Direction = E\r\n");
            else if ((w_direction >= 112.5) && (w_direction < 157.5)) serialIO.printf("Wind Direction = SE\r\n");
            else if ((w_direction >= 157.5) && (w_direction < 202.5)) serialIO.printf("Wind Direction = S\r\n");
            else if ((w_direction >= 202.5) && (w_direction < 247.5)) serialIO.printf("Wind Direction = SW\r\n");
            else if ((w_direction >= 247.5) && (w_direction < 292.5)) serialIO.printf("Wind Direction = W\r\n");
            else if ((w_direction >= 292.5) && (w_direction < 337.5)) serialIO.printf("Wind Direction = NW\r\n");
            else serialIO.printf("Wind Direction = N\r\n");

        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Wind Speed
    else if (!strncmp(messageBufferIncoming, "getWindSpeed()", sizeof("getWindSpeed()")-1)) {
        // Get Wind Speed
        if (state == 1) {
            serialIO.printf("Wind Speed = %.2f mph\r\n", (wSpeed));
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Wind
    else if (!strncmp(messageBufferIncoming, "getWind()", sizeof("getWind()")-1)) {
        // Get Wind Direction
        if (state == 1) {
            if (wSpeed < 1) {
                serialIO.printf("There is no wind.\r\n");
            } else if ((wSpeed >= 1) && (wSpeed < 5)) {
                serialIO.printf("There are only calm winds.\r\n");
            } else {
                w_direction = wdirection();
                w_direction = w_direction + (compass.sample() / 10.0);  // Offset that the unit is no aligned by using compass
                if (w_direction > 360) w_direction = w_direction - 360;
                // Convert to cardinal direction
                if (w_direction < 22.5) serialIO.printf("Wind traveling N at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 22.5) && (w_direction < 67.5)) serialIO.printf("Wind traveling NE at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 67.5) && (w_direction < 112.5)) serialIO.printf("Wind traveling E at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 112.5) && (w_direction < 157.5)) serialIO.printf("Wind traveling SE at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 157.5) && (w_direction < 202.5)) serialIO.printf("Wind traveling S at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 202.5) && (w_direction < 247.5)) serialIO.printf("Wind traveling SW at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 247.5) && (w_direction < 292.5)) serialIO.printf("Wind traveling W at %.2f mph\r\n", wSpeed);
                else if ((w_direction >= 292.5) && (w_direction < 337.5)) serialIO.printf("Wind traveling NW at %.2f mph\r\n", wSpeed);
                else serialIO.printf("Wind traveling N at %.2f mph\r\n", wSpeed);
            }
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Rain Amount
    else if (!strncmp(messageBufferIncoming, "getRainAmount()", sizeof("getRainAmount()")-1)) {
        // Get Rain Amount
        if (state == 1) {
            rainAmount = rainCount * 0.011f;
            serialIO.printf("Rain Amount = %f inches today\r\n", (rainAmount));
        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Current Weather Command
    else if (!strncmp(messageBufferIncoming, "getWeather()", sizeof("getWeather()")-1)) {
        // Message Sample: Current Condition is (forecast) at (temperature) degrees (wind condition). Pressure is (pressure) and humidity is (humidity). Observed at (location).
        if (state == 1) {
            //Predict conditions based on data collected from rain gauge and light sensor.
            if (rainLevel == 3) {
                if (temp_in >= 37.0) {                              // Heavy Rain
                    strcpy(forecastOutput, "heavy rain at ");
                } else if ((temp_in < 37.0) && (temp_in > 32.0)) {  // Heavy Mix
                    strcpy(forecastOutput, "heavy rain/snow at ");
                } else if (temp_in <= 32.0) {                       // Heavy Snow
                    strcpy(forecastOutput, "heavy snow at ");
                }
            } else if (rainLevel == 2) {
                if (temp_in >= 37.0) {                              // Moderate Rain
                    strcpy(forecastOutput, "rain showers at ");
                } else if ((temp_in < 37.0) && (temp_in > 32.0)) {  // Moderate Mix
                    strcpy(forecastOutput, "rain/snow showers at ");
                } else if (temp_in <= 32.0) {                       // Moderate Snow
                    strcpy(forecastOutput, "snow showers at ");
                }
            } else if (rainLevel == 1) {
                if (temp_in >= 37.0) {                              // Light Rain
                    strcpy(forecastOutput, "light rain at ");
                } else if ((temp_in < 37.0) && (temp_in > 32.0)) {  // Light Mix
                    strcpy(forecastOutput, "light rain/snow at ");
                } else if (temp_in <= 32.0) {                       // Light Snow
                    strcpy(forecastOutput, "snow flurries at ");
                }
            } else if (rainLevel == 0) {                            // No Precipitation
                if (lightLevel == 0) {                              // Dark Skies (Nighttime)
                    strcpy(forecastOutput, "night skies at ");
                } else if (lightLevel == 1) {                       // Mostly Cloudly
                    strcpy(forecastOutput, "mostly cloudy at ");
                } else if (lightLevel == 2) {                       // Partly Cloudy
                    strcpy(forecastOutput, "partly cloudy at ");
                } else {                                            // Mostly Sunny
                    strcpy(forecastOutput, "mostly sunny at ");
                }
            }


            // Temperature
            drdy = 1;
            wait(0.1);
            temp_in = read_register16(TEMP);
            wait(0.1);
            drdy = 0;
            wait(0.1);
            temp_in = (temp_in*3.3)/5;  // Calibration offset
            temp_in = ((temp_in*9) / 100) + 32;     // Convert to fahrenheit

            // Pressure
            drdy = 1;
            wait(0.1);
            pressure_msb = read_register(PRESSURE);
            pressure_msb &= 0x07;
            pressure_lsb = read_register16(PRESSURE_LSB);
            wait(0.1);
            drdy = 0;
            wait(0.1);
            pressure = ((pressure_msb<<16)| pressure_lsb);
            pressure /= 4;
            pressure /=3376.85f;

            // Humidity
            getHumidity = humidity;
            getHumidity = getHumidity*38.12f;

            // Determine Wind Condition

            if (wSpeed < 1) {                                      // No Wind
                serialIO.printf("Current Condition is %s%d degrees. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, pressure, getHumidity, gps.latitude, gps.longitude);
            } else if ((wSpeed >= 1) && (wSpeed < 5)) {              // Calm Winds
                serialIO.printf("Current Condition is %s%d degrees with calm winds. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, pressure, getHumidity, gps.latitude, gps.longitude);
            } else {
                if (w_direction < 22.5) serialIO.printf("Current Condition is %s%d degrees with wind traveling N at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 22.5) && (w_direction < 67.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling NE at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 67.5) && (w_direction < 112.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling E at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 112.5) && (w_direction < 157.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling SE at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 157.5) && (w_direction < 202.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling S at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 202.5) && (w_direction < 247.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling SW at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 247.5) && (w_direction < 292.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling W at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else if ((w_direction >= 292.5) && (w_direction < 337.5)) serialIO.printf("Current Condition is %s%d degrees with wind traveling NW at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
                else serialIO.printf("Current Condition is %s%d degrees with wind traveling N at %d mph. Pressure is %.2u and humidity is %.2f. Observed at %.3f, %.3f\r\n", forecastOutput, (int)temp_in, (int)wSpeed, pressure, getHumidity, gps.latitude, gps.longitude);
            }

        } else {
            serialIO.printf("Information is currently unavailable, please try again later\r\n");
        }
    }

    // Easter Eggs

    // Hi
    else if (!strncmp(messageBufferIncoming, "Hi", sizeof("Hi")-1)) {
        serialIO.printf("Hello foolish person.\r\n");
    }
    // Do a barrel roll.
    else if (!strncmp(messageBufferIncoming, "Do a barrel roll.", sizeof("Do a barrel roll.")-1)) {
        serialIO.printf("Why don't you do a barrel roll?\r\n");
    }
    // Who created you?
    else if (!strncmp(messageBufferIncoming, "Who created you?", sizeof("Who created you?")-1)) {
        serialIO.printf("I was created by George P. Burdell.\r\n");
    }
    // Who are you?
    else if (!strncmp(messageBufferIncoming, "Who are you?", sizeof("Who are you?")-1)) {
        serialIO.printf("I am the Van Leer Weather Monitoring Station. I am truely a one-of-a-kind piece of technology.\r\n");
    }
    // Ping
    else if (!strncmp(messageBufferIncoming, "Ping", sizeof("Ping")-1)) {
        serialIO.printf("I am not a submarine.\r\n");
    }
    // Find Chuck Norris
    else if (!strncmp(messageBufferIncoming, "Find Chuck Norris.", sizeof("Find Chuck Norris.")-1)) {
        serialIO.printf("I am sorry but I cannot find Chuck Norris because I know that Chuck Norris cannot be found. Chuck Norris finds you.\r\n");
    }
    // Tell Me A Joke.
    else if (!strncmp(messageBufferIncoming, "Tell me a joke.", sizeof("Tell me a joke.")-1)) {
        serialIO.printf("Humans.\r\n");
    }
    // I need help !
    else if (!strncmp(messageBufferIncoming, "I need help!.", sizeof("I need help!")-1)) {
        serialIO.printf("I cannot help you, but you can get help from the one they call Ewout.\r\n");
    }

    // Invalid Command
    else serialIO.printf("I am sorry but I do not understand your message. Please try again.\r\n");

    serialIO.rxBufferFlush();                            //Flush the Buffer
    return;
}


int main() {

    if ((LPC_WDT->WDMOD >> 2) & 1)
        wdtLED = 1;
    else wdtLED = 0;

    // 30 second timeout on watchdog timer hardware
    wdt.kick(10.0);

    serialIO.baud(9600);
    serialIO.format(8, Serial::None, 1);
    serialIO.attach(&messageReceive, MODSERIAL::RxAutoDetect);      //Attaches Interrupts
    serialIO.autoDetectChar('\n');                                  //Set Detection to Line Feed

    lcd.locate(0,0);
    lcd.printf("Acquiring signal");
    lcd.locate(0,1);
    lcd.printf("from satellite..");

    cs=1;
    spi.frequency(500000);  // the fastest of the sensor
    spi.format(8, 0);       // Use 8 bits of data
    wait(0.5);

    write_register(0x06,0x01);
    wait(0.5);

    write_register(0x03,0x0A);
    wait(0.5);


    wait(1.0);

    //Continuous mode, periodic set/reset, 20Hz measurement rate.
    compass.setOpMode(HMC6352_CONTINUOUS, 1, 20);

    windSpeed.rise(&w_speed);
    rainGauge.rise(&w_rain);

    t.start();      // Heartbeat sensor time
    state = 1;      // Sets state to active

    serialIO.printf("systemReady\r\n");     // Send System Ready Message


    while (1) {


        timeCount = t.read();

        if (timeCount > 0) {
            if (state == 1) {
                // Detect a unusual reading from the GPS Antenna. If consecutive readings are not roughly the same, then it should be assumed that the GPS does not have a confident reading and to signal that it does not have a lock.
                if ((((gps.latitude - prevLatitude > 5.0)||(gps.latitude - prevLatitude < -5.0))&&((gps.longitude - prevLongitude > 5.0)||(gps.longitude - prevLongitude < -5.0)))||(gps.numSat < 2)) {
                    GPSlock = 0;
                    //  lcd.cls();
                    //  lcd.locate(0,0);
                    //  lcd.printf("GPS NOT LOCKED");
                } else {
                    GPSlock = 1;
                    //  lcd.cls();
                    //  lcd.locate(0,0);
                    //  lcd.printf("GPS LOCKED");
                }

                if (gps.latitude != prevLatitude) prevLatitude = gps.latitude;
                if (gps.longitude != prevLongitude) prevLongitude = gps.longitude;

                if (gps.sample()&&(gps.lock)&&(GPSlock)) {
                    lcd.cls();
                    lcd.locate(0,0);
                    lcd.printf("LAT: %f", gps.latitude);
                    lcd.locate(0,1);
                    lcd.printf("LON: %f", gps.longitude);
                    progressBarCount = 0;
                } else {
                    lcd.cls();
                    lcd.locate(0,0);
                    if (progressBarCount > 19) {
                        progressBarCount = 0;
                    }
                    if (progressBarCount < 3) lcd.printf("Acquiring Signal");
                    else if (progressBarCount < 6) lcd.printf("from satellite  ");
                    else if (progressBarCount < 8) lcd.printf("Are you inside? ");
                    else if (progressBarCount < 10) lcd.printf("Any skyscrapers?");
                    else if (progressBarCount < 13) lcd.printf("Acquiring Signal");
                    else if (progressBarCount < 16) lcd.printf("from satellite  ");
                    else if (progressBarCount < 18) lcd.printf("Clouds overhead?");
                    else lcd.printf("Lost satellite? ");
                    lcd.locate(0,1);
                    switch (progressBarCount) {
                        case 0:
                            lcd.printf("                ");
                            break;
                        case 1:
                            lcd.printf(">               ");
                            break;
                        case 2:
                            lcd.printf(">>              ");
                            break;
                        case 3:
                            lcd.printf("<>>             ");
                            break;
                        case 4:
                            lcd.printf("<<>>            ");
                            break;
                        case 5:
                            lcd.printf(" <<>>           ");
                            break;
                        case 6:
                            lcd.printf("  <<>>          ");
                            break;
                        case 7:
                            lcd.printf("   <<>>         ");
                            break;
                        case 8:
                            lcd.printf("    <<>>        ");
                            break;
                        case 9:
                            lcd.printf("     <<>>       ");
                            break;
                        case 10:
                            lcd.printf("      <<>>      ");
                            break;
                        case 11:
                            lcd.printf("       <<>>     ");
                            break;
                        case 12:
                            lcd.printf("        <<>>    ");
                            break;
                        case 13:
                            lcd.printf("         <<>>   ");
                            break;
                        case 14:
                            lcd.printf("          <<>>  ");
                            break;
                        case 15:
                            lcd.printf("           <<>> ");
                            break;
                        case 16:
                            lcd.printf("            <<>>");
                            break;
                        case 17:
                            lcd.printf("             <<>");
                            break;
                        case 18:
                            lcd.printf("              <<");
                            break;
                        case 19:
                            lcd.printf("               <");
                            break;
                    }
                    progressBarCount++;

                }
                // Calculate the Wind Speed
                wSpeed = speedCount * 1.492f;
                speedCount = 0;

                // Create a rolling average over 10 minutes to determine light and rain level
                lightValue = light;
                if (lightTimeCount < 600) {
                    lightCount = (((lightCount*lightTimeCount)+lightValue)/(lightTimeCount+1));

                    lightTimeCount++;
                } else {
                    lightCount = (((lightCount*599)+lightValue)/600);
                }
                if (lightCount >= 0.7) {
                    lightLevel = 3;
                } else if ((lightCount >= 0.5) && (lightCount < 0.7)) {
                    lightLevel = 2;
                } else if ((lightCount >= 0.3) && (lightCount < 0.5)) {
                    lightLevel = 1;
                } else {
                    lightLevel = 0;
                }

                // Increase Rain Interval
                rainInterval++;

            } else {
                lcd.cls();
                lcd.locate(0,0);
                lcd.printf("PAUSED");
            }

            heartBeat = !heartBeat;
            t.stop();
            t.reset();
            t.start();
        }

        wait(0.05);
        wdt.kick();
    }
    return 0;
}