2013-07-16 1 views
0

제발 용서해주십시오. 꽤 긴 게시물이 될 것입니다. 현재 C#에서 SerialPort 클래스를 사용하여 Fluke 5500A라는 장치와 통신하는 응용 프로그램을 작성하고 있습니다. 필자는 과거에 장치가 명령을 내리고 결과가 무엇이든 예측할 수없는 상태로 반환하는 데 걸리는 시간으로 많은 문제를 겪었습니다. 나는 어제 질문을했다. System.Timers.Timer Usage 질문에 대한 답은 훌륭하고 대부분의 경우 완벽하게 작동하는 것으로 보인다.명백한 IO.Ports.SerialPort C# 또는 가능한 하드웨어 결함의 결함

public class SerialPortConnection 
{ 
    private SerialPort serialPort; 
    private string ping; 
    double failOut; 
    bool isReceiving; 

    public SerialPortConnection(string comPort = "Com1", int baud = 9600, System.IO.Ports.Parity parity = System.IO.Ports.Parity.None, int dataBits = 8, System.IO.Ports.StopBits stopBits = System.IO.Ports.StopBits.One, string ping = "*IDN?", double failOut = 2) 
    { 
     this.ping = ping; 
     this.failOut = failOut * 1000; 

     try 
     { 
      serialPort = new SerialPort(comPort, baud, parity, dataBits, stopBits); 
      serialPort.NewLine = ">"; 
      serialPort.ReadTimeout = 1000; 
     } 
     catch (Exception e) 
     { 
      serialPort = null; 
     } 
    } 

