The software that runs on the Sentinel nodes. This code is for the LPC1114FN28.

Dependencies:   XBEE_900HP_SPI mbed

main.cpp

Committer:
ottaviano3
Date:
2015-08-18
Revision:
1:b51fb321d026
Parent:
0:3540612dfbf8

File content as of revision 1:b51fb321d026:

/*
/ Sentinel software for the active nodes.
/
/ Design work done by:
/ Dominic Ottaviano
/ Sheldon Fernandes
/ Thien L. Nguyen
*/

#include "mbed.h"
#include "xbee900hp.h"

/*===========================================================/
/ Primary Configuration Area                                 /
/ Global Variables and Pin Assigments Declared Within        /
/===========================================================*/

// Define GPS pin connections.
Serial gps(dp16,dp15);

// Define xbee connections. Mosi,Miso,SCK,ATTN,Reset
xbee900hp xbee(dp2,dp1,dp6, dp9, dp4);

// Function prototypes
// Function to query the GPS
int getGPS(char* data);

// Global Variables
// Buffer for reading in from xbee
char buffer[256];
// Buffer for storing GPS data
char gpsmsg[256];

/*===========================================================/
/ END OF Primary Configuration Area                          /
/===========================================================*/

/*===========================================================/
/ Begin main program code                                    /
/===========================================================*/

int main()
{
    /*===========================/
    / Configuration Section      /
    /===========================*/

    // Set GPS paramters
    // Baud rate
    gps.baud(4800);
    // Other params (8 data bits, no parity, 1 stop bit)
    gps.format(8,SerialBase::None,1);

    // Configure gps with these parameters:
    // NMEA, 4800 Baud, 8 Data bits, 1 Stop bit, No Parity
    unsigned int gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'0'^','^'1'^','^'4'^'8'^'0'^'0'^','^'8'^','^'1'^','^'0';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    // Send command to the GPS module
    gps.printf("$PSRF100,1,4800,8,1,0*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable automatic broadcast of all messages. We are going to poll manually.
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,0,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable GLL
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'1'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,1,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable GSA
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'2'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,2,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable GSV
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'3'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,3,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable RMC
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'4'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,4,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    // Disable VTG
    gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'5'^','^'0'^','^'0'^','^'1';
    // Trim to 8 bits just in case
    gpsxor = gpsxor & 0xFF;
    gps.printf("$PSRF103,5,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);

    /*===========================/
    / END Configuration Section  /
    /===========================*/


    // Set the node id of this module. Generated from the serial of the xbee
    char nodeidarray[10];
    int nodeid = 0;

    // Initialize nodeidarray
    for (int i = 0; i<10; i++) {
        nodeidarray[i] = 0;
    }

    // Get xbee serial number
    int serialget = xbee.getSerial(nodeidarray);

    if (serialget == 0) {
        for (int i = 0; i<10; i++) {
            // Nonlinear function to expand unique id space
            nodeid += nodeidarray[i]*nodeidarray[i]+nodeidarray[i];
        }
    }
    // Node id should now be a unique int

    // Set variables, there are more than we need here but it would be useful in the future if we did need any.
    char ns, ew;
    int lock;
    double satsused;
    double hdop;
    double latitude, longitude;
    double altitude;
    double time;
    char altunits;
    double geoidsep;
    char geoidunits;
    int difrefstationid;
    unsigned int gpschecksum;
    unsigned int filledbuff;

    // Announce the node to the base station.
    filledbuff = snprintf (buffer, sizeof(buffer)-1, "ANCE,%i,\r\n",nodeid);
    // Send packet out into the air.
    xbee.sendPacket(buffer, filledbuff);

    // Main program run loop.
    while(true) {
        // Get new data from the GPS and if data is read successfully continue
        if (!(getGPS(gpsmsg))) {
            // Parse the recieved data and check if its valid (HINT: lf = double since pointers aren't promoted)
            if(sscanf(gpsmsg, "$GPGGA,%lf,%lf,%c,%lf,%c,%i,%lf,%lf,%lf,%c,%lf,%c,,%i*%x", &time, &latitude, &ns, &longitude, &ew, &lock, &satsused, &hdop, &altitude, &altunits, &geoidsep, &geoidunits, &difrefstationid, &gpschecksum) == 14) {
                // Check if the lock is valid
                if((lock != 1) && (lock != 2) && (lock != 6)) {
                    // Format code line to send out on radio that node has no lock
                    filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,\r\n",nodeid);
                    // Send packet out into the air.
                    xbee.sendPacket(buffer, filledbuff);
                } else {
                    // Convert latitude into proper form for display on a map.
                    double degrees;
                    double minutes = modf(latitude/100.0f, &degrees);
                    minutes = (minutes*100.0f)/60.0f;
                    latitude = degrees + minutes;
                    // Convert longitude
                    minutes = modf(longitude/100.0f, &degrees);
                    minutes = (minutes*100.0f)/60.0f;
                    longitude = degrees + minutes;

                    // Correct for south and west.
                    if(ns == 'S') {
                        latitude  *= -1.0;
                    }
                    if(ew == 'W') {
                        longitude *= -1.0;
                    }

                    // Format string for sending out over radio.
                    filledbuff = snprintf (buffer, sizeof(buffer)-1, "DLIN,%i,%f,%f,%f,%f,\r\n",nodeid, latitude, longitude, altitude, satsused);
                    // Send packet out.
                    xbee.sendPacket(buffer, filledbuff);
                }
                // Wait a second for GPS data to be fresh again and not waste cycles.
                wait(1);
            } else {
                // GPS hasn't found a good enough lock
                filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid);
                // Send packet out into the air.
                xbee.sendPacket(buffer, filledbuff);
                // Wait half a second then try again.
                wait(0.5);
            }
        } else {
            // GPS hasn't found lock or sent a corrupted message
            filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid);
            // Send packet out into the air.
            xbee.sendPacket(buffer, filledbuff);
            // Wait half a second a try again.
            wait(0.5);
        }
    }
}

