diff --git a/GPSSpeedMultiCore.ino b/GPSSpeedMultiCore.ino index 1391af4..d3b20ee 100644 --- a/GPSSpeedMultiCore.ino +++ b/GPSSpeedMultiCore.ino @@ -5,6 +5,7 @@ #include "Adafruit_LEDBackpack.h" //for screen #include #include +#include //for determining startup brightness #define DISPLAY_ADDRESS 0x70 //I2C address of screen #define GPS_WAIT_TIME 1100 #define GPS_UPDATE_FREQUENCY 10 //GPS update frequency per sec @@ -13,6 +14,13 @@ //GPS SFE_UBLOX_GPS myGPS; +double lat = 0; +double lng = 0; +int tzOff = 12; //local TZ offset +bool centuryBit; //needed to get month from RTC +double az, elev; //for sun location in the sky +double transit, sunrise, sunset; //sun related times +double civilTransit, civilRiise, civilSet; //astro related times //threading std::atomic speed(0); @@ -29,10 +37,11 @@ unsigned long timeOfLastFix = 0UL; //button volatile bool buttonPushed = false; -volatile int screenBrightnessButton = 15; -volatile int screenBrightnessCurrent = screenBrightnessButton; +volatile int ScreenBrightnessUser = 15; +volatile int screenBrightnessCurrent = ScreenBrightnessUser; volatile unsigned long lastButtonPush = 0UL; + void chageBrightness() { if (millis() - lastButtonPush > DEBOUNCE_DELAY) { buttonPushed = true; @@ -42,14 +51,14 @@ void chageBrightness() { void connectGPS() { //need to do this everytime the GPS turns back on do { //set gps to 115200 baudrate code comes from sparkfun examples - Serial.println("GNSS: trying 115200 baud"); + // Serial.println("GNSS: trying 115200 baud"); Serial1.begin(115200); if (myGPS.begin(Serial1) == true) break; delay(100); - Serial.println("GNSS: trying 9600 baud"); + //Serial.println("GNSS: trying 9600 baud"); Serial1.begin(9600); if (myGPS.begin(Serial1) == true) { - Serial.println("GNSS: connected at 9600 baud, switching to 115200"); + // Serial.println("GNSS: connected at 9600 baud, switching to 115200"); myGPS.setSerialRate(115200); delay(100); } else { @@ -62,18 +71,33 @@ void connectGPS() { //need to do this everytime the GPS turns back on myGPS.setDynamicModel(DYN_MODEL_AUTOMOTIVE); //set dynamic model of GPS to automotive to more accutate results } +bool setStartBrightness() { + while (!(myGPS.getFixType() > 0)) {} + double GPSTime=myGPS.getHour()+(myGPS.getMinute()/60); + + //get sunset time + calcSunriseSunset(myGPS.getYear(), myGPS.getMonth(), myGPS.getDay(), lat, lng, transit, sunrise, sunset); + //get civilSet time + calcCivilDawnDusk(myGPS.getYear(), myGPS.getMonth(), myGPS.getDay(), lat, lng, civilTransit, civilRiise, civilSet); + + if(GPSTimesunrise)&&(GPSTimecivilSet){ + screenBrightnessCurrent=0; + } + disp.setBrightness(screenBrightnessCurrent); + return true; +} + void setup() { //setup screen Wire.setSCL(17); Wire.setSDA(16); //Wire.setClock(100000); disp.begin(DISPLAY_ADDRESS); - disp.setBrightness(screenBrightnessButton); - disp.clear(); - disp.writeDigitAscii(0, 71); //"G" - disp.writeDigitAscii(1, 80); //"P" - disp.writeDigitAscii(2, 83); //"S" - disp.writeDisplay(); + disp.setBrightness(ScreenBrightnessUser); //screen brightness pinMode(20, INPUT_PULLUP); @@ -86,30 +110,29 @@ void setup1() { Serial1.setRX(1); Serial1.setTX(0); connectGPS(); + setStartBrightness(); } void loop() { - - //change brightness if (buttonPushed == true) { - if (screenBrightnessButton == 15) { - screenBrightnessButton = MIDDLE_SCREEN_BRIGHTNESS; - } else if (screenBrightnessButton == MIDDLE_SCREEN_BRIGHTNESS) { - screenBrightnessButton = 0; + if (ScreenBrightnessUser == 15) { + ScreenBrightnessUser = MIDDLE_SCREEN_BRIGHTNESS; + } else if (ScreenBrightnessUser == MIDDLE_SCREEN_BRIGHTNESS) { + ScreenBrightnessUser = 0; } else { - screenBrightnessButton = 15; + ScreenBrightnessUser = 15; } - disp.setBrightness(screenBrightnessButton); - screenBrightnessCurrent=screenBrightnessButton; + disp.setBrightness(ScreenBrightnessUser); + screenBrightnessCurrent = ScreenBrightnessUser; buttonPushed = false; } disp.clear(); if (gpsFixType.load() > 0) { - if (screenBrightnessCurrent != screenBrightnessButton){ - disp.setBrightness(screenBrightnessButton); - screenBrightnessCurrent=screenBrightnessButton; + if (screenBrightnessCurrent != ScreenBrightnessUser) { + disp.setBrightness(ScreenBrightnessUser); + screenBrightnessCurrent = ScreenBrightnessUser; } timeOfLastFix = millis(); //reset no gps screen display int temp = speed.load() * 10; @@ -128,9 +151,9 @@ void loop() { disp.writeDigitAscii(2, 48 + digit2, true); disp.writeDigitAscii(3, 48 + digit3); } else { - if (screenBrightnessCurrent!=0){ + if (screenBrightnessCurrent != 0) { disp.setBrightness(0); - screenBrightnessCurrent=0; + screenBrightnessCurrent = 0; } unsigned long currentTime = millis(); unsigned long timeSinceLastFIx = timeOfLastFix - currentTime; diff --git a/sunriseSunset.h b/sunriseSunset.h new file mode 100644 index 0000000..6301ede --- /dev/null +++ b/sunriseSunset.h @@ -0,0 +1,142 @@ + +#include +//#define PI 3.1415926 +#define ZENITH -.83 + +/* zenith calc +offical = 90 degrees 50' +civil = 96 degrees +nautical = 102 degrees +astronomical = 108 degrees +http://edwilliams.org/sunrise_sunset_algorithm.htm +*/ +float calculateSunrise(int year,int month,int day,float lat, float lng,int localOffset, int daylightSavings) { + /* + localOffset will be <0 for western hemisphere and >0 for eastern hemisphere + daylightSavings should be 1 if it is in effect during the summer otherwise it should be 0 + */ + //1. first calculate the day of the year + float N1 = floor(275 * month / 9); + float N2 = floor((month + 9) / 12); + float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3)); + float N = N1 - (N2 * N3) + day - 30; + + //2. convert the longitude to hour value and calculate an approximate time + float lngHour = lng / 15.0; + float t = N + ((6 - lngHour) / 24); //if rising time is desired: + //float t = N + ((18 - lngHour) / 24) //if setting time is desired: + + //3. calculate the Sun's mean anomaly + float M = (0.9856 * t) - 3.289; + + //4. calculate the Sun's true longitude + float L = fmod(M + (1.916 * sin((PI/180)*M)) + (0.020 * sin(2 *(PI/180) * M)) + 282.634,360.0); + + //5a. calculate the Sun's right ascension + float RA = fmod(180/PI*atan(0.91764 * tan((PI/180)*L)),360.0); + + //5b. right ascension value needs to be in the same quadrant as L + float Lquadrant = floor( L/90) * 90; + float RAquadrant = floor(RA/90) * 90; + RA = RA + (Lquadrant - RAquadrant); + + //5c. right ascension value needs to be converted into hours + RA = RA / 15; + + //6. calculate the Sun's declination + float sinDec = 0.39782 * sin((PI/180)*L); + float cosDec = cos(asin(sinDec)); + + //7a. calculate the Sun's local hour angle + float cosH = (sin((PI/180)*ZENITH) - (sinDec * sin((PI/180)*lat))) / (cosDec * cos((PI/180)*lat)); + /* + if (cosH > 1) + the sun never rises on this location (on the specified date) + if (cosH < -1) + the sun never sets on this location (on the specified date) + */ + + //7b. finish calculating H and convert into hours + float H = 360 - (180/PI)*acos(cosH); // if if rising time is desired: + //float H = acos(cosH) // if setting time is desired: + H = H / 15; + + //8. calculate local mean time of rising/setting + float T = H + RA - (0.06571 * t) - 6.622; + + //9. adjust back to UTC + float UT = fmod(T - lngHour,24.0); + + //10. convert UT value to local time zone of latitude/longitude + return UT + localOffset + daylightSavings; + + } + float calculateSunset(int year,int month,int day,float lat, float lng,int localOffset, int daylightSavings) { + /* + localOffset will be <0 for western hemisphere and >0 for eastern hemisphere + daylightSavings should be 1 if it is in effect during the summer otherwise it should be 0 + */ + //1. first calculate the day of the year + float N1 = floor(275 * month / 9); + float N2 = floor((month + 9) / 12); + float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3)); + float N = N1 - (N2 * N3) + day - 30; + + //2. convert the longitude to hour value and calculate an approximate time + float lngHour = lng / 15.0; + //float t = N + ((6 - lngHour) / 24); //if rising time is desired: + float t = N + ((18 - lngHour) / 24); //if setting time is desired: + + //3. calculate the Sun's mean anomaly + float M = (0.9856 * t) - 3.289; + + //4. calculate the Sun's true longitude + float L = fmod(M + (1.916 * sin((PI/180)*M)) + (0.020 * sin(2 *(PI/180) * M)) + 282.634,360.0); + + //5a. calculate the Sun's right ascension + float RA = fmod(180/PI*atan(0.91764 * tan((PI/180)*L)),360.0); + + //5b. right ascension value needs to be in the same quadrant as L + float Lquadrant = floor( L/90) * 90; + float RAquadrant = floor(RA/90) * 90; + RA = RA + (Lquadrant - RAquadrant); + + //5c. right ascension value needs to be converted into hours + RA = RA / 15; + + //6. calculate the Sun's declination + float sinDec = 0.39782 * sin((PI/180)*L); + float cosDec = cos(asin(sinDec)); + + //7a. calculate the Sun's local hour angle + float cosH = (sin((PI/180)*ZENITH) - (sinDec * sin((PI/180)*lat))) / (cosDec * cos((PI/180)*lat)); + /* + if (cosH > 1) + the sun never rises on this location (on the specified date) + if (cosH < -1) + the sun never sets on this location (on the specified date) + */ + + //7b. finish calculating H and convert into hours + //float H = 360 - (180/PI)*acos(cosH); // if if rising time is desired: + float H = (180/PI)*acos(cosH);// if setting time is desired: + H = H / 15; + + //8. calculate local mean time of rising/setting + float T = H + RA - (0.06571 * t) - 6.622; + + //9. adjust back to UTC + float UT = fmod(T - lngHour,24.0); + + //10. convert UT value to local time zone of latitude/longitude + return UT + localOffset + daylightSavings; + + } +/* + void printSunrise() { + float localT = calculateSunrise(args); + double hours; + float minutes = modf(localT,&hours)*60; + printf("%.0f:%.0f",hours,minutes); + } + */ \ No newline at end of file