Hi All
Slowly getting through a program that will control a dual axis solar tracker.
I would like to call the function "homing()" from my main loop if a condition is met within the function "printTime()". I have tried declaring variables to "someTime.Hour" etc but keep getting errors stating the variables within "sometime" are not class int's.
The code on line 141 in printTime() works but would rather have this within the main loop.
Any help would be appreciated.`
#include <SolarPosition.h>
#include <DS1307RTC.h>
const uint8_t digits = 3;
// some test positions:
SolarPosition Home(42.898551, -12.539774); // Home//RTC CODE
int sun_position;
int someTime;
const int encoder_a = 2; // Green - pin 2 - Digital
const int encoder_b = 3; // White - pin 3 - Digital
long encoder = 690;
int trackerAzimuthAngle;
int start=0;
int limitSwitchPin = 8;
int azLimitSwitch = 0;
const int azMotorPinPositive = 11;
const int azMotorPinNegative = 12;
int hours; int minutes; int seconds;
void setup() {
Serial.begin(9600);
pinMode(encoder_a, INPUT_PULLUP);
pinMode(encoder_b, INPUT_PULLUP);
attachInterrupt(0, encoderPinChangeA, CHANGE);
attachInterrupt(1, encoderPinChangeB, CHANGE);
pinMode(13, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(limitSwitchPin, INPUT);
pinMode(azMotorPinPositive, OUTPUT);
pinMode(azMotorPinNegative, OUTPUT);
// set the Time service as the time provider//RTC CODE
SolarPosition::setTimeProvider(RTC.get);
}
void loop() {
azLimitSwitch = digitalRead(limitSwitchPin);
if(start<1){
homing();
} // Send tracker back to home position if power enabled
start ++;
rtcCode();
delay(1000);
}
void homing() {
digitalWrite(azMotorPinNegative, HIGH);
digitalWrite(azMotorPinPositive, HIGH);
while(digitalRead(limitSwitchPin) == HIGH) {
Serial.print("HOMING");// Change this to move the motor
Serial.print('\n');
digitalWrite(azMotorPinNegative, LOW);
}
digitalWrite(azMotorPinNegative, HIGH);
while(digitalRead(limitSwitchPin) == LOW){
Serial.print("BACKING OFF");//Change this to move motor
Serial.print('\n');
digitalWrite(azMotorPinPositive, LOW);
encoder = 0;// Check this in main program
}
digitalWrite(azMotorPinPositive, HIGH);
}
void running(){
trackerAzimuthAngle = encoder/6.7;//change to degrees
if(sun_position > trackerAzimuthAngle){
digitalWrite(azMotorPinPositive, LOW);}
else{digitalWrite(11, HIGH);}
Serial.print("start ");
Serial.print(start);
Serial.print('\n');//establish if the program has just started
Serial.print("Tracker Azimuth Angle = ");
Serial.println(trackerAzimuthAngle);
}
void rtcCode(){
printTime(RTC.get());
Serial.print(F("Home:\t"));
printSolarPosition(Home.getSolarPosition(), digits);
Serial.println();
Serial.print('\n');
}
void encoderPinChangeA() {
encoder += digitalRead(encoder_a) == digitalRead(encoder_b) ? -1 : 1;
}
void encoderPinChangeB() {
encoder += digitalRead(encoder_a) != digitalRead(encoder_b) ? -1 : 1;
}
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"));
sun_position=(pos.azimuth);
}
void printTime(time_t t)
{
tmElements_t someTime;
breakTime(t, someTime);
Serial.print(someTime.Hour);
Serial.print(F(":"));
Serial.print(someTime.Minute);
Serial.print(F(":"));
Serial.print(someTime.Second);
Serial.print(F(" UTC 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));
if(someTime.Hour == 12 && someTime.Minute == 25 && someTime.Second == 0){
homing();// Time to be set when tracker goes back to home position.
}
if(someTime.Hour > 7){
running();
Serial.print("RUNNING "); Serial.print('\n');}
else{Serial.print("Waiting ");Serial.print('\n');
}
}
can miss the exact second you are looking for if things don't work out quite right. The if might not be see for a period greater than once second.
What to do?
Look instead for the exact minute, and provide a mechanism so you only do the thing once, like a flag that says you've homed or whatever homing() does.
Reset the flag, here just a Boolean variable, when the minute is 40.
Or something like that.
Best: lose the one second delay. With the time available, you could just watch the seconds and see when it changed. Then the intent of the one second delay would be implemented exactly; the code would run once every time the seconds changes, right on time.
And if the loop is running freely and frequently, tests for absolute to the second times would need no more than the if statement as you wrote it. No statements in the loop will execute at the same time as least time through.
Yes thank you.
I used the seconds to stop the code repeating but as you said a Bool would be a better way.
The delay(1000) is only for testing and will be removed once the code is completed.
Thanks for your help.