changeset 245:b1dc2ba9a315

Revise dedrift automatic slope update disable logic
author Daniele Nicolodi <daniele@grinta.net>
date Thu, 26 Feb 2015 23:11:01 +0100
parents 4db8746bd575
children d6a37eca6d92
files FXAnalyse.c
diffstat 1 files changed, 113 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/FXAnalyse.c	Thu Feb 26 23:10:06 2015 +0100
+++ b/FXAnalyse.c	Thu Feb 26 23:11:01 2015 +0100
@@ -358,10 +358,13 @@
 	int keep_slope;     // keep current slope value when dedrift is disabled
 	double f0;          // target frequency
 	double fDDS;        // DDS center frequency
-	double threshold;   // maximum allowed frequency change
 	double applied;     // currently applied slope
 	double interval;    // measurement duration
 	double t0;          // beginning of currrent measurement interval
+	double threshold;   // maximum allowed frequency change
+	int badcount;       // number of bad data points encountered consecutively
+	int badcountmax;    // maximum number of consecutive bad data points
+	int safety;         // stop slope update when too many consecutive bad data points are detected
 	struct stat stat;   // frequency mean and slope
 };
 
@@ -375,67 +378,121 @@
 	.keep_slope = TRUE,
 	.f0 = 0.0,
 	.fDDS = 70e6,
-	.threshold = 100.0,
 	.applied = 0.0,
 	.interval = 30.0,
 	.t0 = 0.0
+	.threshold = 10.0,
+	.badcount = 0,
+	.safety = TRUE,
+	.badcountmax = 10,
 };
 
 
