0

555 タイマー IC から来るピン番号 13 のパラレル ポートの入力周波数をカウントする必要があります。実際の周波数は約 3 ~ 4 Hz (ON パルス) である必要があります。私はいくつかのコードを何度か試しましたが、毎回異なる値を与えています。次のコードを試しました:

    [DllImport("inpout32.dll", EntryPoint = "Inp32")]
    public static extern int Input(int adress);

    private void button1_Click(object sender, EventArgs e)
    {
        int currentState = Input(889);
        int LastState;
        while (true)
        {
            int State = Input(889);
            if (State != currentState)
            {
                if (Input(889) == 120)
                {
                    LastState = 0;
                }
                else
                {
                    LastState = 1;
                }
                break;
            }
        }
        GetFreq(LastState);

    }
    void GetFreq(int LastPulse)
    {
        int highPulseFreq = 0;
        int lowPulseFreq = 0;
        if (LastPulse == 1)
        {
            highPulseFreq++;
        }
        if (LastPulse == 0)
        {
            lowPulseFreq++;
        }
        int startTime = DateTime.Now.Second;
        while (true)
        {
            if (startTime == DateTime.Now.Second)
            {
                if (Input(889) != 120)// ON
                {
                    if (LastPulse == 0)
                    {
                        highPulseFreq++;
                        LastPulse = 1;
                    }
                }
                else
                {
                    if (LastPulse == 1)
                    {
                        lowPulseFreq++;
                        LastPulse = 0;
                    }
                }
            }
            else
            {
                MessageBox.Show("ON Pulses: " + highPulseFreq.ToString() + Environment.NewLine + "OFF Pulses: " + lowPulseFreq.ToString());
                break;
            }
        }
    }

出力:

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

正確な周波数を取得するにはどうすればよいですか? 私のコードに何か問題がありますか? を使用しinpout32.dllてパラレルポートを制御しています。

4

3 に答える 3

0

信号の最高周波数の少なくとも 2 倍のレートで信号をサンプリングする必要があります。予想される最高周波数が約 4 Hz である場合、15 ~ 20 Hz の信号をサンプリングすると良い結果が得られます。

幸いなことに、このレートでのサンプリングは、Windows の高精度タイマーをあまりいじらずに実行できるものです (あまり精度を必要としない場合)。20Hz のサンプル レートは 50 ミリ秒のサンプル期間に対応するため、サンプル値を記録する間に約 50 ミリ秒スリープするループを使用できます。サンプル間の非常に正確なデルタ T は得られません (システムによっては、各サンプル間の時間に最大 15 ~ 30 ミリ秒の変動が見られる場合があります) が、扱っている周波数には十分なはずです。と。

数秒分のサンプル (および関連するタイムスタンプ) を記録し、データをスプレッドシートにエクスポートできます。スプレッドシートに入ると、分析とグラフ化を行うことができます。または、フーリエ変換 (FFT) を使用して信号を時間領域から周波数領域に変換するなど、サンプルのリストを分析するための時系列分析コードを見つけることができます。

サンプルの作成例です。タイムスタンプの精度をさらに高める必要がある場合は、の使用DateTime.NowStopWatchinに置き換えることができます。GetInputSamples

[DllImport("inpout32.dll", EntryPoint = "Inp32")] 
public static extern int Input(int adress); 

struct Sample 
{
    public int Value;
    public int Milliseconds;
};

private void button1_Click(object sender, EventArgs e) 
{ 
    TimeSpan duration = TimeSpan.FromSeconds(5);
    TimeSpan samplePeriod = TimeSpan.FromMilliseconds(50);

    var samples = GetInputSamples(889, duration, samplePeriod);
    SaveSamplesCSV(samples, "test.csv");
} 

private static List<Sample> GetInputSamples(int inputPort, TimeSpan duration, TimeSpan samplePeriod)
{ 
    List<Sample> samples = new List<Sample>();

    var oldPriority = Thread.CurrentThread.Priority;
    try
    {
        Thread.CurrentThread.Priority = ThreadPriority.Highest;

        DateTime start = DateTime.Now;
        while (DateTime.Now - start < duration)
        {
            int value = Input(inputPort); 
            TimeSpan timestamp = DateTime.Now - start;

            samples.Add(new Sample() { Value = value, Milliseconds = (int)timestamp.TotalMilliseconds });

            Thread.Sleep(samplePeriod);
        }
    }
    finally
    {
        Thread.CurrentThread.Priority = oldPriority;
    }

    return samples;
}

private static void SaveSamplesCSV(List<Sample> samples, string fileName)
{
    using (StreamWriter writer = File.CreateText(fileName))
    {
        writer.WriteLine("Sample, Time (ms)");
        foreach (var sample in samples)
        {
            writer.WriteLine("{0}, {1}", sample.Value, sample.Milliseconds);
        }
    }
}
于 2012-07-17T22:35:48.963 に答える
0

あなたはあらゆる種類のことを少し間違っています。まず、パルスを 1 秒間カウントし、最大1 秒間パルスをカウントします(2 番目の GetFreq が呼び出される場所によって異なります)。

次に、パルスのアップとダウンをカウントしていますが、周波数は 1 秒あたりのアップ (またはダウン) パルスの数である必要があり、両方ではありません (周波数の 2 倍になります)。

最後に、3 または 4 Hz を測定する場合、1 秒間測定すると丸め誤差が発生します。5 秒間測定してみてください。a を使用して、Stopwatchこれらの 5 秒を測定します。

于 2012-07-16T06:50:45.853 に答える
0

代わりに次の関数を使用してみてください。

double GetFreq(long time, out int highCount, out int lowCount)
{
    const int ADDRESS = 0x378 + 1, MASK = 0x10;
    highCount = lowCount = 0;
    bool LastState = (Input(ADDRESS) & MASK) == MASK;
    if (LastState)
    {
        highCount++;
    }
    else
    {
        lowCount++;
    }
    System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
    stopwatch.Start();
    while (stopwatch.ElapsedMilliseconds <= time)
    {
        if ((Input(ADDRESS) & MASK) == MASK) // High
        {
            if (!LastState)
            {
                highCount++;
                LastState = true;
            }
        }
        else
        {
            if (!LastState)
            {
                lowCount++;
                LastState = false;
            }
        }
    }
    stopwatch.Stop();
    return ((double)(highCount + lowCount)) / time * 500
}

関数を呼び出す必要がある場合は、次のようにします。

int highCount, lowCount;
double frequenct = GetFreq(1000, out highCount, out lowCount);

私のコードでは、ビットごとの演算子を使用ANDして不要なビットをマスクしました。これは、 と直接比較するよりも優れているはず120です。結果がビット単位の場合は、==または!=演算子を使用して直接比較しないでください。

を使用System.Diagnostics.Stopwatchするよりもはるかに正確な を使用しDateTime.Now.Secondました。

于 2012-07-16T06:50:10.497 に答える