Better precision float?

So I'm trying to calculate sunrise and sunset using this:
Sunrise - Sunset

But having a hard time using float. The variables require more decimals than float apparently supports. Is there a data type or way to get something more precise than 6-7 digits?

There are other sunrise/set algorithms that work well with single precision floats. I don't recall at the moment which ones work, so you will have to try a few different ones.

If you're only concerned with one location, you could do the maths in an excel spreadsheet and then import it as a look up table. It would be much quicker.

This Arduino time library has sunrise and sunset calculations that are supposedly accurate. If you don't want the entire thing, you might cut out the rise/set code. I haven't tried it out.

I found some code that I had tested some time ago, and it works OK with single precision, with about 4 minutes accuracy at my location. See attached zip file.

sunrise.zip (2.05 KB)

So I’ve tried this two ways now:

This way I followed the sunrise.zip algorithm.

#include <Time.h>

void setup() {
  setTime(12, 0, 0, 2, 12, 2014);
  
  Serial.begin(9600);
  
  getSunrise();
}

void loop() {

}

void getSunrise() {
  float rd = 57.295779513082322;
  float lat = 34.8444;
  float lon = -82.3856;
  float tz = -5;
  
  float z = 90.5;
  float theHour = 255;
  float theMinute = 0;
  
  float y,decl, eqt, ha;
  unsigned char a;
  int doy, minutes, rs=1;
  
  a=6;
  doy=(month()-1)*30.3+day()-1;
  y = 1.721420632104e-02*(doy+a/24);
  eqt=229.18 * (0.000075+0.001868*cos(y)-0.032077*sin(y)-0.014615*cos(y*2)-0.040849*sin(y* 2));
  decl=0.006918-0.399912*cos(y)+0.070257*sin(y)-0.006758*cos(y*2)+0.000907*sin(y*2)-0.002697*cos(y*3)+0.00148*sin(y*3);
  Serial.print("doy: ");
  Serial.println(doy);
  Serial.print("y: ");
  Serial.println(y);
  Serial.print("eqt: ");
  Serial.println(eqt);
  Serial.print("decl: ");
  Serial.println(decl);
  
  ha=(cos(z)/(cos(lat)*cos(decl))-tan(lat)*tan(decl));
  ha=acos(ha);
  if(rs==0)
    ha=-ha;
  
  minutes = 720+4*(lon-ha)*rd-eqt;
  minutes += (tz*60);
  if(minutes<0)
    minutes += 1440;
  minutes %= 1440;
  
  theHour = minutes/60;
  theMinute = minutes-theHour*60;
  
  Serial.print("Hour: ");
  Serial.println(theHour);
  Serial.print("Minutes: ");
  Serial.println(theMinute);
}

I’m getting this in my Serial:

doy: 334
y: 5.75
eqt: 10.71
decl: -0.38
Hour: 19.00
Minutes: 0.00

Obviously this isn’t correct for sunrise. Googling the times for that day, I get 7:35a for sunrise for today and 5:24pm for sunset for the lat, long, and current date in the code. Obviously none of those are real close to 1900 hours so I’m not quite sure what’s going on here. Seems like the float limitations may have something to do with this.

The next code I tried was based off Arduino - Sunset/Sunrise

#include <Time.h>

void setup() {
  setTime(12, 0, 0, 26, 12, 2014);
  
  Serial.begin(9600);
  
  getSunTPoint(true);
  getSunTPoint(false);
}

void loop() {}

void getSunTPoint(boolean indicator) {
  float lat = 34.8444;
  float lon = -82.3856;
  float localOffset = -5;
  float zenith = 1.579522973054868;
  
  float Ni   = floor(275*month()/9);
  float Nii  = floor((month()+9)/12);
  float Niii = (1+floor((year()-4*floor(year()/4)+2)/3));
  float n = Ni-(Nii*Niii)+day()-30;
  
  float IngHour = lon / 15;
  
  float t;
  if(indicator)
    t = n+((6-IngHour)/24);
  else
    t = n+((18-IngHour)/24);
    
  float M = (0.9856*t)-3.289;
  
  float L = M+(1.916*sin(M))+(0.020*sin(2*M))+282.634;
    if(L<0)
      L+=360;
    if(L>=360)
      L-=360;
    //Potential add/sub 360
  
  float RA = atan(0.91764*tan(L));
    if(RA<0)
      RA+=360;
    if(RA>=360)
      RA-=360;
    //Potential add/sub 360
    
  float Lquadrant = (floor(L/90))*90;
  float RAquadrant = (floor(RA/90))*90;
  RA=RA+(Lquadrant-RAquadrant);
  
  RA=RA/15;
  
  float sinDec = 0.39782*sin(L);
  float cosDec = cos(asin(sinDec));
  
  float cosH = (cos(zenith)-(sinDec*sin(lat)))/(cosDec*cos(lat));
  
  if(cosH > 1)
    Serial.println("The sun never rises on this location.");
  if(cosH < -1)
    Serial.println("The sun never sets on this location.");
  
  float H;
  if(indicator)
    H = 360-acos(cosH);
  else
    H = acos(cosH);
    
  H = H/15;
    
  float T = H+RA-(0.06571*t)-6.622;
  
  float UT = T-IngHour;
    if(UT<0)
      UT+=24;
    if(UT>=24)
      UT-=24;
  
  float localT = UT + localOffset;
  
  Serial.println(localT);
}

And I get a result of this for the same credentials:

17.98
18.24

The top is suppose to be sunrise and the bottom is sunset. Unfortunately, I can’t quite figure out just exactly what these numbers mean. What I’ve learned is that there is in fact an algorithm out there, but either none of the ones I find work, or I’m doing something wrong. And since I’m not God, it’s probably the latter.

Any guidance would be awesome. I can’t find a library that can get it done yet, so I’m at the point of trying to perfect my own algorithm and still avoid the floating issue.
This is the closest algorithm I’ve found: sunrise-set, but that’s where I run into the floating issue. I’m not terribly concerned about absolute precision. Obviously the more precise the better, but being off a couple minutes or so shouldn’t bother my project all too much.