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 '�' 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 '�' 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 '�' } 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; } }