Calculates azimuth and elevation of a satellite dish based on its longitude, latitude and selected satellite.

Dependencies:   PinDetect TextLCD mbed MODGPS

main.cpp

Committer:
BartJanssens
Date:
2012-03-29
Revision:
0:fe8decc6a938

File content as of revision 0:fe8decc6a938:

/*  Satelitte Positioner
  *
  * Calculates azimuth and elevation of a satellite dish based on its longitude, latitude
  * and selected satellite.
  * see: http://www.alcyone.com/max/writing/essays/geostationary-orbits.html
  *      http://www.spaceacademy.net.au/watch/track/locgsat.htm
  *      http://www.dishpointer.com/
  *  
  * Copyright (c) 2012 Bart Janssens
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
#include "mbed.h"

#include "TextLCD.h"
#include "PinDetect.h"
#include "GPS.h"

#include "SatGps.h"
#include "SatelliteList.h"


#define GPSRX p10
#define GPSBAUD 4800

#define MAXGPRMC 3
#define MAXGPRMCA 4

#define PI 3.14159265

TextLCD lcd(p24, p26, p27, p28, p29, p30, TextLCD::LCD16x2 ); // rs, e, d0, d1, d2, d3, LCD16x2 
LocalFileSystem local("local");
GPS gps(NC, GPSRX);
AnalogIn ain(p20); //temperature from LM35
PinDetect  modeButton(p13);
PinDetect  plusButton(p14);
PinDetect  minButton(p15);

// heartbeat
DigitalOut led1(LED1);
// 0.05 second flash of LED2
DigitalOut led2(LED2);
Timeout t2;

// 0.05 second flash of LED3
DigitalOut led3(LED3);
Timeout t3;

// 0.05 second flash of LED4
DigitalOut led4(LED4);
Timeout t4;

int gprmc_c = 0;


int mode = modeAzimuth;

SatelliteList slist("/local/SAT.TXT",';');
Satellite *s;
pos_t pos;

const float G = 6.67421e-11; // ( m�/kg/s�)
const float Mr = 5.9736e24;  // Mass of Earth (Kg)
const float Rr = 6.378137e6; // Radius of Earth (m)
const float T = 23.934192*60*60; // the period of Earth rotation (s)

const float degreesPerRadian =  180/PI;
const float dr = PI/180;

const float r1 = ((G*Mr*T*T)/(4*PI*PI)); // the radius of the path of the geostatic satellite
const float r = pow(r1, float(1.0 / 3.0));
const float h = r - Rr; //  the height of the satelite
const float b = Rr/r;   // the geostationary orbit constant

void switch_mode(buttons);
void display_satellite();
void display_position();
void display_time();
void display_temperature();
void display_welcome();
void calculate_satellite();

void t2out(void) { led2 = 0; }
void blip2(void) { led2 = 1; t2.attach(&t2out, 0.05); }

void t3out(void) { led3 = 0; }
void blip3(void) { gprmc_c = 0;led3 = 1; t3.attach(&t3out, 0.05); }

void t4out(void) { led4 = 0; }
void blip4(void) { led4 = 1; t4.attach(&t4out, 0.05); }

void buttonModePressed( void ) {
    //led4 = !led4;
    mode = (((mode + 1) % 4));
    //printf("Mode button pressed %d \r\n", mode);
    switch_mode(buttonNone);
}

void buttonPlusPressed( void ) {
    //led4 = !led4;
    switch_mode(buttonPlus);
}

void buttonMinPressed( void ) {
    //led4 = !led4;
    switch_mode(buttonMin);
}

void switch_mode(buttons button)
{
   switch(mode)
   {
        case modeAzimuth:
            //printf("Azimuth mode \r\n");
            switch(button)
            {
                case buttonPlus:
                    s = slist.getNext();
                    break;
                case buttonMin:
                    s = slist.getPrev();
                    break;
                default:
                    break;
            }
            calculate_satellite();
            display_satellite();
            break;
        case modePosition:
            //printf("Position mode \r\n");
            display_position();
            break;
        case modeTime: 
            //printf("Time mode \r\n");
            display_time();
            break;
        case modeTemperature: 
            display_temperature();
            //printf("Temperature mode \r\n");
            break;
        default:
            //printf("Invalid mode \r\n");
            break;
    }
}

void calculate_satellite(){
    float denominator, B, Gc;
    float la,lo,ob,az,el;
    
    lo = pos.lo;
    la = pos.la;
    ob = s->getOrbit();
    pos.ob = ob;

    la = la * dr; //convert latitude observer from deg to rad
    B = (lo - ob) * dr; //longitude diff between satellite and observer
    Gc = cos(B) * cos(la); //Gc is the great circle angle between observer and satellite
    Gc = atan(sqrt(1 - Gc * Gc) / Gc);
    if (Gc < 1.419) {     //if greater than 81.3deg skip
        denominator = sin(la);
        if (denominator != 0.0) {
            az = atan(tan(B) / denominator); //compute azimuth angle
            if (la >= 0)  az = az + PI; //adjust for northern hemisphere   
        } else az = 0.0;
        el = (( (1.0 / b) * cos(la) * cos(B)) - 1);
        denominator = ( (1.0 /b) * sqrt(1-(pow(cos(la),2) * pow(cos(B),2))) );
           if (denominator!=0)
        {
            el/=denominator;
            el = atan(el);
        }       
        else el = PI/2;
    } else {
        az = 0.0;
        el = PI/2;
    }

    // convert from rad to deg
    az = az/dr; 
    el = el/dr;
    pos.az = az;
    pos.el = el;
    
    //printf("Azimuth observer =  %.2f \r\n", az);
    //printf("Elevation observer =  %.2f \r\n", el);

}

void display_satellite(){

    string sname;
    
    sname = s->getCname();

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("%.1f\xDF %s",pos.ob,sname.c_str()); //DF is the grade sign '&#65533;'
    lcd.locate(0,1);
    lcd.printf("A:%.1f\xDF",pos.az);
    lcd.printf(" E:%.1f\xDF",pos.el);
    //printf("Sat: %.2f LAT: %.2f LON: %.2f AZ: %.2f EL: %.2f tem: %.1f \r\n",pos.ob, pos.la, pos.lo, pos.az, pos.el, pos.tm);
 }
 
 void display_position(){

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("LAT: %.4f\xDF",pos.la); //DF is the grade sign '&#65533;'
    lcd.locate(0,1);
    lcd.printf("LON: %.4f\xDF",pos.lo);
 }
 
 void display_temperature(){

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Temp: %.1f\xDF",pos.tm); //DF is the grade sign '&#65533;'
 }
 
  void display_time(){

    GPS_Time now;
    gps.timeNow(&now);
    //printf("Time: %d-%d-%d %d:%d:%d UTC\r\n", now.day, now.month, now.year, now.hour, now.minute, now.second);
     
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Date: %d-%d-%d", now.day, now.month, now.year);
    lcd.locate(0,1);
    lcd.printf("Time: %d:%d:%d",now.hour, now.minute, now.second);
 }
 
 void display_welcome(){
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("SatGPS v1.0");
    lcd.locate(0,1);
    lcd.printf("4 PVDV");
 }


int main() {



    GPS_Time q1;
    GPS_VTG  v1;
    int gprmca_c; //Counter for the GPRMC 'Valid A' field

    pos.az = 0.0;
    pos.el = 0.0;
    pos.tm = 0.0;
    
    display_welcome();
    wait(2);

    
    //slist.display();    
    s = slist.getCurrent();

    
    gps.baud(GPSBAUD);
    gps.format(8, GPS::None, 1);   
    gps.attach_gga(&blip2);    
    // Sample of a callback to a function when a NMEA RMC message is recieved.    
    gps.attach_rmc(&blip3);
    
    //printf("Wait for the GPS NMEA data to become valid. \r\n");
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Waiting for");
    lcd.locate(0,1);
    lcd.printf("valid GPS signal");
    while (!gps.isTimeValid()) {
       //printf("%s \r\n",gps.buffer);
       led1 = !led1;
       wait(1);
    }
    
    modeButton.mode( PullDown );
    modeButton.attach_asserted( &buttonModePressed );
    minButton.mode( PullDown );
    minButton.attach_asserted( &buttonMinPressed );
    plusButton.mode( PullDown );
    plusButton.attach_asserted( &buttonPlusPressed );
    modeButton.setSampleFrequency(); 
    minButton.setSampleFrequency(); 
    plusButton.setSampleFrequency(); 
    led4 = 0;
    

    

        
    while(1) {
    
        wait(2);
        led1 = 1;
        //printf("%s \r\n",gps.buffer);
        
        
        if (gprmc_c > MAXGPRMC){
            lcd.cls();
            lcd.locate(0,0);
            lcd.printf("Lost connection");
            lcd.locate(0,1);
            lcd.printf("with GPS module");
        }
        else {
            if (!gps.isTimeValid()){
                gprmca_c++;
                if (gprmca_c > MAXGPRMCA) {
                    lcd.cls();
                    lcd.locate(0,0);
                    lcd.printf("Waiting for");
                    lcd.locate(0,1);
                    lcd.printf("valid GPS signal");
                }
                
            } else {
                
                gprmca_c = 0; //Resets the bad GPRMC counter
                // Grab a snapshot of the current time.
                gps.timeNow(&q1);
        
                // Grab velicity
                gps.vtg(&v1);
                             
                // Grab longitude, latitude and height
                pos.lo = gps.longitude();
                pos.la = gps.latitude();;
                pos.tm = ain.read() *330;
                
                switch_mode(buttonNone);
            }
        }
        
        gprmc_c++;
        led1 = 0;
    
       
    }
 

}