Trouble adding a library function to my code

Hi, I'm trying to make a GPS based solar tracker and want to use the hour angle at sunrise to trigger the tracker. This is what I've got till now:

#include <Dusk2Dawn.h>
#include <Servo.h>
#include <DS1307RTC.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

Servo servo1; //controls altitude

int Mins=0,Lastmin=0;
int lon, lat, diff,i,r,s,y,m,d;
SoftwareSerial mySerial(3, 2);

Adafruit_GPS GPS(&mySerial);

//conversion of degrees and minutes to decimal degrees
double convertDegMinToDecDeg (float degMin) 
  {
  double min = 0.0;
  double decDeg = 0.0;
 
  min = fmod((double)degMin, 100.0);
 
  degMin = (int) ( degMin / 100 );
  decDeg = degMin + ( min / 60 );
 
  return decDeg; 
}


void setup() 
{
  Serial.begin(115200);
  GPS.begin(9600);
  
   tmElements_t  tm;// specific time from RTC is initialized

 
  tm.Minute ;
  tm.Hour   ;
  tm.Day    ;
  tm.Month  ;
  tm.Year   ;
  time_t s_date = makeTime(tm);

y = GPS.year;
m = GPS.month;
d = GPS.day;
lon = convertDegMinToDecDeg(GPS.longitude);
lat= convertDegMinToDecDeg(GPS.latitude);
float diff = 5.30;

//calculation of sunrise and sunset as per data from GPS  
  Dusk2Dawn place(lon, lat, diff);
  int placeSunrise  = place.sunrise(y, m, d, false);
  int placeSunset   = place.sunset(y, m , d, false);
  
  char time1[6];
  Dusk2Dawn::min2str(time1, placeSunrise);
  Serial.println(time1); 

  char time2[6];
  Dusk2Dawn::min2str(time2, placeSunset);
  Serial.println(time2); 

placeSunrise = r;
placeSunset = s;

  servo1.attach(4);
  servo1.write(180);
  delay(500);

}
void loop()
{
  tmElements_t tm;
for (i=r; i<=s ; i+=5) 
{
  if(RTC.read(tm))
  {
 //controlled movement of motor and panel
    Mins = tm.Minute;
    delay(500);
    
    //9 am to 9:20 am
    if(Mins==200) servo1.write(5);
    if(Mins==220) servo1.write(10); 
    if(Mins==240) servo1.write(15);
    if(Mins==260) servo1.write(20);
    if(Mins==280) servo1.write(25);
    if(Mins==300) servo1.write(30);   
    if(Mins==320) servo1.write(35);
    if(Mins==340) servo1.write(40);
    if(Mins==360) servo1.write(45);
    if(Mins==380) servo1.write(50);
    if(Mins==400) servo1.write(55);   
    if(Mins==420) servo1.write(60);
    if(Mins==440) servo1.write(65);
    if(Mins==460) servo1.write(70);
    if(Mins==480) servo1.write(75);
    if(Mins==500) servo1.write(80);   
    if(Mins==520) servo1.write(85);
    if(Mins==540) servo1.write(90);
    //3 am to 3:20 am
  
  
  }
  if(i=s)
  {
  servo1.write(0);//move back to initial position
  }
 }
}

The Dusk2Dawn library is the one found here

I'm trying to include the hourAngleSunrise function in my setup and assign it to 'hour',to use in the loop.
I checked the .h file and it shows hourAngleSunrise is in the private part of the class; would that affect being able to add it in?
Any suggestions on how I can go about this are appreciated.

As the name indicates, private variables or functions are obfuscated - meaning you don’t see them outside the class itself. Move that to the public part in the library and you’ll have access.

Question is going to be how can you be sure this variable stays current, if it was private it means the developer did not make efforts to provide easy access and might have some special requirements/ side effects etc... so you need to read and understand the library to see how to use it (or test and cross fingers all goes well)

J-M-L:
As the name indicates, private variables or functions are obfuscated - meaning you don’t see them outside the class itself. Move that to the public part in the library and you’ll have access.

Question is going to be how can you be sure this variable stays current, if it was private it means the developer did not make efforts to provide easy access and might have some special requirements/ side effects etc... so you need to read and understand the library to see how to use it (or test and cross fingers all goes well)

Hi, I'll try moving the function to the public part and test it out. I'll also go over the library again, but from what I've seen, the function was easily accessible. Thanks a lot for your help!

