modifiche posizione iniziale e sistema d'allarme.
Dependencies: MTK3339 TextLCD mbed tsi_sensor
Fork of app_gps by
Diff: main.cpp
- Revision:
- 1:80d31bcee0e5
- Parent:
- 0:828a0c36c3e2
- Child:
- 2:3a9cacc54417
--- a/main.cpp Thu Nov 07 11:53:56 2013 +0000 +++ b/main.cpp Mon Jul 13 10:04:05 2015 +0000 @@ -1,36 +1,171 @@ #include "mbed.h" #include "MTK3339.h" +#include "TextLCD.h" +#include "tsi_sensor.h" + +#define ELEC0 9 +#define ELEC1 10 +#define LAT 0 +#define LON 1 static int waitData = 0; -static MTK3339 gps(P4_22, P4_23); + +static MTK3339 gps(PTE22, PTE23); +static DigitalOut r_led(LED_RED); +static DigitalOut g_led(LED_GREEN); +static DigitalOut b_led(LED_BLUE); +static TSIAnalogSlider slider(ELEC0, ELEC1, 40); +static TextLCD lcd(PTE5, PTE3, PTE2, PTB11, PTB10, PTB9, TextLCD::LCD16x2); +const double PI = 3.141592654; // Pi greco +const double R = 6371000.0; // Raggio della Terra in metri +const int N = 60; -static void dataAvailable() { +double initPos[2] = {.0, .0}; +double thrs = 3.0; // Soglia di allarme in metri +bool set = false; + +static void dataAvailable() +{ waitData |= gps.getAvailableDataType(); } -int main(void) { - - gps.start(&dataAvailable, (MTK3339::NmeaGga|MTK3339::NmeaVtg)); +// Trasforma un angolo da gradi in radianti +static double toRadians(double deg) +{ + return deg * PI / 180.0; +} + +// Calcola la distanza tra 2 punti in metri +static double dist(double lat1, double lon1, double lat2, double lon2) +{ + double dPhi, dLam, a, c; + + dPhi = toRadians(lat2 - lat1); + dLam = toRadians(lon2 - lon1); + a = sin(dPhi/2) * sin(dPhi/2) + + cos(toRadians(lat1)) * cos(toRadians(lat2)) * sin(dLam/2) * sin(dLam/2); + c = 2 * atan2(sqrt(a), sqrt(1-a)); + return ceil(R * c); +} + +// Calcola la distanza tra punto iniziale e attuale in metri +static double distFromInit(double lat, double lon) +{ + return dist(initPos[LAT], initPos[LON], lat, lon); +} + +static double mean(double* x, int n) +{ + double sum = 0; + for (int i=0; i<n; i++) { + sum += x[i]; + } + return sum / n; +} + +static double var(double* x, int n) +{ + double x1[n]; + for (int i=0; i<n; i++) { + x1[i] = x[i]*x[i]; + } + return mean(x1,n) - (mean(x,n)*mean(x,n)); +} + +static double stdev(double* y, int n) +{ + return sqrt(var(y,n)); +} - while(1) { - while(waitData == 0); +static void setInitPos() +{ + set = false; + double coords[2][N]; + int i = 0; + int c = 0; + double meanLat, meanLon, stdevLat, stdevLon; + while (!set && gps.gga.satellites>=4) { + coords[LAT][i%N] = gps.getLatitudeAsDegrees(); + coords[LON][i%N] = gps.getLongitudeAsDegrees(); + wait(1); + i++; + if (i>=N) { + meanLat = mean(coords[LAT], N); + meanLon = mean(coords[LON], N); + stdevLat = stdev(coords[LAT], N); + stdevLon = stdev(coords[LON], N); + + for (int j=0; j<N; j++) { + if (coords[LAT][j] > meanLat-stdevLat && coords[LAT][j] < meanLat+stdevLat && + coords[LON][j] > meanLon-stdevLon && coords[LON][j] < meanLon+stdevLon) + c++; + } + + if (c>=N*.5) { + initPos[LAT] = coords[LAT][i%N]; + initPos[LON] = coords[LON][i%N]; + set = true; + } + } + } +} + +static void setRGBColor(double r, double g, double b) +{ + r_led = 1 - r; + g_led = 1 - g; + b_led = 1 - b; +} + +int main(void) +{ + + double d; + + gps.start(&dataAvailable, MTK3339::NmeaGga); + + while (1) { + + while (waitData == 0); + + lcd.cls(); + if ((waitData & MTK3339::NmeaGga) != 0) { waitData &= ~(MTK3339::NmeaGga); - printf("gpa: fix=%d, sats=%d, alt=%f, lat=%f, lon=%f\n", - gps.gga.fix, gps.gga.satellites, gps.gga.altitude, - gps.getLatitudeAsDegrees(), gps.getLongitudeAsDegrees()); + + if (gps.gga.satellites < 4) { + lcd.printf("Fixing\nsatellites (%d)", gps.gga.satellites); + setRGBColor(1, 1, 0); + } else if (!set) { + // La prima volta prendi la posizione iniziale + lcd.printf("Acquiring\nposition...", gps.gga.satellites); + setInitPos(); + } else { + // Prendi la soglia impostata dall'utente + if (slider.readPercentage() != 0.0) { + thrs = floor(slider.readPercentage() * 12.0 + 3.0); + } + + // Calcola la distanza tra punto iniziale e attuale + d = distFromInit(gps.getLatitudeAsDegrees(), gps.getLongitudeAsDegrees()); + + // Verifica che la soglia sia superata + if (d >= thrs) { + lcd.printf("THRS=%2.0fm SATS=%d\nDIST=%2.0fm ALARM!", thrs, gps.gga.satellites, d); + setRGBColor(1, 0, 0); + } else { + lcd.printf("THRS=%2.0fm SATS=%d\nDIST=%2.0fm OK!", thrs, gps.gga.satellites, d); + setRGBColor(0, 1, 0); + } + } + } - if ((waitData & MTK3339::NmeaVtg) != 0) { - waitData &= ~(MTK3339::NmeaVtg); - printf("vtg: course=%f, speed=%f km/h, mode=%c\n", - gps.vtg.course, gps.vtg.speedKmHour, gps.vtg.mode); - } - - waitData &= (MTK3339::NmeaGga|MTK3339::NmeaVtg); + + waitData &= MTK3339::NmeaGga; } -} \ No newline at end of file +}