Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Netduino Serial Events issue

serial vb.net events

  • Please log in to reply
11 replies to this topic

#1 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 07 January 2013 - 08:14 PM

Hopefully I am in the correct forum.  Please forgive me if I am not.

 

I am using a Netduino Plus (flashed to 4.2) to communicate to a sensor with a serial interface.  I had problems with it not working reliably so I started a new project with only the critical bits in play.  I am seeing very similar results.

 

I send a serial Command to the sensors and look for a response.  However in the test I set up I am using a program called Docklight, which is similar to HyperTeminal but has scripting, this can simulate the request/response serial commands of the sensor.  I am seeing the same results either way.

 

I am using the RS-232 Shield found here

 

I have attached the code, but here is the issue.

 

I press the on-board button, Debug shows "Button Pressed" and then displays the expected response.

 

Posted Image

 

NOTE: 

1. Request

2. Response

 

 

 

I press the button again, nothing happens.

Again, still nothing.  Nothing happens regardless of how many times I hit the button.  If I use the program Docklight to force a serial received event (send a serial message to the Netduino) then the Debug window  will display the "Button Pressed" message and the expected response for however many times I hit the button.

 

Posted Image

NOTE:

1. Request

2. Response

3. Forced Response

4. Queued Request

5. Queued Request

6. Queued Request

7. Response

8. Response

9. Response

 

 

 

 

It will then function normally 1 time before hanging up again.

Posted Image

 

NOTE: 

1. Request

2. Response

3. Forced Response

4. Queued Request

5. Queued Request

6. Queued Request

7. Response

8. Response

9. Response

10. Request

11. Response

 

 

The same symptoms happen even when I have an auto-scripted responses from turned OFF.  I press the button and it sends the request.  However, it does not display the "Button Pressed" message or send a serial request again until I force a response.  I feel like I am screwing up something on the events.

 

Does anybody have any ideas?  I am feeling stumped on this one.  I am probably overlooking something very obvious to an experienced Netduino user.

 

 



#2 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 07 January 2013 - 08:17 PM

I tried to include my Code as an attachment but it didn't appear to work.  Here it is.

 

 

Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
Imports SecretLabs.NETMF.Hardware
Imports SecretLabs.NETMF.Hardware.NetduinoPlus
Imports Microsoft.VisualBasic.Constants
Imports System.IO.Ports
Imports SecretLabs.NETMF.Hardware.NetduinoPlus.SerialPorts
 
Module Module1
    Public _onBoardLED As OutputPort
    Public _onBoardButton As InterruptPort
    Public WithEvents ComPort As New SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)
    Dim Led As New OutputPort(Pins.ONBOARD_LED, False)
    Public Button As New InterruptPort(Pins.ONBOARD_SW1, True, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh)
 
    Sub Main()
        AddHandler Button.OnInterrupt, AddressOf ButtonPress
        AddHandler ComPort.DataReceived, AddressOf ComDataReceived
        ComPort.Open()
        Thread.Sleep(Timeout.Infinite)
    End Sub
 
    'Button Press Event
    Sub ButtonPress(ByVal data1 As UInteger, ByVal data2 As UInteger, ByVal time As Date)
 
        'Define Serial Bytes to send out.
        Dim RequestID(7) As Byte
        RequestID = {15, 15, 32, 5, 5, 219, 4}
 
        Debug.Print("Button Pressed")
 
        'Write Serial Bytes to send to COM port
        'ComPort.Write(RequestID, 0, RequestID.Length)
 
    End Sub
 
    'Data Received on COM port Event
    Sub ComDataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)
        Dim buffer(80) As Byte
        Dim ReceivedBytes(1) As Byte
        Dim strRecvd As String = ""
        Dim ByteRead As Byte = 0
        Dim LastByteRead As Byte = 0
        Dim ByteCount As Integer = 0
        Dim i As Integer = 0
 
        'Read COM Data Byte by Byte.  
        Do Until i = 81
            ByteRead = CByte(ComPort.ReadByte())
            buffer(i) = ByteRead
            ByteCount = ByteCount + 1
 
            'If Byte=4 then stop reading unless preceeding byte is 5
            If ByteRead = CByte(4) And LastByteRead <> 5 Then
                Exit Do
            End If
 
            LastByteRead = ByteRead
            i = i + 1
 
        Loop
 
        ReDim ReceivedBytes(ByteCount - 1)
        Array.Copy(buffer, ReceivedBytes, ByteCount)
 
        'Create String to display Bytes received
        For j = 0 To ByteCount - 1
            strRecvd = strRecvd & ReceivedBytes(j).ToString & " "
        Next
 
        'Output String of Received Bytes
        Debug.Print(strRecvd)
 
        'Clear Data
        Array.Clear(ReceivedBytes, 0, ReceivedBytes.Length)
        strRecvd = ""
    End Sub
 
