Exemplo n.º 1
0
        public static Dictionary <AnalogChannel, AnalogWaveProperties> MeasureAutoArrangeSettings(IScope scope, AnalogChannel aciveChannel, Action <float> progressReport)
        {
            float progress = 0f;

            progressReport(progress);

            //stop scope streaming
            scope.DataSourceScope.Stop();

            //Prepare scope for test
            if (scope is SmartScope)
            {
                (scope as SmartScope).SetDisableVoltageConversion(false);
            }

            //set to timerange wide enough to capture 50Hz, but slightly off so smallest chance of aliasing
            const float initialTimeRange = 0.0277f;

            scope.AcquisitionMode   = AcquisitionMode.AUTO;
            scope.AcquisitionLength = initialTimeRange;
            scope.SetViewPort(0, scope.AcquisitionLength);
            //s.AcquisitionDepth = 4096;
            scope.TriggerHoldOff     = 0;
            scope.SendOverviewBuffer = false;

            TriggerValue trigger = new TriggerValue()
            {
                mode    = TriggerMode.Edge,
                source  = TriggerSource.Channel,
                channel = AnalogChannel.ChA,
                edge    = TriggerEdge.RISING,
                level   = 5000,
            };

            scope.TriggerValue = trigger;

            foreach (AnalogChannel ch in AnalogChannel.List)
            {
                scope.SetCoupling(ch, Coupling.DC);
            }

            scope.CommitSettings();
            progress += .1f;
            progressReport(progress);
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // VERTICAL == VOLTAGE

            //set to largest input range
            float maxRange = 1.2f / 1f * 36f;

            foreach (AnalogChannel ch in AnalogChannel.List)
            {
                scope.SetVerticalRange(ch, -maxRange / 2f, maxRange / 2f);
            }

            float[] minValues = new float[] { float.MaxValue, float.MaxValue };
            float[] maxValues = new float[] { float.MinValue, float.MinValue };
            //measure min and max voltage over 3 full ranges
            for (int i = -1; i < 2; i++)
            {
                progress += .1f;
                progressReport(progress);

                foreach (AnalogChannel ch in AnalogChannel.List)
                {
                    scope.SetYOffset(ch, (float)i * maxRange);
                }
                scope.CommitSettings();

                System.Threading.Thread.Sleep(100);
                scope.ForceTrigger();

                //fetch data
                DataPackageScope p = FetchLastFrame(scope);

                if (p == null)
                {
                    Logger.Error("Didn't receive data from scope, aborting");
                    return(null);
                }

                //check if min or max need to be updated (only in case this measurement was not saturated)
                float[] dataA = (float[])p.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChA).array;
                float[] dataB = (float[])p.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChB).array;
                float   minA  = dataA.Min();
                float   maxA  = dataA.Max();
                float   minB  = dataB.Min();
                float   maxB  = dataB.Max();

                if (minA != p.SaturationLowValue[AnalogChannel.ChA] && minA != p.SaturationHighValue[AnalogChannel.ChA] && minValues[0] > minA)
                {
                    minValues[0] = minA;
                }
                if (minB != p.SaturationLowValue[AnalogChannel.ChB] && minB != p.SaturationHighValue[AnalogChannel.ChB] && minValues[1] > minB)
                {
                    minValues[1] = minB;
                }
                if (maxA != p.SaturationLowValue[AnalogChannel.ChA] && maxA != p.SaturationHighValue[AnalogChannel.ChA] && maxValues[0] < maxA)
                {
                    maxValues[0] = maxA;
                }
                if (maxB != p.SaturationLowValue[AnalogChannel.ChB] && maxB != p.SaturationHighValue[AnalogChannel.ChB] && maxValues[1] < maxB)
                {
                    maxValues[1] = maxB;
                }
            }

            //calc ideal voltage range and offset
            float sizer = 3; //meaning 3 waves would fill entire view

            float[] coarseAmplitudes = new float[2];
            coarseAmplitudes[0] = maxValues[0] - minValues[0];
            coarseAmplitudes[1] = maxValues[1] - minValues[1];
            float[] desiredOffsets = new float[2];
            desiredOffsets[0] = (maxValues[0] + minValues[0]) / 2f;
            desiredOffsets[1] = (maxValues[1] + minValues[1]) / 2f;
            float[] desiredRanges = new float[2];
            desiredRanges[0] = coarseAmplitudes[0] * sizer;
            desiredRanges[1] = coarseAmplitudes[1] * sizer;

            //intervene in case the offset is out of range for this range
            if (desiredRanges[0] < Math.Abs(desiredOffsets[0]))
            {
                desiredRanges[0] = Math.Abs(desiredOffsets[0]);
            }
            if (desiredRanges[1] < Math.Abs(desiredOffsets[1]))
            {
                desiredRanges[1] = Math.Abs(desiredOffsets[1]);
            }

            //set fine voltage range and offset
            scope.SetVerticalRange(AnalogChannel.ChA, -desiredRanges[0] / 2f, desiredRanges[0] / 2f);
            scope.SetYOffset(AnalogChannel.ChA, -desiredOffsets[0]);
            scope.SetVerticalRange(AnalogChannel.ChB, -desiredRanges[1] / 2f, desiredRanges[1] / 2f);
            scope.SetYOffset(AnalogChannel.ChB, -desiredOffsets[1]);
            scope.CommitSettings();

            System.Threading.Thread.Sleep(100);
            scope.ForceTrigger();

            //now get data in order to find accurate lowHigh levels (as in coarse mode this was not accurate)
            DataPackageScope pFine = FetchLastFrame(scope);

            Dictionary <AnalogChannel, float[]> dataFine = new Dictionary <AnalogChannel, float[]>();

            dataFine.Add(AnalogChannel.ChA, (float[])pFine.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChA).array);
            dataFine.Add(AnalogChannel.ChB, (float[])pFine.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChB).array);

            Dictionary <AnalogChannel, float> minimumValues = new Dictionary <AnalogChannel, float>();
            Dictionary <AnalogChannel, float> maximumValues = new Dictionary <AnalogChannel, float>();
            Dictionary <AnalogChannel, float> amplitudes    = new Dictionary <AnalogChannel, float>();
            Dictionary <AnalogChannel, float> offsets       = new Dictionary <AnalogChannel, float>();
            Dictionary <AnalogChannel, bool>  isFlatline    = new Dictionary <AnalogChannel, bool>();

            foreach (var kvp in dataFine)
            {
                minimumValues.Add(kvp.Key, kvp.Value.Min());
                maximumValues.Add(kvp.Key, kvp.Value.Max());
                amplitudes.Add(kvp.Key, kvp.Value.Max() - kvp.Value.Min());
                offsets.Add(kvp.Key, (kvp.Value.Max() + kvp.Value.Min()) / 2f);
                isFlatline.Add(kvp.Key, amplitudes[kvp.Key] < 0.01f);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // HORIZONTAL == FREQUENCY

            const float minTimeRange = 500f * 0.00000001f;//500 samples over full hor span
            const float maxTimeRange = 1f;

            double frequency, frequencyError, dutyCycle, dutyCycleError;
            Dictionary <AnalogChannel, double> finalFrequencies = new Dictionary <AnalogChannel, double>();

            finalFrequencies.Add(AnalogChannel.ChA, double.MaxValue);
            finalFrequencies.Add(AnalogChannel.ChB, double.MaxValue);
            int   iterationCounter = 0; //only for performance testing
            float currTimeRange    = minTimeRange;
            bool  continueLooping  = true;

            if (isFlatline.Where(x => x.Value).ToList().Count == isFlatline.Count) //no need to find frequency in case of 2 DC signals
            {
                continueLooping = false;
            }
            int remeasureCounter = 0; // in case of spikes, we try to remeasure until captured. But slow sines can cause this to go wild

            while (continueLooping)
            {
                progress += .04f;
                progressReport(progress);

                iterationCounter++;     //only for performance testing

                scope.AcquisitionLength = currTimeRange;
                scope.SetViewPort(0, scope.AcquisitionLength);
                scope.CommitSettings();

                System.Threading.Thread.Sleep(100);
                scope.ForceTrigger();

                DataPackageScope pHor = FetchLastFrame(scope);
                Dictionary <AnalogChannel, float[]> timeData = new Dictionary <AnalogChannel, float[]>();
                timeData.Add(AnalogChannel.ChA, (float[])pHor.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChA).array);
                timeData.Add(AnalogChannel.ChB, (float[])pHor.GetData(ChannelDataSourceScope.Viewport, AnalogChannel.ChB).array);

                bool notCapturedFullAmplitude = false;
                foreach (var kvp in timeData)
                {
                    //make sure entire amplitude is in view
                    float currMinVal      = kvp.Value.Min();
                    float currMaxVal      = kvp.Value.Max();
                    float lowMarginValue  = minimumValues[kvp.Key] + amplitudes[kvp.Key] * 0.1f;
                    float highMarginValue = maximumValues[kvp.Key] - amplitudes[kvp.Key] * 0.1f;
                    if (currMinVal > lowMarginValue || currMaxVal < highMarginValue)
                    {
                        notCapturedFullAmplitude = true;
                        continue;
                    }

                    Dictionary <int, bool> risingNFallingEdges;
                    ComputeFrequencyDutyCycle(pHor.GetData(ChannelDataSourceScope.Viewport, kvp.Key), out frequency, out frequencyError, out dutyCycle, out dutyCycleError, out risingNFallingEdges, currMinVal, currMaxVal);
                    if (!double.IsNaN(frequency) && (finalFrequencies[kvp.Key] == double.MaxValue))
                    {
                        finalFrequencies[kvp.Key] = frequency;
                    }
                }

                if (notCapturedFullAmplitude && remeasureCounter++ < 5)
                {
                    //need to re-measure, so don't increment
                }
                else
                {
                    remeasureCounter = 0;
                    //update and check whether we've found what we were looking for
                    currTimeRange *= 100f;
                    bool freqFoundForAllActiveWaves = true;
                    foreach (var kvp in timeData)
                    {
                        if (!isFlatline[kvp.Key] && finalFrequencies[kvp.Key] == double.MaxValue)
                        {
                            freqFoundForAllActiveWaves = false;
                        }
                    }
                    continueLooping = !freqFoundForAllActiveWaves;
                    if (currTimeRange > maxTimeRange)
                    {
                        continueLooping = false;
                    }
                }
            }

            //in case of flatline or very low freq, initial value will not have changed
            foreach (AnalogChannel ch in finalFrequencies.Keys.ToList())
            {
                if (finalFrequencies[ch] == double.MaxValue)
                {
                    finalFrequencies[ch] = 0;
                }
            }

            Dictionary <AnalogChannel, AnalogWaveProperties> waveProperties = new Dictionary <AnalogChannel, AnalogWaveProperties>();

            foreach (var kvp in isFlatline)
            {
                waveProperties.Add(kvp.Key, new AnalogWaveProperties(minimumValues[kvp.Key], maximumValues[kvp.Key], amplitudes[kvp.Key], offsets[kvp.Key], isFlatline[kvp.Key], finalFrequencies[kvp.Key]));
            }

            return(waveProperties);
        }
