/// <summary> /// Perfrom Y-factor calibration /// </summary> /// <param name="calParams"></param> /// <param name="sysMessage"></param> /// <param name="yFactorCal"></param> public void PerformCal(SweepParams calParams, SysMessage sysMessage, out YfactorCal yFactorCal) { List <double> powerListNdOn = new List <double>(); List <double> powerListNdOff = new List <double>(); calParams.MinAtten = calParams.Attenuation; calParams.MaxAtten = calParams.Attenuation; // set filter bool err = SetFilter(calParams.sys2Detect); if (err) { yFactorCal = null; return; } sysMessage.calibration.temp = preselector.GetTemp(); // perfrom cal for number of attenuations // IS THIS necessary??? //int iterations = 1 + // (measParams.MaxAtten - measParams.Attenuation) // / measParams.StepAtten; //for (int i = 0; i < iterations; i++) //{ FFTParams fftParams = new FFTParams(sensorCapabilities, calParams, possibleSampleRates, possibleSpans); if (fftParams.Error) { Utilites.LogMessage("error calculating FFT Params"); yFactorCal = null; return; } // load sysMessage with fftParams and perfrom sweep for cal fftParams.LoadMessage(sysMessage); // Perform sweep with calibrated noise source on preselector.SetNdIn(); preselector.PowerOnNd(); err = DetectSpan(fftParams, calParams, powerListNdOn, null, null); if (err) { yFactorCal = null; return; } // perfrom sweep with calibrated noise source off preselector.PowerOffNd(); err = DetectSpan(fftParams, calParams, powerListNdOff, null, null); if (err) { yFactorCal = null; return; } // Y-Factor Calibration if (powerListNdOff.Count != powerListNdOn.Count) // sanity check { Utilites.LogMessage("Error getting sweep data. " + "Noise diode on and off power list are different sizes"); yFactorCal = null; return; } yFactorCal = new YfactorCal(powerListNdOn, powerListNdOff, (double)sysMessage.calibration.measurementParameters.resolutionBw, (double)sysMessage.calibration.measurementParameters.equivalentNoiseBw, calParams.DwellTime, sysMessage.preselector.excessNoiseRatio, sysMessage.antenna.cableLoss, sysMessage.antenna.gain); sysMessage.calibration.processed = true; sysMessage.gain = yFactorCal.GainDbw; sysMessage.noiseFigure = yFactorCal.NoseFigureDbw; }
/// <summary> /// /// </summary> public static void MainLoop() { // verify needed paths exists if (!Directory.Exists(Constants.MESSAGE_FILES_DIR)) { Directory.CreateDirectory(Constants.MESSAGE_FILES_DIR); } if (!Directory.Exists(Constants.LOG_FILE_DIR)) { Directory.CreateDirectory(Constants.LOG_FILE_DIR); } JavaScriptSerializer serializer = new JavaScriptSerializer(); Config config = serializer.Deserialize <Config>( File.ReadAllText(Constants.ConfigFile)); SensorDriver sensor = new SensorDriver(config.PreselectorIp, config.SensorHostName); TimedCount timer = new TimedCount(); Stopwatch stopwatch = new Stopwatch(); bool initialCalComplete = false; YfactorCal yFactorCal = null; int numOfMeasurements = 0; // create and write initial location message string locString = File.ReadAllText(Constants.LocMessage); LocMessage locMessage = serializer.Deserialize <LocMessage>(locString); locMessage.loadMessageFields(); Utilites.WriteMessageToFile(locMessage); while (true) { if (timer.elaspedTime() >= SECONDS_IN_HOUR || !initialCalComplete) { // reset stopwatch to zero but do not start stopwatch.Reset(); // read in parameters for calibration SweepParams calParams; string jsonString = File.ReadAllText(Constants.Spn43CalSweepParamsFile); calParams = serializer.Deserialize <SweepParams>( jsonString); SysMessage sysMessage = new SysMessage(); sysMessage.loadMessageFields(); sysMessage.version = config.Version; sysMessage.calibration.byteOrder = config.ByteOrder; sysMessage.calibration.compression = config.Compression; sysMessage.calibration.dataType = config.DataType; sysMessage.calibration.numOfMeasurementsPerCal = numOfMeasurements; sysMessage.calibration.measurementType = calParams.MeasurementType; sysMessage.calibration.calsPerHour = Constants.CALS_PER_HOUR; sysMessage.calibration.compression = Constants.COMPRESSION; sysMessage.calibration.byteOrder = Constants.BYTE_ORDER; sysMessage.calibration.dataType = Constants.DATA_TYPE; sysMessage.calibration.measurementParameters.detector = calParams.Detector; sysMessage.calibration.measurementParameters.window = calParams.Window; sysMessage.calibration.measurementParameters.attenuation = calParams.Attenuation; sysMessage.calibration.measurementParameters.videoBw = -1; sysMessage.calibration.measurementParameters.dwellTime = calParams.DwellTime; // if yFactorCall == null and error occured while performing cal sensor.PerformCal(calParams, sysMessage, out yFactorCal); if (yFactorCal == null) { Utilites.LogMessage("Error performing calibration, " + "cal aborted"); // don't write message, start the loop again continue; } Utilites.WriteMessageToFile(sysMessage); initialCalComplete = true; timer.reset(); numOfMeasurements = 0; } else { // need to have completed cal to perform sweep if (yFactorCal == null) { continue; } // get last time from stop watch TimeSpan elapsedTime = stopwatch.Elapsed; stopwatch.Restart(); SweepParams sweepParams; string jsonString = File.ReadAllText(Constants.Spn43MeasurementFile); sweepParams = serializer.Deserialize <SweepParams>( jsonString); DataMessage dataMessage = new DataMessage(); dataMessage.loadMessageFields(); dataMessage.version = config.Version; dataMessage.byteOrder = config.ByteOrder; dataMessage.dataType = config.DataType; dataMessage.comment = config.Compression; dataMessage.timeBetweenAcquisitions = elapsedTime.TotalSeconds; dataMessage.sysToDetect = sweepParams.sys2Detect; dataMessage.measurementType = sweepParams.MeasurementType; dataMessage.compression = Constants.COMPRESSION; dataMessage.dataType = Constants.DATA_TYPE; dataMessage.byteOrder = Constants.BYTE_ORDER; dataMessage.measurementParameters.attenuation = sweepParams.Attenuation; dataMessage.measurementParameters.detector = sweepParams.Detector; dataMessage.measurementParameters.dwellTime = sweepParams.DwellTime; dataMessage.measurementParameters.window = sweepParams.Window; bool err = sensor.PerformMeasurement(sweepParams, dataMessage, yFactorCal); if (err) { throw new Exception("Error performing measurement"); // don't write message, start the loop again continue; } numOfMeasurements++; Utilites.WriteMessageToFile(dataMessage); } } }
//} /// <summary> /// Performs a multi-segment detection with a Keysight N6841A sensor /// and applies variable attenuation when overload occurs. /// </summary> /// <param name="sweepParams"></param> /// <param name="dataMessage"></param> public bool PerformMeasurement(SweepParams sweepParams, DataMessage dataMessage, YfactorCal yFactorCal) { SetFilter(sweepParams.sys2Detect); preselector.SetRfIn(); preselector.PowerOffNd(); FFTParams fftParams = new FFTParams(sensorCapabilities, sweepParams, possibleSampleRates, possibleSpans); if (fftParams.Error) { Utilites.LogMessage("error calculating FFT Params"); return(true); } fftParams.LoadMessage(dataMessage); // set filter bool err = SetFilter(sweepParams.sys2Detect); List <double> powerList = new List <double>(); List <double> frequencyList = new List <double>(); List <int> attenList = Enumerable.Repeat(sweepParams.Attenuation, (int)fftParams.NumSegments).ToList(); // detect over span for (int i = 0; i < fftParams.NumSegments; i++) { double cf = fftParams.CenterFrequencies[i]; uint numFftsToCopy; if (i == fftParams.NumFullSegments) { numFftsToCopy = fftParams.NumBinsLastSegment; } else { numFftsToCopy = fftParams.NumValidFftBins; } sweepParams.Attenuation = 0; // set attenuation back to its initial value. Hardcodded to 0 for testing purpose if (sweepParams.DynamicAttenuation) { bool overload = true; while (overload && attenList[i] <= MAX_ATTEN) { err = DetectSegment(sweepParams, fftParams, powerList, frequencyList, cf, numFftsToCopy, ref overload); if (err) { return(true); } if (overload) { dataMessage.overloadFlag = true; sweepParams.Attenuation += sweepParams.StepAtten; attenList[i] = sweepParams.Attenuation; } // remove previous duplicated segment int indexDuplicate = 0; foreach (double number in frequencyList) { if (number == frequencyList[frequencyList.Count - 1]) { indexDuplicate = frequencyList.IndexOf(number); if (indexDuplicate == frequencyList.Count - 1) { indexDuplicate = 0; } break; } } if (indexDuplicate != 0) { frequencyList.RemoveRange(indexDuplicate - Convert.ToInt32(numFftsToCopy) + 1, Convert.ToInt32(numFftsToCopy)); powerList.RemoveRange(indexDuplicate - Convert.ToInt32(numFftsToCopy) + 1, Convert.ToInt32(numFftsToCopy)); } // end removing } } else { bool overload = false; err = DetectSegment(sweepParams, fftParams, powerList, frequencyList, cf, numFftsToCopy, ref overload); if (err) { return(true); } if (overload) { dataMessage.overloadFlag = true; } } } List <double> measuredPowers = new List <double>(); // Init antenna class to access cable loss and antenna gain string antennaString = File.ReadAllText(Constants.AntennaFile); SysMessage.Antenna antenna = new JavaScriptSerializer().Deserialize <SysMessage.Antenna>( antennaString); // reference power levels to input of isotropic antenna for (int i = 0; i < powerList.Count; i++) { measuredPowers.Add( powerList[i] + antenna.cableLoss - antenna.gain - yFactorCal.GainDbw[i]); } dataMessage.processed = true; dataMessage.measuredPowers = measuredPowers; return(false); }