// solarTimeRTC

// Arduino example sketch for SolarPosition library
//
// Calculate solar position from time and location information
// using an RTC as a time source.

// 2017 Ken Willmott
// Arduino library based on the program "Arduino Uno and Solar Position Calculations"
// (c) David R. Brooks, which can be found at http://www.instesre.org/ArduinoDocuments.htm
// and issued under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License:
// https://creativecommons.org/licenses/by-nc-nd/4.0/

// Simulation at https://wokwi.com/projects/362461186756144129
// Based on https://wokwi.com/projects/362382128060882945
// written for https://forum.arduino.cc/t/solar-position-library-for-solar-trackers/1116831/5

const byte azimuthStepPin = 6;
const byte azimuthDirPin = 5;
const byte elevationStepPin = 4;
const byte elevationDirPin = 3;
const int stepsPerRevolution = 3200; // 16x microstepping
// Note that for the Wokwi stepper simulation, I used "gearRatio":"16:1" in diagram.json
// versus the 16:1 microstepping in thr drivers because the motor sim 
// only displays 1/2 step microstepping  
// https://docs.wokwi.com/parts/wokwi-stepper-motor#simulation-behavior
// Also note the wiring order is a bit odd to get the initial position 
// to display 0° and to get the angle signs to match.  
// 
 
#include "SolarPosition.h"  // https://github.com/KenWillmott/SolarPosition

// choose your RTC library (DS1307 lib can also read from the DS3231 IC):

//#include <DS3232RTC.h>
#include <DS1307RTC.h> // https://github.com/PaulStoffregen/DS1307RTC
#include <AccelStepper.h> // http://www.airspayce.com/mikem/arduino/AccelStepper/

AccelStepper azimuthStepper(AccelStepper::DRIVER, azimuthStepPin, azimuthDirPin);
AccelStepper elevationStepper(AccelStepper::DRIVER, elevationStepPin, elevationDirPin);

// Wokwi sets the default RTC to match the local computer's system time,
// if your local computer's time is not UTC, you need an offset
const int localUtcOffsetHours = 4;// Adjust RTC from default Wokwi local time setting to UTC:

// number of decimal digits to print
const uint8_t digits = 3;

// some test positions:
SolarPosition Toronto(43.653109, -79.386304);  // Toronto, Canada
SolarPosition Timbuktu(16.775214, -3.007455); // Timbuktu, Mali, Africa
SolarPosition Melbourne(-37.668987, 144.841006); //Melbourne Airport (MEL)
SolarPosition Ulaanbaatar(47.847410, 106.769004); //Ulaanbaatar Airport (ULN)
SolarPosition NewportNews(37.1303, -76.5026); //NewportNews Airport (PHF)

// program begins

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\tSolar Position Demo"));
  if (localUtcOffsetHours != 0 ) { // make local/UTC adjustments
    unsigned long newTime = RTC.get() + 3600L * localUtcOffsetHours;
    RTC.set(newTime);
  }
  // set the Time service as the time provider
  SolarPosition::setTimeProvider(RTC.get);

  azimuthStepper.setMaxSpeed(200.0);
  azimuthStepper.setAcceleration(200.0);
  azimuthStepper.moveTo(0);

  elevationStepper.setMaxSpeed(200.0);
  elevationStepper.setAcceleration(200.0);
  elevationStepper.moveTo(0);
}



void loop()
{
  // now test the real time methods:
  //
  const uint32_t moveInterval = 15000l;
  static uint32_t lastMoveTime = -(moveInterval -1000);
  uint32_t now = millis();

  azimuthStepper.run();
  elevationStepper.run();


  if (now - lastMoveTime >= moveInterval) {
    lastMoveTime += moveInterval;
    Serial.println();

    printTime(RTC.get());

    Serial.print(F("Toronto:\t"));
    printSolarPosition(Toronto.getSolarPosition(), digits);
    Serial.print(F("Melbourne:\t"));
    printSolarPosition(Melbourne.getSolarPosition(), digits);
    Serial.print(F("Timbuktu:\t"));
    printSolarPosition(Timbuktu.getSolarPosition(), digits);
    Serial.print(F("Ulaanbaatar:\t"));
    printSolarPosition(Ulaanbaatar.getSolarPosition(), digits);
    Serial.print(F("Newport News:\t"));
    printSolarPosition(NewportNews.getSolarPosition(), digits);

    azimuthStepper.moveTo(stepsPerRevolution * ( -NewportNews.getSolarAzimuth()) / 360.0);
    elevationStepper.moveTo(stepsPerRevolution * ( -NewportNews.getSolarElevation()) / 360.0);

  }
}

// Print a solar position to serial
//
void printSolarPosition(SolarPosition_t pos, int numDigits)
{
  Serial.print(F("el: "));
  Serial.print(pos.elevation, numDigits);
  Serial.print(F(" deg\t"));

  Serial.print(F("az: "));
  Serial.print(pos.azimuth, numDigits);
  Serial.println(F(" deg"));
}

// Print a time to serial
//
void printTime(time_t t)
{
  tmElements_t someTime;
  breakTime(t, someTime);

  if (someTime.Hour < 10)Serial.print('0');
  Serial.print(someTime.Hour);
  Serial.print(F(":"));
  if (someTime.Minute < 10)Serial.print('0');
  Serial.print(someTime.Minute);
  Serial.print(F(":"));
  if (someTime.Second < 10)Serial.print('0');
  Serial.print(someTime.Second);
  Serial.print(localUtcOffsetHours == 0 ? F(" UTC on "): F(" LT on "));
  Serial.print(dayStr(someTime.Wday));
  Serial.print(F(", "));
  Serial.print(monthStr(someTime.Month));
  Serial.print(F(" "));
  Serial.print(someTime.Day);
  Serial.print(F(", "));
  Serial.println(tmYearToCalendar(someTime.Year));
}
GND5VSDASCLSQWRTCDS1307+
A4988
A4988
Azimuth
Elevation
Solar Tracker/Compass (Aim Azimuth pointer at sun then is north is up^^^)