Exemplo n.º 2
0
        static void ConfigureScope()
        {
            Logger.Info("Configuring scope");

            //Stop the scope acquisition (commit setting to device)
            scope.Running = false;
            scope.CommitSettings();

            //Set handler for new incoming data
            scope.DataSourceScope.OnNewDataAvailable += PrintVoltageBars;
            //Start datasource
            scope.DataSourceScope.Start();

            //Configure acquisition

            /******************************/
            /* Horizontal / time settings */
            /******************************/
            //Disable logic analyser
            scope.ChannelSacrificedForLogicAnalyser = null;
            //Don't use rolling mode
            scope.Rolling = false;
            //Don't fetch overview buffer for faster transfers
            scope.SendOverviewBuffer = false;
            //Set sample depth to the minimum for a max datarate
            scope.AcquisitionLength = scope.AcquisitionLengthMin;
            //trigger holdoff in seconds
            scope.TriggerHoldOff = 0;
            //Acquisition mode to automatic so we get data even when there's no trigger
            scope.AcquisitionMode = AcquisitionMode.AUTO;
            //Don't accept partial packages
            scope.PreferPartial = false;
            //Set viewport to match acquisition
            scope.SetViewPort(0, scope.AcquisitionLength);

            /*******************************/
            /* Vertical / voltage settings */
            /*******************************/
            foreach (AnalogChannel ch in AnalogChannel.List)
            {
                //FIRST set vertical range
                scope.SetVerticalRange(ch, -3, 3);
                //THEN set vertical offset (dicated by range)
                scope.SetYOffset(ch, 0);
                //use DC coupling
                scope.SetCoupling(ch, Coupling.DC);
                //and x10 probes
                scope.SetProbeDivision(ch, ProbeDivision.X10);
            }

            // Set trigger to channel A
            scope.TriggerValue = new TriggerValue()
            {
                channel = AnalogChannel.ChA,
                edge    = TriggerEdge.RISING,
                level   = 1.0f
            };

            //Update the scope with the current settings
            scope.CommitSettings();

            //Show user what he did
            PrintScopeConfiguration();

            //Set scope runnign;
            scope.Running = true;
            scope.CommitSettings();
        }
