diff --git a/kstars/ekos/capture/capture.h b/kstars/ekos/capture/capture.h
--- a/kstars/ekos/capture/capture.h
+++ b/kstars/ekos/capture/capture.h
@@ -458,6 +458,11 @@
//void updateAutofocusStatus(bool status, double HFR);
void startPostFilterAutoFocus();
+ // Timed refocus
+ void startRefocusEveryNTimer();
+ void restartRefocusEveryNTimer();
+ int getRefocusEveryNTimerElapsedSec();
+
// Flat field
void openCalibrationDialog();
IPState processPreCaptureCalibrationStage();
@@ -585,6 +590,11 @@
double focusHFR; // HFR value as received from the Ekos focus module
double fileHFR; // HFR value as loaded from the sequence file
+ // Refocus every N minutes
+ bool isRefocus;
+ int refocusEveryNMinutesValue; // number of minutes between forced refocus
+ QElapsedTimer refocusEveryNTimer; // used to determine when next force refocus should occur
+
//Meridan flip
double initialHA;
double initialRA;
diff --git a/kstars/ekos/capture/capture.cpp b/kstars/ekos/capture/capture.cpp
--- a/kstars/ekos/capture/capture.cpp
+++ b/kstars/ekos/capture/capture.cpp
@@ -53,7 +53,7 @@
#define MAX_CAPTURE_RETRIES 3
// Current Sequence File Format:
-#define SQ_FORMAT_VERSION 1.8
+#define SQ_FORMAT_VERSION 1.9
// We accept file formats with version back to:
#define SQ_COMPAT_VERSION 1.6
@@ -108,6 +108,8 @@
autoFocusStatus = false;
resumeAlignmentAfterFlip = false;
+ isRefocus = false;
+
mDirty = false;
jobUnderEdit = false;
currentFilterPosition = -1;
@@ -221,11 +223,13 @@
guideDeviationCheck->setChecked(Options::enforceGuideDeviation());
guideDeviation->setValue(Options::guideDeviation());
autofocusCheck->setChecked(Options::enforceAutofocus());
+ refocusEveryNCheck->setChecked(Options::enforceRefocusEveryN());
meridianCheck->setChecked(Options::autoMeridianFlip());
meridianHours->setValue(Options::autoMeridianHours());
useFITSViewerInCapture->setChecked(Options::useFITSViewerInCapture());
connect(autofocusCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty()));
+ connect(refocusEveryNCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty()));
connect(HFRPixels, SIGNAL(valueChanged(double)), this, SLOT(setDirty()));
connect(guideDeviationCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty()));
connect(guideDeviation, SIGNAL(valueChanged(double)), this, SLOT(setDirty()));
@@ -357,6 +361,8 @@
Options::setGuideDeviation(guideDeviation->value());
Options::setEnforceGuideDeviation(guideDeviationCheck->isChecked());
Options::setEnforceAutofocus(autofocusCheck->isChecked());
+ Options::setEnforceRefocusEveryN(refocusEveryNCheck->isChecked());
+
Options::setAutoMeridianFlip(meridianCheck->isChecked());
Options::setAutoMeridianHours(meridianHours->value());
Options::setUseFITSViewerInCapture(useFITSViewerInCapture->isChecked());
@@ -422,6 +428,10 @@
initialHA = getCurrentHA();
meridianFlipStage = MF_NONE;
+
+ // start timer to measure time until next forced refocus
+ startRefocusEveryNTimer();
+
// Check if we need to update the sequence directory numbers before starting
/*for (int i=0; i < jobs.count(); i++)
{
@@ -1313,6 +1323,16 @@
HFRPixels->setValue(fileHFR);
}
+ // check if time for forced refocus
+
+ if (Options::captureLogging())
+ qDebug() << "Elapsed Time (secs): " << getRefocusEveryNTimerElapsedSec() << " Requested Interval (secs): " << refocusEveryN->value()*60;
+
+ if (refocusEveryNCheck->isEnabled() && refocusEveryNCheck->isChecked() && getRefocusEveryNTimerElapsedSec() >= refocusEveryN->value()*60)
+ isRefocus = true;
+ else
+ isRefocus = false;
+
// If we suspended guiding due to primary chip download, resume guide chip guiding now
if (guideState == GUIDE_SUSPENDED && suspendGuideOnDownload)
emit resumeGuiding();
@@ -1327,6 +1347,18 @@
state = CAPTURE_DITHERING;
emit newStatus(Ekos::CAPTURE_DITHERING);
}
+ else if (isRefocus && activeJob->getFrameType() == FRAME_LIGHT)
+ {
+ appendLogText(i18n("Scheduled refocus started..."));
+
+ secondsLabel->setText(i18n("Focusing..."));
+
+ // force refocus
+ emit checkFocus(0.1);
+
+ state = CAPTURE_FOCUSING;
+ emit newStatus(Ekos::CAPTURE_FOCUSING);
+ }
else if (isAutoFocus && activeJob->getFrameType() == FRAME_LIGHT)
{
secondsLabel->setText(i18n("Focusing..."));
@@ -1499,6 +1531,8 @@
appendLogText(i18n("Dither complete."));
+ // FIXME ought to be able to combine these - only different is value passed
+ // to checkFocus()
if (isAutoFocus && autoFocusStatus == false)
{
secondsLabel->setText(i18n("Focusing..."));
@@ -1507,6 +1541,16 @@
emit newStatus(Ekos::CAPTURE_FOCUSING);
return true;
}
+ else if (isRefocus)
+ {
+ appendLogText(i18n("Scheduled refocus started..."));
+
+ secondsLabel->setText(i18n("Focusing..."));
+ emit checkFocus(0.1);
+ state = CAPTURE_FOCUSING;
+ emit newStatus(Ekos::CAPTURE_FOCUSING);
+ return true;
+ }
startNextExposure();
@@ -2059,6 +2103,15 @@
calibrationStage = CAL_NONE;
}
+ // If we haven't performed a single autofocus yet, we stop
+ if (!job->isPreview() && Options::enforceRefocusEveryN() && (isAutoFocus == false && firstAutoFocus == true))
+ {
+ appendLogText(i18n(
+ "Manual scheduled focusing is not supported. Run Autofocus process before trying again."));
+ abort();
+ return;
+ }
+
if (currentFilterPosition > 0)
{
// If we haven't performed a single autofocus yet, we stop
@@ -2371,8 +2424,14 @@
if (focusState == FOCUS_COMPLETE)
{
+ // enable option to have a refocus event occur if HFR goes over threshold
autofocusCheck->setEnabled(true);
HFRPixels->setEnabled(true);
+
+ // also set scheduled refocus enabled
+ refocusEveryNCheck->setEnabled(true);
+ refocusEveryN->setEnabled(true);
+
if (focusHFR > 0 && firstAutoFocus && HFRPixels->value() == 0 && fileHFR == 0)
{
firstAutoFocus = false;
@@ -2380,6 +2439,9 @@
// in case in-sequence-focusing is used.
HFRPixels->setValue(focusHFR + (focusHFR * (Options::hFRThresholdPercentage() / 100.0)));
}
+
+ // successful focus so reset elapsed time
+ restartRefocusEveryNTimer();
}
if (activeJob &&
@@ -2401,7 +2463,7 @@
return;
}
- if (isAutoFocus && activeJob && activeJob->getStatus() == SequenceJob::JOB_BUSY)
+ if ((isRefocus || isAutoFocus) && activeJob && activeJob->getStatus() == SequenceJob::JOB_BUSY)
{
if (focusState == FOCUS_COMPLETE)
{
@@ -2564,6 +2626,23 @@
else
autofocusCheck->setChecked(false);
}
+ else if (!strcmp(tagXMLEle(ep), "RefocusEveryN"))
+ {
+ if (!strcmp(findXMLAttValu(ep, "enabled"), "true"))
+ {
+ refocusEveryNCheck->setChecked(true);
+ int minutesValue = atof(pcdataXMLEle(ep));
+ if (minutesValue > 0)
+ {
+ refocusEveryNMinutesValue = minutesValue;
+ refocusEveryN->setValue(refocusEveryNMinutesValue);
+ }
+ else
+ refocusEveryNMinutesValue = 0;
+ }
+ else
+ refocusEveryNCheck->setChecked(false);
+ }
else if (!strcmp(tagXMLEle(ep), "MeridianFlip"))
{
if (!strcmp(findXMLAttValu(ep, "enabled"), "true"))
@@ -2880,6 +2959,8 @@
<< guideDeviation->value() << "" << endl;
outstream << ""
<< HFRPixels->value() << "" << endl;
+ outstream << ""
+ << refocusEveryN->value() << "" << endl;
outstream << ""
<< meridianHours->value() << "" << endl;
foreach (SequenceJob *job, jobs)
@@ -4547,4 +4628,20 @@
Options::setDefaultObserver(observerName);
}
+
+
+void Capture::startRefocusEveryNTimer()
+{
+ refocusEveryNTimer.restart();
+}
+
+void Capture::restartRefocusEveryNTimer()
+{
+ refocusEveryNTimer.restart();
+}
+
+int Capture::getRefocusEveryNTimerElapsedSec()
+{
+ return refocusEveryNTimer.elapsed()/1000;
+}
}
diff --git a/kstars/ekos/capture/capture.ui b/kstars/ekos/capture/capture.ui
--- a/kstars/ekos/capture/capture.ui
+++ b/kstars/ekos/capture/capture.ui
@@ -6,8 +6,8 @@
0
0
- 662
- 517
+ 707
+ 580
@@ -970,7 +970,7 @@
3
- -
+
-
false
@@ -992,7 +992,7 @@
- -
+
-
false
@@ -1056,32 +1056,32 @@
- -
-
+
-
+
false
- Abort sequence if guiding deviation exceed this value
+ Perform autofocusing once Half-Flux-Radius (HFR) value exceeds this limit
- Guiding Deviation <
-
-
- false
+ Autofocus if HFR >
- -
-
+
-
+
false
- Perform autofocusing once Half-Flux-Radius (HFR) value exceeds this limit
+ Abort sequence if guiding deviation exceed this value
- Autofocus if HFR >
+ Guiding Deviation <
+
+
+ false
@@ -1098,7 +1098,7 @@
- -
+
-
Number of images to capture
@@ -1111,6 +1111,39 @@
+ -
+
+
+ false
+
+
+ Refocus every
+
+
+
+ -
+
+
+ false
+
+
+ 1
+
+
+ 999
+
+
+ 60
+
+
+
+ -
+
+
+ minutes
+
+
+
diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg
--- a/kstars/kstars.kcfg
+++ b/kstars/kstars.kcfg
@@ -1443,6 +1443,15 @@
false
+
+
+ false
+
+
+
+ Sets the time interval before forced autofocus attempts during a capture sequence.
+ 60
+
If the target hour angle exceeds this value, Ekos will command a meridian flip and if successful it will resume guiding and capture operations.