Calculates azimuth and elevation of a satellite dish based on its longitude, latitude and selected satellite.
Dependencies: PinDetect TextLCD mbed MODGPS
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 '�' 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 '�' 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 '�' 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 }
Generated on Tue Jul 12 2022 21:03:40 by 1.7.2