2016-07-25 1 views
0

VB.NET의 Excel 2013 용 VSTO 추가 기능에서 직렬 연결을 통해 계측기와 인터페이스 할 수 있습니다. 현재 COM 연결이 올바르게 설정되어 있으며 한 번에 하나의 명령을 보내고받을 수 있습니다. 하나의 버튼을 누르고 다른 워크 시트 셀에서 두 개의 별도 판독 값을 수집 할 수 있도록 설정하고 싶습니다. 아래의 코드를 사용하면 도구가 단일 판독 값을 수집하는 데 효과적이지만 코드에서 두 번째 명령을 계측기로 보내면 다른 단일 읽기 명령을 보낼 때까지 데이터 수신 이벤트가 완전히 작동하지 않습니다. 나는 그 장비가 두 번째 명령을 받고 처리했음을 알고 있지만 결코 탁월한 것으로 나타나지 않습니다. 누구든지이 코드를 수정하는 방법을 도울 수 있습니까? 이 모든 경우에 제대로 작동하는 것으로 나타납니다 악기에 대한 간단한에 .write 명령이기 때문에 내 인 sendCommand 하위를 포함하지 않았다직렬 포트 데이터 수신 이벤트가 확실하지 않다면

Private Sub mySerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) 
    'Handles serial port data received events 
    UpdateFormDeligate1 = New UpdateFormDeligate(AddressOf UpdateDisplay) 

    Dim n As Integer = mySerialPort.BytesToRead 'find number of bytes in buff 
    comBuffer = New Byte(n - 1) {} 're-dimension storage buffer (n - 1) 
    mySerialPort.Read(comBuffer, 0, n) 'read data from the buffer 

    comBuffer2 = mySerialPort.ReadTo(vbCr) 

    Me.Invoke(UpdateFormDeligate1) 'call the deligate 
    mySerialPort.Close() 
End Sub 


Private Sub Invoke(updateFormDeligate1 As UpdateFormDeligate) 
    lblReading.Label = processReading() 'write to a Current Reading lable on the ribbon 

    Dim myApp As Excel.Application = Globals.ThisAddIn.Application 
    Dim currentCell = myApp.ActiveCell 
    currentCell.Value = processReading() 'write data in the excel active cell 

    Try 
     advanceCell() 
    Catch ex As Exception 
     System.Windows.Forms.MessageBox.Show(ex.Message) 
    End Try 
    If measureNo = 2 Then 'this case is selected when I want to read 2 measurements with a single button push 
     cmdSent = 2 
     sendCommand(measureCmd) 

    End If 
End Sub 

Private Sub UpdateDisplay() 

End Sub 

참고. 나는 데이터 수신 이벤트를 사용하는 것에 익숙하지 않기 때문에 누구나 제공 할 수있는 도움을 주시면 감사하겠습니다.

+0

버그가 많습니다. 가장 심각한 버그는 이벤트 처리기 내에서 Close()를 호출하는 것입니다. 첫 번째 명령 후에 쇼가 끝납니다. –

+0

감사합니다. 한스. 나는 첫번째 쓰기 후에 시리얼 포트를 다시 열었다면 중요하다는 것을 알기 위해 가까이에 추가했다. 직렬 포트가 닫혀있는 경우 직렬 포트를 여는 루틴이 쓰기 명령에 있습니다. 두 개의 쓰기/읽기를 시도하기 위해 포트를 열어 두어도 문제가없는 것 같습니다. 닫은 경우 다시 열었습니다. – user3566911

답변

0

확인을 클릭하면 문제가있는 스크립트의 관련 부분 만 격리하려고 시도하고 테스트를 위해 완전히 새로운 도구 모음을 만들었습니다. 다음은이 새로운 툴바의 전체 코드입니다. 하나는 연결/측정 단추이고 상태/결과를 표시하는 레이블입니다. 나는 그것을 읽을 수 있도록 코드에 주석을 넣어 보았는데, 잘하면이 도움이된다.

이 새 도구 모음이 올바르게 작동하는 것 같습니다. Invoke 메서드 (Visual Studio가 Excel2013과 함께 사용하기 위해 약간 변경됨)와 함께 DataReceived 이벤트 처리기를 올바르게 사용하는 것에 대해서는 아직 확실하지 않습니다. 아무도 내가 아직 명확하지 않은 방식으로 이러한 이벤트를 사용하고 있는지와 내가 더 잘 만들 수있는 방법에 대한 제안을 제공했는지에 관해 의견을 제시해 주실 수 있습니까?

도움을 받으려면 다시 한번 감사드립니다. 정말 감사.

