Calculates azimuth and elevation of a satellite dish based on its longitude, latitude and selected satellite.
Dependencies: PinDetect TextLCD mbed MODGPS
Diff: main.cpp
- 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 '�' + 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; + + + } + + +}