Count Parallel port input frequency - C#

可紊 提交于 2019-12-12 04:08:36

问题


I have to count the input frequency of the parallel port at Pin no.13, comming from a 555 timer IC, the real frequency should be around 3-4 Hz (ON Pulse). I have tried several codes, several times but every time those are giving different values. I have tried the following code:

    [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;
            }
        }
    }

OUTPUT:

What should I do, to get accurate frequency? Is any thing wrong in my code? I am using the inpout32.dll to control parallel port.


回答1:


You're doing all sorts of things a bit wrong. First, you're counting pulses for an entire second, you're counting pulses for up to a second (depends on where in the second GetFreq is called).

Second, you're counting up and down pulses, although I think the frequency should be the number of up (or down) pulses each second, not both of them (that would be double the frequency).

And finally, if you want to measure 3 or 4 Hz, measuring for one second is going to introduce rounding errors. Try measuring for 5 seconds. Use a Stopwatch to measure those 5 seconds.




回答2:


Try using the following function instead:

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
}

And when you need to call the function, just do the following:

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

In my code, I used bitwise operator AND to mask out unnecessary bits, which should be better than directly comparing against 120. Remember when the results are bitwise, never compare directly using == or != operators.

I used System.Diagnostics.Stopwatch which is a lot more precise than using DateTime.Now.Second.




回答3:


You need to sample your signal at rate that is at least twice the highest frequency in your signal. If your expected highest frequency is about 4Hz, then sampling the signal anywhere from 15 - 20Hz should give good results.

Fortunately, sampling at this rate is something that can be done without too much futzing around with high precision timers on Windows (if you don't require a lot of accuracy). A 20Hz sample rate corresponds to a sample period of 50ms, so you can use a loop where you sleep for about 50ms between recording sample values. You won't get a super precise delta-T between samples (you may see variations of up to 15-30ms in the time between each sample, depending on your system), but it should be good enough for the frequencies you're dealing with.

You can record several seconds worth of samples (and associated timestamps), and then export the data to a spreadsheet. Once in the spreadsheet, you can do some analysis and graphing. Or you can find some time series analysis code to analyze the list of samples, such as using a Fourier transform (FFT) to convert a signal from the time domain to the frequency domain.

Here is an example of creating the samples. You can replace the use of DateTime.Now with a StopWatch in GetInputSamples if you really need more accuracy in the timestamps.

[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);
        }
    }
}


来源:https://stackoverflow.com/questions/11499113/count-parallel-port-input-frequency-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!