Imports Microsoft.Office.Tools.Ribbon 
Imports System.IO.Ports 

Public Class Measure2x_COM 
Dim mySerialPort As New SerialPort 
Dim CMD As String = "M" & vbCr 'statement telling instrument to measure 
Dim measureNo As Integer = 0 'counts the number of measure commands sent to the instrument 

Private Delegate Sub UpdateFormDeligate() 
Private UpdateFormDeligate1 As UpdateFormDeligate 

Dim sngReading As Single 'this is the reading received from the instrument as a single data type 

Private Sub setupConnectCOM() 
    'Open COM and send measure command - this part works correctly 
    'first, check if serial port is open 
    If mySerialPort.IsOpen Then 'send measure command 
     mySerialPort.Write(CMD) 'the instrument will generally take 15.1 sec to perform a measurement before sending the result back 
    Else 
     'if serial port is not open, set it up, then open, then send command 
     'Setup COM --this part works correctly 
     With mySerialPort 
      .PortName = "COM3" 
      .BaudRate = 1200 
      .DataBits = 7 
      .Parity = Parity.None 
      .StopBits = StopBits.Two 
      .Handshake = Handshake.None 
      .ReadTimeout = 16000 
     End With 

     Try 
      mySerialPort.Open() 
     Catch ex As Exception 
      System.Windows.Forms.MessageBox.Show(ex.Message) 
      Exit Sub 'exit sub if the connection fails 
     End Try 
     Threading.Thread.Sleep(200) 'wait 0.2 sec for port to open 

     mySerialPort.Write(CMD) 'send measure command after serial port is open 

    End If 
    measureNo = 1 
    lblResult.Label = "Measuring" 
End Sub 

Private Sub Measure2x_COM_Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load 
    AddHandler mySerialPort.DataReceived, AddressOf mySerialPort_DataReceived 

End Sub 

Private Sub mySerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) 
    'Handles serial port data received events 
    UpdateFormDeligate1 = New UpdateFormDeligate(AddressOf UpdateDisplay) 

    'Read data as it comes back from serial port 
    'I had to do this in two steps because it, for some reason needs to read 
    'the +/- symbol as a Byte, then needs to read the ASCII measurement number 
    'the third part concatenates the data and converts it to a single type 

    'part 1 - read +/- symbol 
    Dim comBuffer As Byte() 
    Dim n As Integer = mySerialPort.BytesToRead 'find number of bytes in buff 
    comBuffer = New Byte(n - 1) {} 're-dimension storage buffer (n - 1) 
    mySerialPort.Read(comBuffer, 0, n) 'read data from the buffer 

    'part 2 - read ASCII measurement number 
    Dim comBuffer2 As String 
    comBuffer2 = mySerialPort.ReadTo(vbCr) 

    'part 3 - concatenate read data and convert to single type 
    Dim txtReading As String = Nothing 
    txtReading = System.Text.ASCIIEncoding.ASCII.GetString(comBuffer) & CStr(CInt(comBuffer2)/10) 
    sngReading = CSng(txtReading) 

    'Call the update form deligate 
    'Visual Studio slightly changed this from the example on Microsoft's website that used a Windows Form 
    'I tried the code in a windows form and I get the same results 
    Me.Invoke(UpdateFormDeligate1) 'call the deligate 
End Sub 

Private Sub Invoke(updateFormDeligate1 As UpdateFormDeligate) 
    lblResult.Label = sngReading 'set the Result label in the ribbon to equal the received data value 

    'now place the data received in the active cell in the worksheet 
    Dim myApp As Excel.Application = Globals.ThisAddIn.Application 
    Dim currentCell = myApp.ActiveCell 
    currentCell.Value = sngReading 

    'advance cell to the next cell 
    Dim newCell = currentCell 
    newCell = myApp.ActiveCell.Offset(1, 0) 
    newCell.Select() 
    currentCell = newCell 

    'check if this was the first reading from the instrument 
    'if it was the first reading, then send a second read command 
    If measureNo = 1 Then 
     measureNo = 2 'make sure to change measurement number to 2 to avoid infinite loop 
     mySerialPort.Write(CMD) 'send command to measure to instrument 
    End If 
End Sub 

'the usage of this section changed from the Microsoft Windows Form example 
'in function, the mySerialPort_DataREceived(), Invoke(), and UpdateDisplay() functions do appear to be 
'working with the same results and same hangups 
Private Sub UpdateDisplay() 

End Sub 

Private Sub btnMeasure_Click(sender As Object, e As RibbonControlEventArgs) Handles btnMeasure.Click 
    setupConnectCOM() 'connect to COM and send first measure command 
End Sub 
End Class