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

Dependencies:   PinDetect TextLCD mbed MODGPS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*  Satelitte Positioner
00002   *
00003   * Calculates azimuth and elevation of a satellite dish based on its longitude, latitude
00004   * and selected satellite.
00005   * see: http://www.alcyone.com/max/writing/essays/geostationary-orbits.html
00006   *      http://www.spaceacademy.net.au/watch/track/locgsat.htm
00007   *      http://www.dishpointer.com/
00008   *  
00009   * Copyright (c) 2012 Bart Janssens
00010   *
00011   * Permission is hereby granted, free of charge, to any person obtaining a copy
00012   * of this software and associated documentation files (the "Software"), to deal
00013   * in the Software without restriction, including without limitation the rights
00014   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00015   * copies of the Software, and to permit persons to whom the Software is
00016   * furnished to do so, subject to the following conditions:
00017   *
00018   * The above copyright notice and this permission notice shall be included in
00019   * all copies or substantial portions of the Software.
00020   *
00021   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00022   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00024   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00027   * THE SOFTWARE.
00028   */
00029 #include "mbed.h"
00030 
00031 #include "TextLCD.h"
00032 #include "PinDetect.h"
00033 #include "GPS.h"
00034 
00035 #include "SatGps.h"
00036 #include "SatelliteList.h"
00037 
00038 
00039 #define GPSRX p10
00040 #define GPSBAUD 4800
00041 
00042 #define MAXGPRMC 3
00043 #define MAXGPRMCA 4
00044 
00045 #define PI 3.14159265
00046 
00047 TextLCD lcd(p24, p26, p27, p28, p29, p30, TextLCD::LCD16x2 ); // rs, e, d0, d1, d2, d3, LCD16x2 
00048 LocalFileSystem local("local");
00049 GPS gps(NC, GPSRX);
00050 AnalogIn ain(p20); //temperature from LM35
00051 PinDetect  modeButton(p13);
00052 PinDetect  plusButton(p14);
00053 PinDetect  minButton(p15);
00054 
00055 // heartbeat
00056 DigitalOut led1(LED1);
00057 // 0.05 second flash of LED2
00058 DigitalOut led2(LED2);
00059 Timeout t2;
00060 
00061 // 0.05 second flash of LED3
00062 DigitalOut led3(LED3);
00063 Timeout t3;
00064 
00065 // 0.05 second flash of LED4
00066 DigitalOut led4(LED4);
00067 Timeout t4;
00068 
00069 int gprmc_c = 0;
00070 
00071 
00072 int mode = modeAzimuth;
00073 
00074 SatelliteList slist("/local/SAT.TXT",';');
00075 Satellite *s;
00076 pos_t pos;
00077 
00078 const float G = 6.67421e-11; // ( m�/kg/s�)
00079 const float Mr = 5.9736e24;  // Mass of Earth (Kg)
00080 const float Rr = 6.378137e6; // Radius of Earth (m)
00081 const float T = 23.934192*60*60; // the period of Earth rotation (s)
00082 
00083 const float degreesPerRadian =  180/PI;
00084 const float dr = PI/180;
00085 
00086 const float r1 = ((G*Mr*T*T)/(4*PI*PI)); // the radius of the path of the geostatic satellite
00087 const float r = pow(r1, float(1.0 / 3.0));
00088 const float h = r - Rr; //  the height of the satelite
00089 const float b = Rr/r;   // the geostationary orbit constant
00090 
00091 void switch_mode(buttons);
00092 void display_satellite();
00093 void display_position();
00094 void display_time();
00095 void display_temperature();
00096 void display_welcome();
00097 void calculate_satellite();
00098 
00099 void t2out(void) { led2 = 0; }
00100 void blip2(void) { led2 = 1; t2.attach(&t2out, 0.05); }
00101 
00102 void t3out(void) { led3 = 0; }
00103 void blip3(void) { gprmc_c = 0;led3 = 1; t3.attach(&t3out, 0.05); }
00104 
00105 void t4out(void) { led4 = 0; }
00106 void blip4(void) { led4 = 1; t4.attach(&t4out, 0.05); }
00107 
00108 void buttonModePressed( void ) {
00109     //led4 = !led4;
00110     mode = (((mode + 1) % 4));
00111     //printf("Mode button pressed %d \r\n", mode);
00112     switch_mode(buttonNone);
00113 }
00114 
00115 void buttonPlusPressed( void ) {
00116     //led4 = !led4;
00117     switch_mode(buttonPlus);
00118 }
00119 
00120 void buttonMinPressed( void ) {
00121     //led4 = !led4;
00122     switch_mode(buttonMin);
00123 }
00124 
00125 void switch_mode(buttons button)
00126 {
00127    switch(mode)
00128    {
00129         case modeAzimuth:
00130             //printf("Azimuth mode \r\n");
00131             switch(button)
00132             {
00133                 case buttonPlus:
00134                     s = slist.getNext();
00135                     break;
00136                 case buttonMin:
00137                     s = slist.getPrev();
00138                     break;
00139                 default:
00140                     break;
00141             }
00142             calculate_satellite();
00143             display_satellite();
00144             break;
00145         case modePosition:
00146             //printf("Position mode \r\n");
00147             display_position();
00148             break;
00149         case modeTime: 
00150             //printf("Time mode \r\n");
00151             display_time();
00152             break;
00153         case modeTemperature: 
00154             display_temperature();
00155             //printf("Temperature mode \r\n");
00156             break;
00157         default:
00158             //printf("Invalid mode \r\n");
00159             break;
00160     }
00161 }
00162 
00163 void calculate_satellite(){
00164     float denominator, B, Gc;
00165     float la,lo,ob,az,el;
00166     
00167     lo = pos.lo;
00168     la = pos.la;
00169     ob = s->getOrbit();
00170     pos.ob = ob;
00171 
00172     la = la * dr; //convert latitude observer from deg to rad
00173     B = (lo - ob) * dr; //longitude diff between satellite and observer
00174     Gc = cos(B) * cos(la); //Gc is the great circle angle between observer and satellite
00175     Gc = atan(sqrt(1 - Gc * Gc) / Gc);
00176     if (Gc < 1.419) {     //if greater than 81.3deg skip
00177         denominator = sin(la);
00178         if (denominator != 0.0) {
00179             az = atan(tan(B) / denominator); //compute azimuth angle
00180             if (la >= 0)  az = az + PI; //adjust for northern hemisphere   
00181         } else az = 0.0;
00182         el = (( (1.0 / b) * cos(la) * cos(B)) - 1);
00183         denominator = ( (1.0 /b) * sqrt(1-(pow(cos(la),2) * pow(cos(B),2))) );
00184            if (denominator!=0)
00185         {
00186             el/=denominator;
00187             el = atan(el);
00188         }       
00189         else el = PI/2;
00190     } else {
00191         az = 0.0;
00192         el = PI/2;
00193     }
00194 
00195     // convert from rad to deg
00196     az = az/dr; 
00197     el = el/dr;
00198     pos.az = az;
00199     pos.el = el;
00200     
00201     //printf("Azimuth observer =  %.2f \r\n", az);
00202     //printf("Elevation observer =  %.2f \r\n", el);
00203 
00204 }
00205 
00206 void display_satellite(){
00207 
00208     string sname;
00209     
00210     sname = s->getCname();
00211 
00212     lcd.cls();
00213     lcd.locate(0,0);
00214     lcd.printf("%.1f\xDF %s",pos.ob,sname.c_str()); //DF is the grade sign '&#65533;'
00215     lcd.locate(0,1);
00216     lcd.printf("A:%.1f\xDF",pos.az);
00217     lcd.printf(" E:%.1f\xDF",pos.el);
00218     //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);
00219  }
00220  
00221  void display_position(){
00222 
00223     lcd.cls();
00224     lcd.locate(0,0);
00225     lcd.printf("LAT: %.4f\xDF",pos.la); //DF is the grade sign '&#65533;'
00226     lcd.locate(0,1);
00227     lcd.printf("LON: %.4f\xDF",pos.lo);
00228  }
00229  
00230  void display_temperature(){
00231 
00232     lcd.cls();
00233     lcd.locate(0,0);
00234     lcd.printf("Temp: %.1f\xDF",pos.tm); //DF is the grade sign '&#65533;'
00235  }
00236  
00237   void display_time(){
00238 
00239     GPS_Time now;
00240     gps.timeNow(&now);
00241     //printf("Time: %d-%d-%d %d:%d:%d UTC\r\n", now.day, now.month, now.year, now.hour, now.minute, now.second);
00242      
00243     lcd.cls();
00244     lcd.locate(0,0);
00245     lcd.printf("Date: %d-%d-%d", now.day, now.month, now.year);
00246     lcd.locate(0,1);
00247     lcd.printf("Time: %d:%d:%d",now.hour, now.minute, now.second);
00248  }
00249  
00250  void display_welcome(){
00251     lcd.cls();
00252     lcd.locate(0,0);
00253     lcd.printf("SatGPS v1.0");
00254     lcd.locate(0,1);
00255     lcd.printf("4 PVDV");
00256  }
00257 
00258 
00259 int main() {
00260 
00261 
00262 
00263     GPS_Time q1;
00264     GPS_VTG  v1;
00265     int gprmca_c; //Counter for the GPRMC 'Valid A' field
00266 
00267     pos.az = 0.0;
00268     pos.el = 0.0;
00269     pos.tm = 0.0;
00270     
00271     display_welcome();
00272     wait(2);
00273 
00274     
00275     //slist.display();    
00276     s = slist.getCurrent();
00277 
00278     
00279     gps.baud(GPSBAUD);
00280     gps.format(8, GPS::None, 1);   
00281     gps.attach_gga(&blip2);    
00282     // Sample of a callback to a function when a NMEA RMC message is recieved.    
00283     gps.attach_rmc(&blip3);
00284     
00285     //printf("Wait for the GPS NMEA data to become valid. \r\n");
00286     lcd.cls();
00287     lcd.locate(0,0);
00288     lcd.printf("Waiting for");
00289     lcd.locate(0,1);
00290     lcd.printf("valid GPS signal");
00291     while (!gps.isTimeValid()) {
00292        //printf("%s \r\n",gps.buffer);
00293        led1 = !led1;
00294        wait(1);
00295     }
00296     
00297     modeButton.mode( PullDown );
00298     modeButton.attach_asserted( &buttonModePressed );
00299     minButton.mode( PullDown );
00300     minButton.attach_asserted( &buttonMinPressed );
00301     plusButton.mode( PullDown );
00302     plusButton.attach_asserted( &buttonPlusPressed );
00303     modeButton.setSampleFrequency(); 
00304     minButton.setSampleFrequency(); 
00305     plusButton.setSampleFrequency(); 
00306     led4 = 0;
00307     
00308 
00309     
00310 
00311         
00312     while(1) {
00313     
00314         wait(2);
00315         led1 = 1;
00316         //printf("%s \r\n",gps.buffer);
00317         
00318         
00319         if (gprmc_c > MAXGPRMC){
00320             lcd.cls();
00321             lcd.locate(0,0);
00322             lcd.printf("Lost connection");
00323             lcd.locate(0,1);
00324             lcd.printf("with GPS module");
00325         }
00326         else {
00327             if (!gps.isTimeValid()){
00328                 gprmca_c++;
00329                 if (gprmca_c > MAXGPRMCA) {
00330                     lcd.cls();
00331                     lcd.locate(0,0);
00332                     lcd.printf("Waiting for");
00333                     lcd.locate(0,1);
00334                     lcd.printf("valid GPS signal");
00335                 }
00336                 
00337             } else {
00338                 
00339                 gprmca_c = 0; //Resets the bad GPRMC counter
00340                 // Grab a snapshot of the current time.
00341                 gps.timeNow(&q1);
00342         
00343                 // Grab velicity
00344                 gps.vtg(&v1);
00345                              
00346                 // Grab longitude, latitude and height
00347                 pos.lo = gps.longitude();
00348                 pos.la = gps.latitude();;
00349                 pos.tm = ain.read() *330;
00350                 
00351                 switch_mode(buttonNone);
00352             }
00353         }
00354         
00355         gprmc_c++;
00356         led1 = 0;
00357     
00358        
00359     }
00360  
00361 
00362 }