End Module


#3 NooM

NooM

    Advanced Member

  • Members
  • PipPipPip
  • 490 posts
  • LocationAustria

Posted 07 January 2013 - 08:21 PM

yes serial is not that smart.  first: its way esier when you know the expected "packet" size.. you than read it into a array till its reached its size. and not byte by bate.. thats slow as hell, you will loose data this way.

 

if you comminicate like with pc, or anything where you can code on both sides, i suggest using the COBS encoding from my playground (link in signature) - it removes all zeros, so you add one at the beginning of each packet (than the lenght would be good)

and than you start reading :)

 

when something runs out of sync, itr can easly resync itself, since it knows when a packet starts (the only zero, 0x00 possible is the packet start)



#4 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 07 January 2013 - 08:43 PM

Have you tried dropping a breakpoint in the OnDataReceived method - I'm wondering if you are getting stuck on the following line:

 

ByteRead = CByte(ComPort.ReadByte())

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#5 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 07 January 2013 - 09:54 PM

Thanks for the replies.

 

Unfortunately The device communication is fixed.  I cannot changed how the sensor communicates.  The each line is a one packet and the 0s are just as critical as the rest of the data.  The first two bytes (15 15) are the started characters and a 4 is the terminating character.  There is also a checksum and escape character (5) as well.  In the example I showed above the responses were all the same but they will not necessarily be the same or even the same length.

 

I have to examine it byte-by-byte but I can pull in more data at once and examine the packets in code without doing separate comport reads.  The good news is that the communication rate will be very slow at only 1 packet every second or so.  The netduino will also poll the sensor every time any information will be received.  Do you think it might be better to remove the received event and just poll then wait on a response?

 

I was having the same problem with the project and I changed to the byte-by-byte read as a test.  I didn't really seem to change anything.  I will change it back to use ComPort.Read and let you know the results.  



#6 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 18 January 2013 - 04:43 PM

Here is what I have found.  I was still having the hangup problem before I started trying a byte-by-byte read.  I changed back to using ComPort.Read (maybe someone knows a better way for me to do this) and was seeing similar results with events not triggering.

 

According to http://msdn.microsof...y/dd169610.aspx, "The DataReceived event is not gauranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer."

 

I believe this is why I could force a serial input to the Netduino, which would retrigger DataReceived and update the code.  I have switch my code from using the DataReceived as an event and instead just call a subroutine to wait for a response after sending the serial query to the remote device.

 

It isn't my favorite solution but it appears to work every time.



#7 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 18 January 2013 - 06:47 PM

Hi Prince, Also, I noticed this:
Dim RequestID(7) As ByteRequestID = {15, 15, 32, 5, 5, 219, 4}
The code is creating a RequestID of 8 bytes (0 to 7) and then only giving it 7 bytes of data. This might cause a synchronization issue by sending an extra "0" after every request. Note for C# developers who aren't accustomed to VB code: while C# treats the number in the variable declaration's array brackets as the number of elements, Visual Basic treats it as the highest element number in the zero-based array. Chris

#8 caEstrada

caEstrada

    Advanced Member

  • Members
  • PipPipPip
  • 84 posts

Posted 18 January 2013 - 08:53 PM

Hi there,

 

On the receiver, copy char by char.  Use a For upto number of remaining chars.  I have an application running in

industrial environmente and works perfectly, bearing in mind the flowmeter is demanding about times (microseconds).

 

I used Netduino plus and 4.2



#9 caEstrada

caEstrada

    Advanced Member

  • Members
  • PipPipPip
  • 84 posts

Posted 18 January 2013 - 08:55 PM

Also, in my application I do not use events; instead, I do polling.  Probably not very efficient but works, what becomes effective.

 

Let me know if I can help you.



#10 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 19 January 2013 - 06:24 PM

