2012-07-16 3 views
0

핀 번호 13에서 병렬 포트의 입력 주파수를 계산해야합니다. 555 타이머 IC에서 실제 주파수는 약 3-4 Hz (ON 펄스) 여야합니다. 몇 가지 코드를 여러 번 시도했지만 각각 다른 값을 제공합니다. 나는 다음과 같은 코드를 시도 :카운트 병렬 포트 입력 주파수 - C#

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

출력 :

enter image description here enter image description here enter image description here

내가 정확한 주파수를 얻으려면 어떻게해야합니까? 내 코드에서 잘못된 점이 있습니까? inpout32.dll을 사용하여 병렬 포트를 제어하고 있습니다.

+0

오프 펄스 값은 항상 120과 같거나 120보다 약간 크거나 작을 수 있습니까? –

답변

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과 직접 비교하는 것보다 낫습니다. 결과가 비트 단위 일 때 기억하십시오. == 또는 != 연산자를 사용하여 직접 비교하지 마십시오.

보다 많이 사용되었습니다.DateTime.Now.Second보다 정확합니다.

0

당신은 모든 일을 조금 잘못하고 있습니다. 먼저, 초당 펄스 수를 계산 중입니다. 까지의 펄스를 초당 초로 계산합니다 (두 번째 GetFreq가 호출되는 위치에 따라 다름).

둘째로, 주파수가 초당 최대 (또는 아래) 펄스 수 (두 번 주파수가 아님)가 아닌 초당 펄스 수이어야한다고 생각합니다.

마지막으로 3 Hz 또는 4 Hz를 측정하려는 경우 1 초를 측정하면 반올림 오류가 발생합니다. 5 초 동안 측정하십시오. Stopwatch을 사용하여 5 초를 측정하십시오.

0

신호에서 신호의 최고 주파수의 두 배 이상의 속도로 신호를 샘플링해야합니다. 예상되는 가장 높은 주파수가 약 4Hz 인 경우 15-20Hz에서 신호를 샘플링하면 좋은 결과를 얻을 수 있습니다.

다행히도이 속도로 샘플링하는 것은 Windows에서 정밀도가 높은 타이머를 너무 많이 사용하지 않고 수행 할 수있는 작업입니다 (많은 정확도가 필요하지 않은 경우). 20Hz 샘플 속도는 50ms 샘플주기에 해당하므로 샘플 샘플 값을 저장하는 사이에서 약 50ms 동안 잠자기 루프를 사용할 수 있습니다. 샘플 사이에 매우 정확한 델타 - T를 얻지 못할 것입니다 (시스템에 따라 각 샘플 사이의 시간에 최대 15-30ms의 변형이 나타날 수 있음). 그러나 처리중인 주파수에 대해 충분히 양호해야합니다 와.

몇 초의 샘플 (및 연관된 타임 스탬프)을 기록한 다음 데이터를 스프레드 시트로 내보낼 수 있습니다. 일단 스프레드 시트에, 당신은 몇 가지 분석 및 그래프 작업을 수행 할 수 있습니다. 또는 FFT (Fourier Transform)를 사용하여 시간 영역의 신호를 주파수 영역으로 변환하는 등의 샘플 목록을 분석 할 수있는 시계열 분석 코드를 찾을 수 있습니다.

다음은 샘플을 만드는 예제입니다. 타임 스탬프에 정확성이 더 필요하다면 DateTime.Now의 사용을 StopWatch으로 바꾸고 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); 
     } 
    } 
}