+void dedrift_update_enable()
+{
+	logmsg("dedrift: automatic slope update enabled");
+	
+	dedrift.enabled = TRUE;
+	dedrift.t0 = utc;
+	stat_zero(&dedrift.stat);
+	dedrift.stat.previous = NaN;
+}
+
+
+void dedrift_update_disable()
+{
+	logmsg("dedrift: automatic slope update disabled");
+
+	dedrift.enabled = FALSE;
+	stat_zero(&dedrift.stat);
+
+	if (! dedrift.keep_slope) {
+		dedrift.applied = 0.0;
+		ad9956_set_sweep_rate_w(&ad9956, dedrift.applied);
+	}
+	if (! dedrift.keep_freq) {
+		ad9956_set_w(&ad9956, dedrift.fDDS, dedrift.applied);
+	}
+
+	SetCtrlVal(MainPanel, PANEL_SLOPE_APPLIED, dedrift.applied);
+	SetCtrlVal(MainPanel, PANEL_SLOPE_MEASURED, dedrift.stat.slope);
+	SetCtrlVal(MainPanel, PANEL_MEASURE_SLOPE, 0);
+}
+
+
+// Wrapper around stat_accumulate() that updates the statistic only if
+// the new datapoint `v` is within `threshold` from the data point
+// considered in the previous update. If the data point fails this
+// criteria it does not contribute to the collected statistics and the
+// previous data point is used instead and `count` is incremented by
+// one. If the data point is accepted `count` is reset to zero.
+int stat_accumulate_resilient(struct stat *stat, double v, double threshold, int *count)
+{
+	if ((! isnan(stat.previous) && (fabs(v - stat->previous) > threshold)) {
+		// bad data point
+		stat_accumulate(stat, stat->previous);
+		*count++;
+		return TRUE;
+	} else {
+		// good data point
+		stat_accumulate(stat, v);
+		*count = 0;
+		return FALSE;
+	}
+}
+
+
 void dedrift_update(double f)
-{
-	// stop dedrift if the comb is not locked
-	if ((dedrift.enabled) &&
-	    (dedrift.threshold != 0.0) &&
-	    (dedrift.stat.previous != 0.0) &&
-	    (fabs(f - dedrift.stat.previous) > dedrift.threshold)) {
+{	
+	if (! dedrift.enabled)
+		return;
+
+	// update measurement
+	stat_accumulate_resilient(&dedrift.stat, f, dedrift.threshold, &dedrift.badcount);
+	if (dedrift.badcount) {
+		// bad data point detected
+		logmsg("dedrift: bad data point detected");
 		
-		logmsg("dedrift stop: frequency jump detected");
-					
-		if (! dedrift.keep_slope) {
-			dedrift.applied = 0.0;
-			ad9956_set_sweep_rate_w(&ad9956, dedrift.applied);
-			SetCtrlVal(MainPanel, PANEL_SLOPE_APPLIED, dedrift.applied);
-		}
-		if (! dedrift.keep_freq) {
-			ad9956_set_w(&ad9956, dedrift.fDDS, dedrift.applied);
+		// too many consecutive bad data points detected
+		if ((dedrift.safety) && (dedrift.badcount > &dedrift.badcountmax)) {
+			dedrift_update_disable();
+			logmsg("dedrift: maximum number of consecutive bad data points exceeded");
 		}
-		
-		stat_zero(&dedrift.stat);
-		SetCtrlVal(MainPanel, PANEL_SLOPE_MEASURED, dedrift.stat.slope);
-		dedrift.enabled = FALSE;
-		SetCtrlVal(MainPanel, PANEL_MEASURE_SLOPE, 0);
 	}
-	
-	// dedrifting 
-	if (dedrift.enabled) {
 
-		// update measurement
-		stat_accumulate(&dedrift.stat, f);
-		SetCtrlVal(MainPanel, PANEL_SLOPE_MEASURED, dedrift.stat.slope);
-		
-		// update applied slope
-		if ((utc - dedrift.t0) > dedrift.interval) {
+	// check if the previous check disabled slope update
+	if (! dedrift.enabled)
+		return;
+	
+	// update display
+	SetCtrlVal(MainPanel, PANEL_SLOPE_MEASURED, dedrift.stat.slope);
+	
+	// update applied slope
+	if ((utc - dedrift.t0) > dedrift.interval) {
 			
-			// target frequency
-			if (dedrift.f0 == 0.0)
-				dedrift.f0 = dedrift.stat.mean;
-
-			// compute correction
-			double dt = utc - dedrift.t0;
-			double corr = dedrift.stat.slope \
-				+ dedrift.proportional * ((dedrift.stat.mean - dedrift.f0) / dt + 0.5 * dedrift.stat.slope);
-
-			// update
-			dedrift.applied += dedrift.sign * corr * (dedrift.x2 ? 2 : 1);
-			ad9956_set_sweep_rate_w(&ad9956, dedrift.applied);
-			SetCtrlVal(MainPanel, PANEL_SLOPE_APPLIED, dedrift.applied);
-			logmsg("dedrift update: correction=%+3e slope=%+3e", corr, dedrift.applied);
-
-			// start over
-			dedrift.t0 = utc;
-			stat_zero(&dedrift.stat);
-		}
+		// target frequency
+		if (dedrift.f0 == 0.0)
+			dedrift.f0 = dedrift.stat.mean;
+		
+		// compute correction
+		double dt = utc - dedrift.t0;
+		double corr = dedrift.stat.slope \
+			+ dedrift.proportional * ((dedrift.stat.mean - dedrift.f0) / dt + 0.5 * dedrift.stat.slope);
+		
+		// update
+		dedrift.applied += dedrift.sign * corr * (dedrift.x2 ? 2 : 1);
+		ad9956_set_sweep_rate_w(&ad9956, dedrift.applied);
+		SetCtrlVal(MainPanel, PANEL_SLOPE_APPLIED, dedrift.applied);
+		logmsg("dedrift: update correction=%+3e slope=%+3e", corr, dedrift.applied);
+		
+		// start over. keep track of the last updated data point to
+		// avoid gaps in the detectrion of bad data points based on
+		// threshold on the difference between current data point and
+		// previous one
+		double prev = dedrift.stat.previous;
+		stat_zero(&dedrift.stat);
+		dedrift.stat.previous = prev;
+		dedrift.t0 = utc;
 	}
 }
 
@@ -1891,28 +1948,13 @@
 int  CVICALLBACK CB_MeasureSlope (int panel, int control, int event, 
 		 void *callbackData, int eventData1, int eventData2)
 {
+	int enable;
 	switch (event)
 	{
 		case EVENT_COMMIT:
-			GetCtrlVal(panel, control, &dedrift.enabled);
-			if (dedrift.enabled) {
-				dedrift.t0 = utc;
-				stat_zero(&dedrift.stat);
-				logmsg("dedrift start");
-			} else {
-				if (! dedrift.keep_slope) {
-					dedrift.applied = 0.0;
-					ad9956_set_sweep_rate_w(&ad9956, dedrift.applied);
-					SetCtrlVal(MainPanel, PANEL_SLOPE_APPLIED, dedrift.applied);
-				}
-				if (! dedrift.keep_freq) {
-					ad9956_set_w(&ad9956, dedrift.fDDS, dedrift.applied);
-				}
-				stat_zero(&dedrift.stat);
-				SetCtrlVal(panel, PANEL_SLOPE_MEASURED, dedrift.stat.slope);
-				logmsg("dedrift stop");
-			}
-			break;
+			GetCtrlVal(panel, control, &enable);
+			enable ? dedrift_update_enable() : dedrift_update_disable();
+			break;			
 	}
 	return 0;
 }
@@ -1926,7 +1968,7 @@
 			dedrift.applied = 0.0; 
 			SetCtrlVal(panel, PANEL_SLOPE_APPLIED, dedrift.applied);
 			ad9956_set_w(&ad9956, dedrift.fDDS, dedrift.applied);
-			logmsg("dedrift reset");
+			logmsg("dedrift: reset");
 			break;
 	}
 	return 0;
@@ -1997,8 +2039,7 @@
 	switch (event)
 	{
 		case EVENT_COMMIT:
-			GetCtrlVal(panel, control, &value);
-			dedrift.threshold = value ? 100.0 : 0.0;
+			GetCtrlVal(panel, control, &dedrift.safety);
 			break;
 	}
 	return 0;