Exemplo n.º 3
0
        public static Dictionary<AnalogChannel, AnalogWaveProperties> MeasureAutoArrangeSettings(IScope scope, AnalogChannel aciveChannel, Action<float> progressReport)
        {
            float progress = 0f;
            progressReport(progress);

            //stop scope streaming
            scope.DataSourceScope.Stop();

            //Prepare scope for test
            if (scope is SmartScope)
                (scope as SmartScope).SetDisableVoltageConversion(false);

            //set to timerange wide enough to capture 50Hz, but slightly off so smallest chance of aliasing
            const float initialTimeRange = 0.0277f;
            scope.AcquisitionMode = AcquisitionMode.AUTO;
            scope.AcquisitionLength = initialTimeRange;
            scope.SetViewPort(0, scope.AcquisitionLength);
            //s.AcquisitionDepth = 4096;
            scope.TriggerHoldOff = 0;
            scope.SendOverviewBuffer = false;

            AnalogTriggerValue atv = new AnalogTriggerValue();
            atv.channel = AnalogChannel.ChA;
            atv.direction = TriggerDirection.RISING;
            atv.level = 5000;
            scope.TriggerAnalog = atv;

            foreach (AnalogChannel ch in AnalogChannel.List)
                scope.SetCoupling(ch, Coupling.DC);

            scope.CommitSettings();
            progress += .1f;
            progressReport(progress);
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // VERTICAL == VOLTAGE

            //set to largest input range
            float maxRange = 1.2f / 1f * 36f;
            foreach (AnalogChannel ch in AnalogChannel.List)
                scope.SetVerticalRange(ch, -maxRange / 2f, maxRange / 2f);

            float[] minValues = new float[] { float.MaxValue, float.MaxValue };
            float[] maxValues = new float[] { float.MinValue, float.MinValue };
            //measure min and max voltage over 3 full ranges
            for (int i = -1; i < 2; i++)
            {
                progress += .1f;
                progressReport(progress);

                foreach (AnalogChannel ch in AnalogChannel.List)
                    scope.SetYOffset(ch, (float)i * maxRange);
                scope.CommitSettings();

                System.Threading.Thread.Sleep(100);
                scope.ForceTrigger();

                //fetch data
                DataPackageScope p = FetchLastFrame(scope);
                p = FetchLastFrame(scope); //needs this second fetch as well to get voltage conversion on ChanB right?!?

                if (p == null)
                {
                    Logger.Error("Didn't receive data from scope, aborting");
                    return null;
                }

                //check if min or max need to be updated (only in case this measurement was not saturated)
                float[] dataA = (float[])p.GetData(DataSourceType.Viewport, AnalogChannel.ChA).array;
                float[] dataB = (float[])p.GetData(DataSourceType.Viewport, AnalogChannel.ChB).array;
                float minA = dataA.Min();
                float maxA = dataA.Max();
                float minB = dataB.Min();
                float maxB = dataB.Max();

                if (minA != p.SaturationLowValue[AnalogChannel.ChA] && minA != p.SaturationHighValue[AnalogChannel.ChA] && minValues[0] > minA) minValues[0] = minA;
                if (minB != p.SaturationLowValue[AnalogChannel.ChB] && minB != p.SaturationHighValue[AnalogChannel.ChB] && minValues[1] > minB) minValues[1] = minB;
                if (maxA != p.SaturationLowValue[AnalogChannel.ChA] && maxA != p.SaturationHighValue[AnalogChannel.ChA] && maxValues[0] < maxA) maxValues[0] = maxA;
                if (maxB != p.SaturationLowValue[AnalogChannel.ChB] && maxB != p.SaturationHighValue[AnalogChannel.ChB] && maxValues[1] < maxB) maxValues[1] = maxB;
            }

            //calc ideal voltage range and offset
            float sizer = 3; //meaning 3 waves would fill entire view
            float[] coarseAmplitudes = new float[2];
            coarseAmplitudes[0] = maxValues[0] - minValues[0];
            coarseAmplitudes[1] = maxValues[1] - minValues[1];
            float[] desiredOffsets = new float[2];
            desiredOffsets[0] = (maxValues[0] + minValues[0]) / 2f;
            desiredOffsets[1] = (maxValues[1] + minValues[1]) / 2f;
            float[] desiredRanges = new float[2];
            desiredRanges[0] = coarseAmplitudes[0] * sizer;
            desiredRanges[1] = coarseAmplitudes[1] * sizer;

            //intervene in case the offset is out of range for this range
            if (desiredRanges[0] < Math.Abs(desiredOffsets[0]))
                desiredRanges[0] = Math.Abs(desiredOffsets[0]);
            if (desiredRanges[1] < Math.Abs(desiredOffsets[1]))
                desiredRanges[1] = Math.Abs(desiredOffsets[1]);

            //set fine voltage range and offset
            scope.SetVerticalRange(AnalogChannel.ChA, -desiredRanges[0] / 2f, desiredRanges[0] / 2f);
            scope.SetYOffset(AnalogChannel.ChA, -desiredOffsets[0]);
            scope.SetVerticalRange(AnalogChannel.ChB, -desiredRanges[1] / 2f, desiredRanges[1] / 2f);
            scope.SetYOffset(AnalogChannel.ChB, -desiredOffsets[1]);
            scope.CommitSettings();

            //now get data in order to find accurate lowHigh levels (as in coarse mode this was not accurate)
            DataPackageScope pFine = FetchLastFrame(scope);
            pFine = FetchLastFrame(scope); //needs this second fetch as well to get voltage conversion on ChanB right?!?

            Dictionary<AnalogChannel, float[]> dataFine = new Dictionary<AnalogChannel, float[]>();
            dataFine.Add(AnalogChannel.ChA, (float[])pFine.GetData(DataSourceType.Viewport, AnalogChannel.ChA).array);
            dataFine.Add(AnalogChannel.ChB, (float[])pFine.GetData(DataSourceType.Viewport, AnalogChannel.ChB).array);

            Dictionary<AnalogChannel, float> minimumValues = new Dictionary<AnalogChannel, float>();
            Dictionary<AnalogChannel, float> maximumValues = new Dictionary<AnalogChannel, float>();
            Dictionary<AnalogChannel, float> amplitudes = new Dictionary<AnalogChannel, float>();
            Dictionary<AnalogChannel, float> offsets = new Dictionary<AnalogChannel, float>();
            Dictionary<AnalogChannel, bool> isFlatline = new Dictionary<AnalogChannel, bool>();
            foreach (var kvp in dataFine)
            {
                minimumValues.Add(kvp.Key, kvp.Value.Min());
                maximumValues.Add(kvp.Key, kvp.Value.Max());
                amplitudes.Add(kvp.Key, kvp.Value.Max() - kvp.Value.Min());
                offsets.Add(kvp.Key, (kvp.Value.Max() + kvp.Value.Min())/2f);
                isFlatline.Add(kvp.Key, amplitudes[kvp.Key] < 0.01f);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // HORIZONTAL == FREQUENCY

            const float minTimeRange = 500f * 0.00000001f;//500 samples over full hor span
            const float maxTimeRange = 1f;

            double frequency, frequencyError, dutyCycle, dutyCycleError;
            Dictionary<AnalogChannel, double> finalFrequencies = new Dictionary<AnalogChannel, double>();
            finalFrequencies.Add(AnalogChannel.ChA, double.MaxValue);
            finalFrequencies.Add(AnalogChannel.ChB, double.MaxValue);
            int iterationCounter = 0;   //only for performance testing
            float currTimeRange = minTimeRange;
            bool continueLooping = true;
            if (isFlatline.Where(x => x.Value).ToList().Count == isFlatline.Count) //no need to find frequency in case of 2 DC signals
                continueLooping = false;
            while (continueLooping)
            {
                progress += .04f;
                progressReport(progress);

                iterationCounter++;     //only for performance testing

                scope.AcquisitionLength = currTimeRange;
                scope.SetViewPort(0, scope.AcquisitionLength);
                scope.CommitSettings();

                DataPackageScope pHor = FetchLastFrame(scope);
                pHor = FetchLastFrame(scope);
                Dictionary<AnalogChannel, float[]> timeData = new Dictionary<AnalogChannel, float[]>();
                timeData.Add(AnalogChannel.ChA, (float[])pHor.GetData(DataSourceType.Viewport, AnalogChannel.ChA).array);
                timeData.Add(AnalogChannel.ChB, (float[])pHor.GetData(DataSourceType.Viewport, AnalogChannel.ChB).array);

                foreach (var kvp in timeData)
                {
                    //make sure entire amplitude is in view
                    float currMinVal = kvp.Value.Min();
                    float currMaxVal = kvp.Value.Max();
                    float lowMarginValue = minimumValues[kvp.Key] + amplitudes[kvp.Key] * 0.1f;
                    float highMarginValue = maximumValues[kvp.Key] - amplitudes[kvp.Key] * 0.1f;
                    if (currMinVal > lowMarginValue) break;
                    if (currMaxVal < highMarginValue) break;

                    ComputeFrequencyDutyCycle(pHor.GetData(DataSourceType.Viewport, kvp.Key), out frequency, out frequencyError, out dutyCycle, out dutyCycleError);
                    if (!double.IsNaN(frequency) && (finalFrequencies[kvp.Key] == double.MaxValue))
                        finalFrequencies[kvp.Key] = frequency;
                }

                //update and check whether we've found what we were looking for
                currTimeRange *= 100f;
                bool freqFoundForAllActiveWaves = true;
                foreach (var kvp in timeData)
                    if (!isFlatline[kvp.Key] && finalFrequencies[kvp.Key] == double.MaxValue)
                        freqFoundForAllActiveWaves = false;
                continueLooping = !freqFoundForAllActiveWaves;
                if (currTimeRange > maxTimeRange)
                    continueLooping = false;
            }

            //in case of flatline or very low freq, initial value will not have changed
            foreach (AnalogChannel ch in finalFrequencies.Keys.ToList())
                if (finalFrequencies[ch] == double.MaxValue)
                    finalFrequencies[ch] = 0;

            Dictionary<AnalogChannel, AnalogWaveProperties> waveProperties = new Dictionary<AnalogChannel, AnalogWaveProperties>();
            foreach (var kvp in isFlatline)
                waveProperties.Add(kvp.Key, new AnalogWaveProperties(minimumValues[kvp.Key], maximumValues[kvp.Key], amplitudes[kvp.Key], offsets[kvp.Key], isFlatline[kvp.Key], finalFrequencies[kvp.Key]));

            return waveProperties;
        }