I looked through that code, and it really is convoluted. Interestingly, the author of the library (not the author of the code) doesn't understand it (see comment below):

  jday    = jDay(y, m, d);
  timeUTC = sunriseSetUTC(isRise, jday, _latitude, _longitude);

  // Advance the calculated time by a fraction of itself. I've no idea what the
  // purpose of this is.
  newJday    = jday + timeUTC / (60 * 24);
  newTimeUTC = sunriseSetUTC(isRise, newJday, _latitude, _longitude);

You will find this library GitHub - KenWillmott/SolarPosition: Arduino Library to calculate the position of the sun relative to geographic coordinates much easier to use, as it gives the apparent sun position for any time of day, anywhere. I have tested the algorithm and it is accurate to better than 0.01 degree on Arduino with single precision floats (i.e. most of them).

Edit: I looked a bit more at the Dusk2Dawn code, and it calculates the solar position only at noon UTC, then uses that to determine sunrise and sunset. So it is not suitable for a solar tracker.

jremington:
I looked through that code, and it really is convoluted. Interestingly, the author of the library (not the author of the code) doesn't understand it (see comment below):

  jday    = jDay(y, m, d);

timeUTC = sunriseSetUTC(isRise, jday, _latitude, _longitude);

// Advance the calculated time by a fraction of itself. I've no idea what the
  // purpose of this is.
  newJday    = jday + timeUTC / (60 * 24);
  newTimeUTC = sunriseSetUTC(isRise, newJday, _latitude, _longitude);



You will find this library https://github.com/KenWillmott/SolarPosition much easier to use, as it gives the apparent sun position for any time of day, anywhere. I have tested the algorithm and it is accurate to better than 0.01 degree on Arduino with single precision floats (i.e. most of them).

Edit: I looked a bit more at the Dusk2Dawn code, and it calculates the solar position only at noon UTC, then uses that to determine sunrise and sunset. So it is not suitable for a solar tracker.

Thank you! I have been getting an exit status despite trying what @J-M-L had to say. I'll use the solar position library instead.

I have been getting an exit status despite trying what @J-M-L had to say

What modif did you perform? What error did you get?

J-M-L:
What modif did you perform? What error did you get?

I moved the private functions to the public part of the class in the Dusk2Dawn library and re-uploaded the modified library.

I'm not getting an error, just an exit status 1. An error would give me some understanding of where I'm going wrong, but as far as I can understand an exit status 1 is just a compiling or uploading error. I'm not even trying to upload the code, so it would indicate a compiling error right?

I'll be trying what @jremington suggested soon and see if that works.

You can turn on the verbose mode in the IDE preferences
Copy what the compiler error is.

Have you noticed the EDIT from @jremington

Edit: I looked a bit more at the Dusk2Dawn code, and it calculates the solar position only at noon UTC, then uses that to determine sunrise and sunset. So it is not suitable for a solar tracker

J-M-L:
You can turn on the verbose mode in the IDE preferences
Copy what the compiler error is.

Have you noticed the EDIT from @jremington

Yep, I've noticed the edit and switched my library to the one suggested.
The exact complier error (before switching libraries) was this:

/tmp/240567154/dawn2dusk_copy_/dawn2dusk_copy_.ino: In function 'void setup()':

/tmp/240567154/dawn2dusk_copy_/dawn2dusk_copy_.ino:70:1: error: expected initializer before 'placeSunrise'

placeSunrise = r;

^

exit status 1

After switching libraries, I can get the solar position accurately and am trying to get the hour angle from the declination.

OK - would need to see code to help out. if you feel good with the other library, then way to go

J-M-L:
OK - would need to see code to help out. if you feel good with the other library, then way to go

The code is the same as the one in my original post. The other library is working great and I've been able to define an hour angle function so my problem has more or less been solved. I'll have to upload and run the code before getting too happy, but a huge thank you to you and @jremington for helping me out!

well if this is the code at the top:

these part are useless as they don't do anything

  tm.Minute ;
  tm.Hour   ;
  tm.Day    ;
  tm.Month  ;
  tm.Year   ;

so I got rid of it.

s_date is not used

  tmElements_t  tm;// specific time from RTC is initialized
  time_t s_date = makeTime(tm);