int getGPS(char* data)
{
    // Request a query of GGA
    // Precomputed checksum to save cpu cycles
    gps.printf("$PSRF103,0,1,0,1*%u%u\r\n",0x2,0x5);

    // Timer to prevent hangs if gps doesn't respond.
    Timer gpsTO;
    gpsTO.start();

    // Wait for gps to becom readable.
    while (gps.readable() == false) {
        // Timeout
        if (gpsTO.read() > 2) {
           return 1;
        }
    }

    // Wait a tiny bit to allow the gps to send the whole line.
    wait_ms(50);
    // Get data from gps
    gps.scanf("%s",data);

    // Compute checksum of recieved gps data
    int i = 0;
    unsigned int calcgpschecksum = 0;
    // Checksum is calculated between and not including the $ and *
    while ((data[i] != '\0') && (data[i] != '*')) {
        // Skip the $
        if (data[i] != '$') {
            calcgpschecksum = calcgpschecksum ^ data[i];
        }
        i++;
    }
    // Shift the checksum to match the format we recieve from the gps
    calcgpschecksum = calcgpschecksum & 0xFF;

    // Get checksum sent by gps out of string
    unsigned int realgpschecksum = 0;
    char checksumarray[3];
    for (int i = 0; i < 256; i++) {
        if (data[i] == '*') {
            // Create little array with ascii hex values.
            checksumarray[0] = data[i+1];
            checksumarray[1] = data[i+2];
            checksumarray[2] = '\0';
            // Convert ascii values to regular integer
            sscanf(checksumarray,"%x",&realgpschecksum);
            break;
        }
    }

    // Check for checksum match
    if( calcgpschecksum == realgpschecksum ) {
        return 0;
    }

    // No checksum match
    return 1;
}