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

Dependencies:   PinDetect TextLCD mbed MODGPS

Revision:
0:fe8decc6a938
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Mar 29 09:26:14 2012 +0000
@@ -0,0 +1,362 @@
+/*  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;
+    
+       
+    }
+ 
+
+}