#define HORIZONTAL_SERVO_PIN 9

#include <Servo.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

TinyGPSPlus gps;
SoftwareSerial gpsSerial(RXPin, TXPin);

Servo horizontalServo;

const float latitudeReference = 37.7749; // Reference latitude for your location
const float longitudeReference = -122.4194; // Reference longitude for your location

void setup() {
  Serial.begin(9600);
  gpsSerial.begin(GPSBaud);
  
  horizontalServo.attach(HORIZONTAL_SERVO_PIN);
}

void loop() {
  while (gpsSerial.available() > 0) {
    if (gps.encode(gpsSerial.read())) {
      float horizontalAngle = calculateHorizontalAngle(gps.location.lat(), gps.location.lng());
      horizontalServo.write(horizontalAngle);
    }
  }
}

float calculateHorizontalAngle(float latitude, float longitude) {
  // Calculate the difference in longitude
  float deltaLongitude = longitude - longitudeReference;
  
  // Calculate the hour angle
  float hourAngle = 15 * deltaLongitude; // 15 degrees of longitude equals 1 hour
  
  // Calculate solar noon offset
  float solarNoonOffset = 12 - (longitude - longitudeReference) / 15;
  
  // Calculate solar time
  float solarTime = hour() + solarNoonOffset;
  
  // Calculate solar declination angle
  float solarDeclination = 23.45 * sin((360.0 / 365) * (dayOfYear() - 81));
  
  // Calculate solar elevation angle
  float solarElevation = asin(sin(degToRad(latitude)) * sin(degToRad(solarDeclination)) + cos(degToRad(latitude)) * cos(degToRad(solarDeclination)) * cos(degToRad(hourAngle)));
  
  // Calculate horizontal angle
  float horizontalAngle = radToDeg(solarElevation);
  
  return horizontalAngle;
}

float degToRad(float deg) {
  return deg * PI / 180;
}

float radToDeg(float rad) {
  return rad * 180 / PI;
}
