// 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));
}
Azimuth
Elevation
Solar Tracker/Compass
(Aim Azimuth pointer at sun
then is north is up^^^)