Results 1 to 21 of 21

Thread: ReadTimeout not Working?

  1. #1

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    ReadTimeout not Working?

    I am communicating with an Arduino microcontroller board which is running a simple C program which echoes input on the serial port back to a PC. When the application on the PC sends the contents of a textbox to the Arduino, the code on the Arduino reads the port until it intercepts a CR and then echoes this input back to the PC, adding an LF in the process.

    Now when I use a ReadLine() method, it times out straight away, even though the timeout is set to 2 seconds. The LF code is being transmitted as I have checked it using a terminal program. I can see the TX and RX LEDs lighting on the Arduino board so transmission and reception occurs immediately without a delay. The ReadLine method should block until a terminator character is received or it times out. The odd thing is that I can use two methods of sending text to the Arduino board, type text in a textbox and press a button to transmit or type text in the same textbox and hit enter to transmit. Pressing the button doesn't create a timeout but hitting enter does. AcceptsReturn is set to true for the textbox and I have set the multline property to false so as not to confound the issue. The port is a USB virtual serial port.

    Any ideas? The Arduino C and VB code is below:

    #define CR 13
    #define LF 10

    int button_input =12;
    int led_output =7;
    int onboard_led =13;
    char received_command[50];
    byte num_chars_received;
    int char_received;


    // Arduino program. This echoes input on the serial port
    void setup()
    {
    pinMode(onboard_led,OUTPUT);
    pinMode(button_input,INPUT_PULLUP);
    pinMode(led_output,OUTPUT);

    int i;

    Serial.begin(9600); // Set the baud rate to 9600

    }

    void loop()
    {
    if(digitalRead(button_input)) // A high on a digital input allows the program to execute
    {
    if (Serial.available() > 0) // If there is data in the buffer
    {
    num_chars_received = Serial.readBytesUntil(CR, received_command, 25); // read until CR terminator. CR not inclued in number of characters received
    if(num_chars_received>0)
    {
    received_command[num_chars_received]='\0'; // terminate the string with a NULL
    Serial.println(received_command); // This writes to the serial port and adds an LF
    digitalWrite(led_output,HIGH); // Pulse LED on and off
    delay(500);
    digitalWrite(led_output,LOW);
    }
    }
    }
    }



    // Event handler for received data
    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

    Dim myArray(1) As Object

    myArray(0) = " "

    SerialPort1.ReadTimeout = 2000

    If told_to_close = True Then
    okToCloseSerialPort.Set() 'got the close message // set a wait handle.
    Exit Sub
    End If

    timeout = False
    Try
    myArray(1) = SerialPort1.BytesToRead
    myArray(0) = SerialPort1.ReadLine() + vbLf // ReadLine strips the LF when reading from the buffer so add an LF to generate a newline in the text box

    Catch ex As TimeoutException
    timeout = True
    Beep()
    End Try


    ' use a delegate for updating controls to avoid cross threading
    iasync1 = Me.BeginInvoke(DelegateDataReceived, myArray)

    End Sub



    // Transmit the contents of a textbox when a "send" button is clicked
    Private Sub btnSendCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendCommand.Click
    If SerialPort1.IsOpen = True Then
    SerialPort1.Write(txtBoxSendData.Text & vbCr) // Add a CR terminator for the benefit of the Arduino
    txtBoxSendData.Text = "" // blank the textbox
    txtBoxSendData.Focus()
    End If
    End Sub

    // Transmit the contents of a textbox when enter key is pressed
    Private Sub txtBoxSendData_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtBoxSendData.KeyPress
    If e.KeyChar = vbCr Then // Send data if enter key is pressed
    If SerialPort1.IsOpen = True Then
    SerialPort1.Write(txtBoxSendData.Text & vbCr)
    txtBoxSendData.Text = ""
    txtBoxSendData.Focus()
    End If
    End If

    End Sub
    Last edited by Eugbug; May 19th, 2013 at 07:22 AM.

  2. #2
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    Change your Catch to this
    Code:
            Catch ex As TimeoutException
                Debug.WriteLine(ex.Message)
                Debug.WriteLine(myArray(1))
                timeout = True
                Beep()
    In general you should not use a ReadLine in the DataReceived event handler. You are probably assuming that the handler will only be called once for the data being transmitted by your Arduino. My guess is that the event is being raised several times, but the first time it is called it is blocked, so the remaining events are queued. The code I provided will show how many times it is raised, and how many bytes are available when it is.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  3. #3

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    Quote Originally Posted by dbasnett View Post
    Change your Catch to this
    Code:
            Catch ex As TimeoutException
                Debug.WriteLine(ex.Message)
                Debug.WriteLine(myArray(1))
                timeout = True
                Beep()
    In general you should not use a ReadLine in the DataReceived event handler. You are probably assuming that the handler will only be called once for the data being transmitted by your Arduino. My guess is that the event is being raised several times, but the first time it is called it is blocked, so the remaining events are queued. The code I provided will show how many times it is raised, and how many bytes are available when it is.
    My debug output window shows debug messages but nothing from the debug.WriteLine method. Should I have something turned on in the VB settings to enable this?
    Also it doesn't seem to be possible to set breakpoints within the catch block of code. I have also added an integer variable within this block which should get incremented and count the number of times an exception occurs. Even though the beep sounds, the variable never gets incremented. I also used a variable to count the number of times the DataReceived handler fires and it only does this once. If the ReadLine method is blocking, can a re-entrance occur on this handler? If not then it's ok in my example to use ReadLine within the handler and block for a response. At the moment, the responses from the Arduino are simple short replies to commands from the PC. I'm not downloading any data and the Arduino isn't continuously streaming information.
    Last edited by Eugbug; May 19th, 2013 at 05:29 PM.

  4. #4
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    Are you running the code with the Release Configuration? I think it is under Build / Configuration Manager. Set it to Debug if it isn't.

    "If the ReadLine method is blocking, can a re-entrance occur on this handler?" No. The documentation is clear that only one of the SerialPort event handlers can execute at a time.

    "If not then it's ok in my example to use ReadLine within the handler and block for a response." You can do what you want, but consider this. If you send 'abcd' with a CR and you send that back with a LF added how many times do you think the DataReceived event handler will fire? It will fire once for sure, unless you have made other changes to the settings. But I suspect it is firing more than once, which is typical. Lets assume twice. One time it fires after receiving 'abc' and the second time it tries to fire for 'd' and the CRLF.

    The first time it fires you block on the readline but there is no 'line'. The second piece of data arrives, the event is queued to fire because the original is waiting on the readline. The original readline is eventually satisifed but then the second event fires and you have a new readline posted but no data is coming. Eventually that readline will, you guessed it, timeout.

    Get the Debug's fixed and we will see.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  5. #5
    Addicted Member
    Join Date
    Nov 2011
    Posts
    223

    Re: ReadTimeout not Working?

    Hi, because the data echoed is a copy of the string you transmitted you can receive the string in a String variable.

    ReadLine will read every character in the serial buffer until it encounters a NewLine character (decimal 10), it is important that the data sent from the Arduino is terminated with this value. The "Newline" value can be changed if desired, for example if your arduino data was terminated with a carriage return then Newline could be adjusted like so

    Code:
    SerialPort1.NewLine=Chr(13)
    The SerialPort1.WriteLine automatically appends the NewLine character when transmitting, if both PC and arduino could be set up to see the same "NewLine" character you could perhaps change the following line

    Code:
    SerialPort1.Write(txtBoxSendData.Text & vbCr) // Add a CR terminator for the benefit of the Arduino
    To

    Code:
    SerialPort1.WriteLine(txtBoxSendData.Text) // Add a CR terminator for the benefit of the Arduino

    Here is a simple example, the delegate displays the incoming string in a textbox with the MultiLine property set to true

    Code:
     Public Delegate Sub mydelegate(ByVal a_string As String)
    
        Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    
            Dim arduino_string As String = String.Empty
            SerialPort1.ReadTimeout = 20
    
            Try
    
                arduino_string = SerialPort1.ReadLine
                Me.Invoke(New mydelegate(AddressOf txt_out), arduino_string)
    
            Catch ex As Exception
    
            End Try
    
        End Sub
    
        Private Sub txt_out(ByVal s As String)
            TextBox1.AppendText(s & vbCrLf)
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            SerialPort1.Open()
    
        End Sub
    I was not sure why you wanted the BytesToRead, if it is important to know the character count you can capture that and display in the txt_out sub like so

    Code:
    Private Sub txt_out(ByVal s As String)
            TextBox1.AppendText(s & vbCrLf)
            Label1.Text = s.Length.ToString
        End Sub
    EDIT: a quick afterthought..........when you transmit data from PC to arduino it might be wise to make sure the output buffer is empty before you place you data string in there. Place the following as the first line of the transmit button/key

    Code:
    SerialPort1.DiscardOutBuffer()
    Last edited by Mc_VB; May 19th, 2013 at 06:51 PM.

  6. #6

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    The "Active Solution Configuration" is now set to debug however nothing is being displayed in the output window. Both "Exception Messages" and "Program Output" are checked in the output pane.
    Now this is getting stranger because I removed the beep from the catch block and it still sounds! I tried doing a build but this doesn't seem to make any difference.
    Hi Mc_VB. The reason I am using BytestoRead is to keep track on the size of the backlog in the buffer. I was fiddling around with changing the baud rate during a transmission from a GPS unit (which streams out text regularly every second).This caused a backlog of data and I wanted to see how quickly the buffer could be emptied and processed after the baud rate was changed back to the correct value. So this is sort of a legacy in the code from that.
    Last edited by Eugbug; May 19th, 2013 at 07:14 PM.

  7. #7
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    Below the active configuration is the project configuration. Is it set to debug also? What version of vb are you using?

    Is the GPS attached via a cable or is this a virtual serialport via bluetooth (mine is)?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  8. #8

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    Both active and project configuration are set to debug. I'm using VB 2008 Express Edition.
    The Arduino is attached via cable to a USB port. When connected, a virtual serial port is established.
    I have two VB projects. One for the GPS unit and the other for the Arduino. The initial project read from the GPS unit. Since some functionality is similar, I used the GPS project code. Now because it isn't possible to do a "save as" of a project, I copied and pasted the original project and manually renamed all relevant files so that they had the same name as the new project. This seems to work fine but this issue with the beep sounding even though it is remmed out led me to think that obj files were somehow being pulled in from the original project if the file list was referencing them (the DataReceive handler is the same in the original project with a beep in the catch block). Any changes I make to variables in this block don't occur. E.g. a variable won't increment. Yet this beep keeps happening! I also restarted the IDE to no avail.

  9. #9
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    I'd start a new project and copy and paste just the code you have(don't copy the files). Make sure you create the controls and components before you copy the code.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  10. #10

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    After much hassle I rebuilt the project from scratch by creating a new form and adding controls to it which all had to be renamed. I then copied and pasted the code from the original file to the new .vb file.
    (Before doing this I took a "short cut" by just creating a form in the new project, drew a selection box around the controls in the old project and copied and pasted them to the form in the new project. Unfortunately due to file references to the old project or whatever, the original code got wiped)
    The Debug.WriteLines in the catch block still aren't generating output. I set a breakpoint in the DataReceive handler and the program isn't stepping into this block. The beep which I couldn't get rid of seems to be coming from somewhere else and I have no other beep statement in the code. Sometimes it occurs when the form is displayed and also when myArray(0) = SerialPort1.ReadLine() + vbLf is executed. It's as if a break in execution occurs due to an exception. However no warning is displayed and only a beep sounds.

  11. #11
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    I'd suggest starting over with no shortcuts.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  12. #12

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    Ok, I've sorted where this beep is coming from! I am pressing ENTER in a textbox, but the multiline property is set to false. I set it to off while debugging and at the moment I don't need more than one line. Windows thinks I am requesting a new line and beeps to complain. See link http://support.microsoft.com/kb/78305.
    Thanks for all the suggestions

  13. #13
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    What about the "breakpoint in the DataReceive handler and the program isn't stepping into this block"??? Are you still having the timeouts?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  14. #14

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    Quote Originally Posted by dbasnett View Post
    What about the "breakpoint in the DataReceive handler and the program isn't stepping into this block"??? Are you still having the timeouts?
    No, it seems there were never timeouts in the first place. When the beep sounded, I got misled into thinking that this was due to the beep function I had added in the catch block. When I took it out there was still a beep due to this multiline issue. Execution never enters the catch block.

  15. #15
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    FYI. I tested this:

    Code:
        Public Delegate Sub mydelegate(ByVal a_string As String)
    
        Private Sub SerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    
            Dim arduino_string As String = String.Empty
            SerialPort1.ReadTimeout = 20
    
            Try
    
                arduino_string = SerialPort1.ReadLine
                Me.Invoke(New mydelegate(AddressOf txt_out), arduino_string)
    
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
    
        End Sub
    As I suspected it is subject to timeout errors for the reasons specified. You may not see the error, but it can happen. If you run the code at very low speeds, i.e. 1200bps, the error occurs more frequently. Just wanted to give you a heads up.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  16. #16
    Addicted Member
    Join Date
    Nov 2011
    Posts
    223

    Re: ReadTimeout not Working?

    Hi,that is the whole point of a time out, it is not a mistake in the example but designed into the code to stop the ReadLine blocking on reception due to erroneous data or signals. Any timeout value is subject to timeout errors or what would be the point in using it.

    20 mS time out should be good for in excess of a block of 40 characters at the OP's desired rate of 9600 baud. To achieve the same amount of characters without error at 1200 baud the timeout value would have to be scaled up ~x8 (160 mS). I have not tested those figures they are just calculations off the top of my head and must be somewhere in the ball park, the principal is there.

    The value in the time out is important and does not have to be a constant, it can be a variable calculated on baudrate and maximum characters allowed in a single block of data.

    It is a good point raised though and shows just one of many considerations that should be made when interfacing PC to device

  17. #17
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    Quote Originally Posted by Mc_VB View Post
    Hi,that is the whole point of a time out, it is not a mistake in the example but designed into the code to stop the ReadLine blocking on reception due to erroneous data or signals. Any timeout value is subject to timeout errors or what would be the point in using it.

    20 mS time out should be good for in excess of a block of 40 characters at the OP's desired rate of 9600 baud. To achieve the same amount of characters without error at 1200 baud the timeout value would have to be scaled up ~x8 (160 mS). I have not tested those figures they are just calculations off the top of my head and must be somewhere in the ball park, the principal is there.

    The value in the time out is important and does not have to be a constant, it can be a variable calculated on baudrate and maximum characters allowed in a single block of data.

    It is a good point raised though and shows just one of many considerations that should be made when interfacing PC to device
    Timeout errors are an indication that a mistake has occurred, it is not part of a protocol. It should be used to catch errors and nothing more. It is just a little bit harder to write code that does not have timeout errors, except for a legitimate one. This example should not have timeout errors, but because of the readline in the event handler it can have them.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  18. #18

    Thread Starter
    Junior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    25

    Re: ReadTimeout not Working?

    I'm still confused about how data is received and the DataReceived event works. The ReceivedBytesThreshold is set to 1 so once the first byte is received and stored in a buffer under interrupt control, doesn't the DataReceive event trigger? (To add to the confusion, it says in the documentation - "The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer")

    The ReadLine method in my code then reads from the buffer until a termination character is reached or a timeout occurs. By the way my timeout is set at 1 second to allow for any minor processing being done on the Arduino board. At present the response more or less instantly follows the command. Of course if a user is performing key entry on the Arduino, a delay could occur. However the Readline is only called when the DataReceive event is triggered i.e when the Arduino actually replies.

  19. #19
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: ReadTimeout not Working?

    Lets say that you send 3 characters, say 'abc', followed by the newline character, and that the DataReceived event fires for every character.

    When the 'a' is received and the event fires you post a ReadLine that is blocked.
    The 'b' is received but .Net can't raise the DataReceived event because a previous invocation is waiting on the readline, so it queues it.
    Same thing happens for the 'c'.

    Then along comes the newline and the original readline happens. But then two more DataReceived events fire with no data and you have timeouts.

    The reason you may not be seeing this is that by the time the datareceived event is fired the rest of the characters may be in the buffer.

    The easiest way to visualize this is to assume that a DataReceived event will be fired for every byte received, the worst case. Program to that standard and you will not have errors.
    Last edited by dbasnett; May 21st, 2013 at 06:38 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  20. #20
    New Member
    Join Date
    May 2021
    Posts
    1

    Re: ReadTimeout not Working?

    Hi....You need to use the same technique as the 'Blink without delay' example.

    Before you start checking if a characetr is available on the serial port, you store the current value of millis(). You then loop waiting for a character until either a character arrives or the new current millis() value is bigger than the timeout.

    pcb assembly
    Last edited by JethTran; Jul 23rd, 2021 at 04:05 PM.

  21. #21
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,598

    Re: ReadTimeout not Working?

    Welcome to the forum. Before replying to a thread, check the date of the last response. If it is more than a few months old, generally there is no reason to reply. In this case, where the last post was over 9 years ago, you definitely should not have replied. This is known as "grave digging", and is frowned upon.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width