Hi there,

 

On the receiver, copy char by char.  Use a For upto number of remaining chars.  I have an application running in

industrial environmente and works perfectly, bearing in mind the flowmeter is demanding about times (microseconds).

 

I used Netduino plus and 4.2

 

Thanks for the reply.  My background is in PLCs and I am want to use the Netduino in place of a PLC in some of the more single-function or stand-alone industrial applications I do.  I also use a lot of serial communication and would like to have a good way that I can use as a standard for reading serial.  I almost

 

Almost all of the serial communication I use has defined start and stop characters that must be read and interpreted. I don't quite understand your response.  Are you recommending that I do a ComPort.Read and do a For Next Loop to assemble the byte array and examine each byte for the termination characters?  Or are you saying that you use the ComPort.ReadByte without issues?



#11 Cole Prince

Cole Prince

    New Member

  • Members
  • Pip
  • 8 posts
  • LocationJonesboro, AR, USA

Posted 19 January 2013 - 06:34 PM

Chris,

  Thanks for the heads up.  I was aware that VB.Net array dimensions start with element zero but I overlooked it in this test code.  I still find that I have to test my arrays to get everything to work out properly because I have a hard time keeping it all straight.  I usually have to debug it and look for all of the places I have to use array.length-1 and array(i-1)=...

 

I started with C# at first when that is all you had on netduino but I am much more familiar with the syntax of VB so I switched with 4.2.  I don't want to get into a religious argument but I should probably force myself to use C# because that seems to be what most people use.



#12 CougerAC

CougerAC

    New Member

  • Members
  • Pip
  • 3 posts

Posted 31 March 2013 - 06:51 AM

Imports Microsoft.SPOTImports Microsoft.SPOT.HardwareImports SecretLabs.NETMF.HardwareImports SecretLabs.NETMF.Hardware.NetduinoImports System.IO.PortsModule Module1  Dim ComPort As New SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)  Dim WithEvents Button As New InterruptPort(Pins.ONBOARD_SW1, True,                                             Port.ResistorMode.PullUp,                                             Port.InterruptMode.InterruptEdgeLow)  Dim Led As New OutputPort(Pins.ONBOARD_LED, False)  Dim busy As Boolean = False  Dim buttonPress As Boolean = False  Dim RequestID() As Byte = {15, 15, 32, 5, 5, 219, 4}  Dim responseBuf(0 To 79) As Byte  Dim responseIdx As Short = -1  Sub Main()        ComPort.Open()    While True      If buttonPress Then        busy = True        buttonPress = False        ComPort.DiscardInBuffer()        ComPort.DiscardOutBuffer()        Try          ComPort.Write(RequestID, 0, RequestID.Length)        Catch ex As Exception          Debug.Print("Tx Error: " & ex.Message)          busy = False          Continue While        End Try        responseIdx = -1        Do While True          Try            responseBuf(responseIdx + 1) = CByte(ComPort.ReadByte())            responseIdx += 1S          Catch ex As Exception            Debug.Print("Rx Error: " & ex.Message)            Exit Do          End Try          If responseBuf(responseIdx) = 4 Then            If responseIdx > 0 AndAlso responseBuf(responseIdx - 1) <> 5 Then Exit Do          End If        Loop        busy = False        If responseIdx < 0 Then          Debug.Print("No Data")          Continue While        End If        Debug.Print("Data:")        For i = 0 To responseIdx          Debug.Print(" " & responseBuf(i))        Next        Debug.Print(Constants.vbCrLf)      End If    End While  End Sub  Private Sub Button_OnInterrupt(data1 As UInteger, data2 As UInteger, time As Date) Handles Button.OnInterrupt    If busy Then Return    buttonPress = True    Debug.Print("Button Pressed")  End SubEnd Module

I wrote this in the blind, no Netduino handy to test. I am hoping that a call to read will somehow fail if there are no [more] bytes to read. This may not be the case, though, and may need to be handled differently (i.e. BytesToRead = 0, or, timeout after a period of time). It may also need a Threading.Sleep (Time) in the read loop, where Time should be approx. the byte period (i.e. ~1 mS for 9600 bps) to allow the framework some time to deal with incoming data.

 

Hope it helps,

Clif







Also tagged with one or more of these keywords: serial, vb.net, events

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.