    //Open Serial Connection. Returns False If Unable To Open. 
    public bool OpenSerialConnection() 
    { 
     //Opens Initial Connection: 
     try 
     { 
      serialPort.Open(); 
      serialPort.Write("REMOTE\r"); 
     } 
     catch (Exception e) 
     { 
      return false; 
     } 

     serialPort.Write(ping + "\r"); 
     var testReceived = ""; 

     try 
     { 
      testReceived += serialPort.ReadLine(); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    public string WriteSerialConnection(string SerialCommand) 
    { 
     serialPort.Write(String.Format(SerialCommand + "\r")); 
     var received = ""; 

     try 
     { 
      received += serialPort.ReadLine(); 
      return received; 
     } 
     catch 
     { 
      received = "Error: No Data Received From Device"; 
      return received; 
     } 
    } 

    public bool CloseSerialConnection() 
    { 
     try 
     { 
      serialPort.Write("LOCAL\r"); 
      serialPort.Close(); 
      return true; 
     } 
     catch (Exception e) 
     { 
      return false; 
     } 
    } 
} 

당신이 볼 수 있듯이, 나는이 경우에 대한 연결을 열 때, Com1는 난을 작성하여 연결을 테스트 : 예를 들어 나는하여 SerialPort에 연결하는 데 사용하는 내 클래스는 이제 다음과 같습니다 SerialPort에 *IDN? 명령을 보내십시오. 이 명령에 대한 리턴 그래서 다음과 같습니다

FLUKE,5500A,8030005,2.61+1.3+2.0+* 
66> 

그것을 그 토큰을 발견까지 SerialPort.ReadLine()가 완료되지 않도록 내가 줄 바꿈 속성으로 ">"을 설정 한 클래스에서. 한 번도 클래스 자체에서 예외를 throw하지는 못했지만 예외가 발생하지 않고 코드가 제대로 실행되면서도 testReceived이 반환 된 데이터를 제대로 캐치하지 않는 디버깅 중에 알았습니다. 대신 received은 반환 된 문자열을 잡을 : 내가 아는 것이 중요 SerialPort.Write(); 뭔가를 통해 내 첫 번째 명령을 통과 할 때마다

FLUKE,5500A,8030005,2.61+1.3+2.0+* 
66> 

해당 데이터가 완전히 반환하지 않고 명령을 실행할 수 있다는 것입니다. 제 우려는 처음의 ReadLine()은 가끔씩 전체 수익을 포기하지 않고 지나치는 것처럼 보입니다. 내 생각으로는이 문제를 일으키는 장치에 고유 한 결함이 있지만 계속하기 전에 전체적으로 확신하고 싶습니다.

내 명령 순서는 그래서 다음과 같습니다

먼저 나는 시작에 명령을 제출

REMOTE 

이 장치의 수동 인터페이스와 상호 작용을 비활성화하고 나를 직렬 포트를 통해 명령을 제출할 수 있습니다.

은 그 때 나는 장치가 연결되어 있는지 확인하기 위해,이 경우, *IDN?을 실행

*IDN? 

아무것도 반환 응용 프로그램은 다음 FailFast 메시지 상자에 오류를 표시하도록 설정하고,없는 경우. 모두가된다면 아니라 명령과 같이 제출 될 수

STBY 
OUT 30MV,60HZ 
OPER 

여기에 직접 제출하는 유일한 명령은 OUT 30,MV,60HZ입니다. STBYOPER은 응용 프로그램 사용에 불필요한 단계 만 추가하기 때문에 app.config에 설정됩니다. STBY 명령은 안전상의 이유로 기계를 대기 상태로 만듭니다. OPER 명령은이를 작동 모드로 설정하고 장치는 설정된 매개 변수로 작동을 시작합니다.

그러면 응용 프로그램에서 기술자가 결과를 텍스트 상자에 입력하고 제출할 때까지 기다립니다.이러한 결과의 내용은 특히 관련 아니지만 결과 버튼을 눌렀을 때 컴퓨터가 대기에 다시 넣어 :

STBY 

마지막으로, 응용 프로그램이 닫힐 때 두 가지 이상의 명령이 제출 :

*RST 
LOCAL 

먼저 *RST은 전원을 켰을 때와 동일한 상태 (IE가 작동 중이 아니며 매개 변수가 설정되지 않음)인지 확인하기 위해 기기를 재설정합니다. 그런 다음 LOCAL은 사용자 상호 작용을 위해 수동 인터페이스를 다시 활성화하고 다시 REMOTE이 발행 될 때까지 직렬 포트를 통한 액세스를 비활성화합니다.

본 그림에서 알 수 있듯이 *IDN? 이후와 첫 번째 수동 명령 (이 경우 명령은 OUT 30MV,60HZ이라고 가정) 앞에 명령이 실행됩니다. 문제는 때로는 OUT 30MV,60HZ의 출력이 무엇인지를 확인할 때마다 *IDN의 출력을 수신하는 것입니다. 내 코드 또는 프로 시저 내에서 기계 작동에 문제가없는 것을 확인할 수 있습니다. 이것이 일어날 수있는 이유가 있습니까?

내가 말했듯이, 오류는 재현하기가 극히 어렵습니다 (나는 40 번 실행했을 때 두 번 본 적이 있습니다). 그렇더라도 프로덕션 환경에서는이 유형의 모든 오류를 허용 할 수 없으며 응용 프로그램 전체를 테스트하기 전에 오류를 수정해야합니다. 나는 오류를 재현하려고 계속 노력할 것이므로 예제를 제공하고 문제가 무엇인지에 대해 더 명확하게 설명해 줄 수 있기를 바랍니다. 나는 또한 내가 버그가 코드와 내 응용 프로그램 자체 내에서 어딘가에 위치하지 꽤 확신 명확히하고 싶습니다

자연에서 다소 단순한입니다

:

public string SubmitCommand() 
    { 
     if (_command_Input != "No further commands to input.") 
     { 
      string received; 
      serialPort.WriteSerialConnection("STBY"); 
      received = serialPort.WriteSerialConnection(_command_Input); 
      serialPort.WriteSerialConnection("OPER"); 

      //Controls Enabled: 
      _input_IsEnabled = false; 
      _user_Input_IsEnabled = true; 
      _results_Input_IsEnabled = false; 
      RaisePropertyChanged("Input_IsEnabled"); 
      RaisePropertyChanged("User_Input_IsEnabled"); 
      RaisePropertyChanged("Results_Input_IsEnabled"); 

      return received; 
     } 
     else 
      return ""; 
    } 

수신 EDIT

다음과 같이 조작되어있을 필요하지만 현재 당면한 문제에 관련 될 수있는 다른 코드를 볼 수없는 경우

public bool SetOutput() 
    { 
     string inter1 = SubmitCommand(); 

     try 
     { 

      string[] lines = inter1.Split(Environment.NewLine.ToCharArray()).ToArray(); 
      _results_Changed = lines[2]; 
      RaisePropertyChanged("Results_Changed"); 
     } 
     catch 
     { 
      _results_Changed = inter1; 
      RaisePropertyChanged("Results_Changed"); 
     } 
     return true; 
    } 

나는 더 코드를 제공 할 수 있습니다.

+1

결함이 장치에 없다는 것을 어떻게 확인할 수 있습니까? –

+0

@BradRem 그래서 제가 묻고 있습니다. 그것이 장치 결함인지 확신 할 수는 없지만 프로그래밍 결함보다는 문제 해결이 훨씬 어렵습니다 (불가능하지는 않지만). 그 문제를 해결하려고 계속하기 전에 그것이 내 코드 어딘가에 또는 SerialPort 클래스에 결함이 없는지 확인하고 싶습니다. – DanteTheEgregore

+1

사용하는 Win32 통신 API와 비교할 때,'IO.Ports.SerialPort'는 몹시 망가졌습니다. 나는 스스로 곤란을 겪었고 다양한 문제에 관한 다른 사람들의보고를 보았습니다. Win32를 직접 사용하기 위해 전환 한 후에 모두 사라졌습니다. –

답변

1

당신이 진단하기가 어려웠 으면 좋지 않은 답변은 과 같이 정확하게처럼 보입니다.

일반적으로 프로그램이 장치와 동기화되어 있는지 확인해야합니다. 가능한 실패 모드는 드라이버가 여전히 이전 연결의 수신 버퍼에 읽지 않은 데이터를 가지고있을 때입니다. 부실 데이터는 장치의 전송 버퍼에도 존재할 수 있습니다. 백업을 시작하면 그 부실 데이터를 읽고 명령에 대한 응답이라고 가정합니다. 그렇지 않았습니다. 이제 이전 명령에 대한 응답이었던 부실 데이터를 항상 읽을 수 있도록 영구 동기화되지 않습니다.

핸드 셰이 킹을 돌보지 않고도 작동한다는 것은 다소 이상합니다. 일반적으로 장치는 입니다.에주의하십시오.장치가 항상 좋은 신호를 볼 수 있도록

  • 전화 포트
  • 설정을 true로 RtsEnable 및 DtrEnable 속성을 엽니 다 열기() 메소드 사고를 방지하기 위해

    ,이 같은 프로그램을 초기화 데이터를 전송할 수 있습니다.

  • 핸드 셰이크가 꺼져 있기 때문에 이전에 버퍼링되었지만 보낼 수없는 데이터를 장치에서 보낼 수 있도록 약 100ms 동안 슬리핑
  • DiscardInBuffer()를 사용하여 버려집니다. 부실한 sponse 바이트.

이제는 동기화 될 것이라는 것을 보장했습니다.

+0

장치에 연결해도 핸드 셰이크가 필요하지 않습니다. 그 뒤에있는 추론을 알지는 못하지만 장치가 오래되었고 장치와 함께 제공된 프로그래머 용 설명서에는 RS-232 용 핸드 셰이 킹에 대한 언급이 없습니다. IEEE-488에서 핸드 쉐이킹이 필요하다는 것을 알았지 만 그 기능은 다르게 사용되며, 사용하는 회사가 사용하지 않기를 바란다면 그 사용법은 옵션이 아닙니다. – DanteTheEgregore

+0

그러나 이전에는 SerialPorts와 함께 일한 적이 없으므로 어떻게 작동해야하는지에 대해서는 많이 알지 못합니다. 네가 언급 한 것을 시도해 보겠다. – DanteTheEgregore