This is weird, did you mean == ?     if (i = s) {

Once cleaned-up like this

#include <Dusk2Dawn.h>
#include <Servo.h>
#include <DS1307RTC.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

Servo servo1; //controls altitude

int Mins = 0, Lastmin = 0;
int lon, lat, diff, i, r, s, y, m, d;
SoftwareSerial mySerial(3, 2);

Adafruit_GPS GPS(&mySerial);

//conversion of degrees and minutes to decimal degrees
double convertDegMinToDecDeg (float degMin)
{
  double min = 0.0;
  double decDeg = 0.0;

  min = fmod((double)degMin, 100.0);

  degMin = (int) ( degMin / 100 );
  decDeg = degMin + ( min / 60 );

  return decDeg;
}


void setup()
{
  Serial.begin(115200);
  GPS.begin(9600);

  y = GPS.year;
  m = GPS.month;
  d = GPS.day;
  lon = convertDegMinToDecDeg(GPS.longitude);
  lat = convertDegMinToDecDeg(GPS.latitude);
  float diff = 5.30;

  //calculation of sunrise and sunset as per data from GPS
  Dusk2Dawn place(lon, lat, diff);
  int placeSunrise  = place.sunrise(y, m, d, false);
  int placeSunset   = place.sunset(y, m , d, false);

  char time1[6];
  Dusk2Dawn::min2str(time1, placeSunrise);
  Serial.println(time1);

  char time2[6];
  Dusk2Dawn::min2str(time2, placeSunset);
  Serial.println(time2);

  placeSunrise = r;
  placeSunset = s;

  servo1.attach(4);
  servo1.write(180);
  delay(500);

}
void loop()
{
  tmElements_t tm;
  for (i = r; i <= s ; i += 5)
  {
    if (RTC.read(tm))
    {
      //controlled movement of motor and panel
      Mins = tm.Minute;
      delay(500);

      //9 am to 9:20 am
      if (Mins == 200) servo1.write(5);
      if (Mins == 220) servo1.write(10);
      if (Mins == 240) servo1.write(15);
      if (Mins == 260) servo1.write(20);
      if (Mins == 280) servo1.write(25);
      if (Mins == 300) servo1.write(30);
      if (Mins == 320) servo1.write(35);
      if (Mins == 340) servo1.write(40);
      if (Mins == 360) servo1.write(45);
      if (Mins == 380) servo1.write(50);
      if (Mins == 400) servo1.write(55);
      if (Mins == 420) servo1.write(60);
      if (Mins == 440) servo1.write(65);
      if (Mins == 460) servo1.write(70);
      if (Mins == 480) servo1.write(75);
      if (Mins == 500) servo1.write(80);
      if (Mins == 520) servo1.write(85);
      if (Mins == 540) servo1.write(90);
      //3 am to 3:20 am
    }

    if (i == s) {
      servo1.write(0);//move back to initial position
    }
  }
}

the code compiles all fine.

Then I went to modify the Dusk2Dawn.h code to make hourAngleSunrise public

/*  Dusk2Dawn.h
 *  Get estimate time of sunrise and sunset given a set of coordinates.
 *  Created by DM Kishi <dm.kishi@gmail.com> on 2017-02-01.
 *  <https://github.com/dmkishi/Dusk2Dawn>
 */

#ifndef Dusk2Dawn_h
#define Dusk2Dawn_h

  #include "Arduino.h"
  #include <Math.h>

  class Dusk2Dawn {
    public:
      Dusk2Dawn(float, float, float);
      int sunrise(int, int, int, bool);
      int sunset(int, int, int, bool);
      static bool min2str(char*, int);
      float hourAngleSunrise(float, float); // <<--- MOVED TO PUBLIC 
    private:
      float _latitude, _longitude;
      int   _timezone;
      int   sunriseSet(bool, int, int, int, bool);
      float sunriseSetUTC(bool, float, float, float);
      float equationOfTime(float);
      float meanObliquityOfEcliptic(float);
      float eccentricityEarthOrbit(float);
      float sunDeclination(float);
      float sunApparentLong(float);
      float sunTrueLong(float);
      float sunEqOfCenter(float);

      float obliquityCorrection(float);
      float geomMeanLongSun(float);
      float geomMeanAnomalySun(float);
      float jDay(int, int, int);
      float fractionOfCentury(float);
      float radToDeg(float);
      float degToRad(float);
      static bool zeroPadTime(char*, byte);
  };

#endif

and recompiled, no issue...

so I'm not sure what you are facing...

J-M-L:
well if this is the code at the top:

these part are useless as they don't do anything

  tm.Minute ;

tm.Hour  ;
  tm.Day    ;
  tm.Month  ;
  tm.Year  ;




so I got rid of it.

`s_date` is not used

tmElements_t  tm;// specific time from RTC is initialized
  time_t s_date = makeTime(tm);




This is weird, did you mean == ? `    if (i = s) {` 

Once cleaned-up like this 

#include <Dusk2Dawn.h>
#include <Servo.h>
#include <DS1307RTC.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

Servo servo1; //controls altitude

int Mins = 0, Lastmin = 0;
int lon, lat, diff, i, r, s, y, m, d;
SoftwareSerial mySerial(3, 2);

Adafruit_GPS GPS(&mySerial);

//conversion of degrees and minutes to decimal degrees
double convertDegMinToDecDeg (float degMin)
{
  double min = 0.0;
  double decDeg = 0.0;

min = fmod((double)degMin, 100.0);

degMin = (int) ( degMin / 100 );
  decDeg = degMin + ( min / 60 );

return decDeg;
}

void setup()
{
  Serial.begin(115200);
  GPS.begin(9600);

y = GPS.year;
  m = GPS.month;
  d = GPS.day;
  lon = convertDegMinToDecDeg(GPS.longitude);
  lat = convertDegMinToDecDeg(GPS.latitude);
  float diff = 5.30;

//calculation of sunrise and sunset as per data from GPS
  Dusk2Dawn place(lon, lat, diff);
  int placeSunrise  = place.sunrise(y, m, d, false);
  int placeSunset  = place.sunset(y, m , d, false);

char time1[6];
  Dusk2Dawn::min2str(time1, placeSunrise);
  Serial.println(time1);

char time2[6];
  Dusk2Dawn::min2str(time2, placeSunset);
  Serial.println(time2);

placeSunrise = r;
  placeSunset = s;

servo1.attach(4);
  servo1.write(180);
  delay(500);

}
void loop()
{
  tmElements_t tm;
  for (i = r; i <= s ; i += 5)
  {
    if (RTC.read(tm))
    {
      //controlled movement of motor and panel
      Mins = tm.Minute;
      delay(500);

//9 am to 9:20 am
      if (Mins == 200) servo1.write(5);
      if (Mins == 220) servo1.write(10);
      if (Mins == 240) servo1.write(15);
      if (Mins == 260) servo1.write(20);
      if (Mins == 280) servo1.write(25);
      if (Mins == 300) servo1.write(30);
      if (Mins == 320) servo1.write(35);
      if (Mins == 340) servo1.write(40);
      if (Mins == 360) servo1.write(45);
      if (Mins == 380) servo1.write(50);
      if (Mins == 400) servo1.write(55);
      if (Mins == 420) servo1.write(60);
      if (Mins == 440) servo1.write(65);
      if (Mins == 460) servo1.write(70);
      if (Mins == 480) servo1.write(75);
      if (Mins == 500) servo1.write(80);
      if (Mins == 520) servo1.write(85);
      if (Mins == 540) servo1.write(90);
      //3 am to 3:20 am
    }

if (i == s) {
      servo1.write(0);//move back to initial position
    }
  }
}


the code compiles all fine. 

Then I went to modify the Dusk2Dawn.h code to make hourAngleSunrise public

/*  Dusk2Dawn.h
*  Get estimate time of sunrise and sunset given a set of coordinates.
*  Created by DM Kishi dm.kishi@gmail.com on 2017-02-01.
https://github.com/dmkishi/Dusk2Dawn
*/

#ifndef Dusk2Dawn_h
#define Dusk2Dawn_h

#include "Arduino.h"
  #include <Math.h>

class Dusk2Dawn {
    public:
      Dusk2Dawn(float, float, float);
      int sunrise(int, int, int, bool);
      int sunset(int, int, int, bool);
      static bool min2str(char*, int);
      float hourAngleSunrise(float, float); // <<--- MOVED TO PUBLIC
    private:
      float _latitude, _longitude;
      int  _timezone;
      int  sunriseSet(bool, int, int, int, bool);
      float sunriseSetUTC(bool, float, float, float);
      float equationOfTime(float);
      float meanObliquityOfEcliptic(float);
      float eccentricityEarthOrbit(float);
      float sunDeclination(float);
      float sunApparentLong(float);
      float sunTrueLong(float);
      float sunEqOfCenter(float);

float obliquityCorrection(float);
      float geomMeanLongSun(float);
      float geomMeanAnomalySun(float);
      float jDay(int, int, int);
      float fractionOfCentury(float);
      float radToDeg(float);
      float degToRad(float);
      static bool zeroPadTime(char*, byte);
  };

#endif


and recompiled, no issue... 

so I'm not sure what you are facing...

Ok so, I removed the parts you mentioned and cleaned up the code a bit. It's compiling fine. Thank you.

cool :slight_smile: