SerialPort and SerialDataReceivedEventHandler help

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kevin.M.Jonas@gmail.com

    SerialPort and SerialDataReceivedEventHandler help

    I have the following method that handles the data received event:
    private void _port_DataRecei ved(object sender,
    SerialDataRecei vedEventArgs e)
    {
    string data = _port.ReadExist ing();
    _log.LogToFile( data, true);
    }

    The LogToFile function logs data to a file. The second parameter
    indicate if the file should timestamp the message.

    On the initial test of this method I got the following result:
    [9/19/2008 4:40:04 PM]10??I 1
    [9/19/2008 4:40:04 PM] 1909081
    [9/19/2008 4:40:04 PM]640?

    This is not what I expected. I converting an old VB 6.0 program to
    C#. If I add Thread.Sleep(50 0) before the ReadExisting() I get the
    string I was expecting:
    [9/19/2008 4:57:47 PM]10??I 1 1909081657?

    Notice in the first try it is sending 8 bytes at a time. Is there
    anyway to avoid using Thread.Sleep to achieve this?
  • Stefan Hoffmann

    #2
    Re: SerialPort and SerialDataRecei vedEventHandler help

    hi Kevin,

    Kevin.M.Jonas@g mail.com wrote:
    On the initial test of this method I got the following result:
    [9/19/2008 4:40:04 PM]10??I 1
    [9/19/2008 4:40:04 PM] 1909081
    [9/19/2008 4:40:04 PM]640?
    >
    This is not what I expected. I converting an old VB 6.0 program to
    C#. If I add Thread.Sleep(50 0) before the ReadExisting() I get the
    string I was expecting:
    [9/19/2008 4:57:47 PM]10??I 1 1909081657?
    The first result looks good. I don't know, what device you are querying,
    but your string has obviously an explicit start and end symbol. Just
    read it in a loop as long as your string is not complete.


    mfG
    --stefan <--

    Comment

    • Stefan Hoffmann

      #3
      Re: SerialPort and SerialDataRecei vedEventHandler help

      hi,

      Stefan Hoffmann wrote:
      The first result looks good. I don't know, what device you are querying,
      but your string has obviously an explicit start and end symbol. Just
      read it in a loop as long as your string is not complete.
      Better than a loop (i'm using <as start/end tags):

      private string _Data = null;
      private void _port_DataRecei ved(object sender,
      SerialDataRecei vedEventArgs e)
      {
      string data = _port.ReadExist ing();

      if (_Data == null && data.StartsWith ("<"))
      {
      _Data = data;
      data = null;
      }
      if (_Data != null && data != null)
      _Data += data;
      if (_Data != null)
      if (_Data.EndsWith (">"))
      {
      _log.LogToFile( _Data, true);
      _Data = null;
      }
      }

      Depending on the kind of device, you must consider that you get strings
      like "789><12389 7"


      mfG
      --stefan <--

      Comment

      • Kevin.M.Jonas@gmail.com

        #4
        Re: SerialPort and SerialDataRecei vedEventHandler help

        I tried that. There is still only 8 bytes available at a time. The
        only solution I have found so far is to add the sleep. I don't want
        to do that because then I have to make the sleep long enough to get
        the larger messages but not so large any timeouts will be triggered.

        Comment

        • Kevin.M.Jonas@gmail.com

          #5
          Re: SerialPort and SerialDataRecei vedEventHandler help

          On Sep 25, 9:51 am, Stefan Hoffmann <stefan.hoffm.. .@explido.de>
          wrote:
          hi,
          >
          Stefan Hoffmann wrote:
          The first result looks good. I don't know, what device you are querying,
          but your string has obviously an explicit start and end symbol. Just
          read it in a loop as long as your string is not complete.
          >
          Better than a loop (i'm using <as start/end tags):
          >
          private string _Data = null;
          private void _port_DataRecei ved(object sender,
             SerialDataRecei vedEventArgs e)
          {
             string data = _port.ReadExist ing();
          >
             if (_Data == null && data.StartsWith ("<"))
             {
               _Data = data;
               data = null;
             }
             if (_Data != null && data != null)
               _Data += data;
             if (_Data != null)
               if (_Data.EndsWith (">"))
               {
                 _log.LogToFile( _Data, true);
                 _Data = null;
               }
          >
          }
          >
          Depending on the kind of device, you must consider that you get strings
          like "789><12389 7"
          >
          mfG
          --stefan <--
          That's interesting. What isn't being displayed in my post is the
          start and end character - 0x02 and 0x03.

          Comment

          • Stefan Hoffmann

            #6
            Re: SerialPort and SerialDataRecei vedEventHandler help

            hi Kevin,

            Kevin.M.Jonas@g mail.com wrote:
            I tried that. There is still only 8 bytes available at a time.
            Try setting another bit (baud) rate for your port.


            mfG
            --stefan <--

            Comment

            • Rick Lones

              #7
              Re: SerialPort and SerialDataRecei vedEventHandler help

              Kevin.M.Jonas@g mail.com wrote:
              I have the following method that handles the data received event:
              private void _port_DataRecei ved(object sender,
              SerialDataRecei vedEventArgs e)
              {
              string data = _port.ReadExist ing();
              _log.LogToFile( data, true);
              }
              >
              The LogToFile function logs data to a file. The second parameter
              indicate if the file should timestamp the message.
              >
              On the initial test of this method I got the following result:
              [9/19/2008 4:40:04 PM]10??I 1
              [9/19/2008 4:40:04 PM] 1909081
              [9/19/2008 4:40:04 PM]640?
              >
              This is not what I expected. I converting an old VB 6.0 program to
              C#. If I add Thread.Sleep(50 0) before the ReadExisting() I get the
              string I was expecting:
              [9/19/2008 4:57:47 PM]10??I 1 1909081657?
              >
              Notice in the first try it is sending 8 bytes at a time. Is there
              anyway to avoid using Thread.Sleep to achieve this?
              If you know the minimum length of an incoming message, then you could change the
              ReceivedBytesTh reshold property of the SerialPort. Or, if your incoming message
              contains a known end byte that you can synch on, you could use the ReadTo()
              method.

              HTH,
              -rick-

              Comment

              • Kevin.M.Jonas@gmail.com

                #8
                Re: SerialPort and SerialDataRecei vedEventHandler help

                I cannot change the baud rate, I have to match the machine, right?
                The minimum number of characters could be one. The machine sends an
                ACK once and a while to see if anything is listening. This is
                receiving data from a medical device. There is a comments field that
                can be filled out and that will be in the data stream

                I said VB but that was my mistake. It's a service that uses Vb to
                manage it. The code that monitors the serial port is C++. here's the
                C++ code:
                if(ReadFile(hCo mm,buf,4096,&dw BytesTransferre d,NULL) == TRUE)

                That will read the entire stream into the buffer.

                Someone suggested to me to use SerialPort.Read Line. None of these
                make a difference. First, there may be new line characters in the
                data stream that is part of the data. I've tried all of the read
                functions, the program is only getting 8 bytes at a time unless I put
                a sleep in there.

                I have even tried something like
                while (_port.BytesToR ead 0)
                {
                iRead = _port.Read(buff er, iRead, _port.BytesToRe ad);
                iTotal += iRead;
                }

                Only the first 8 bytes unless I put a sleep in the loop. A sleep
                probably isn't bad, it just has to be large enough that on slower
                machines it will still get all the data into the buffer but not so
                long that it causes any timeouts.

                I think I have to do what Stefan suggested if I want to be safe.

                BTW, thanks for the responses. I tried to get a response on the msdn
                forum but apparently my question was off topic for the general C#
                forum.

                Comment

                • Rick Lones

                  #9
                  Re: SerialPort and SerialDataRecei vedEventHandler help

                  Kevin.M.Jonas@g mail.com wrote:
                  On Sep 25, 9:51 am, Stefan Hoffmann <stefan.hoffm.. .@explido.de>
                  wrote:
                  >hi,
                  >>
                  >Stefan Hoffmann wrote:
                  >>The first result looks good. I don't know, what device you are querying,
                  >>but your string has obviously an explicit start and end symbol. Just
                  >>read it in a loop as long as your string is not complete.
                  >Better than a loop (i'm using <as start/end tags):
                  >>
                  >private string _Data = null;
                  >private void _port_DataRecei ved(object sender,
                  > SerialDataRecei vedEventArgs e)
                  >{
                  > string data = _port.ReadExist ing();
                  >>
                  > if (_Data == null && data.StartsWith ("<"))
                  > {
                  > _Data = data;
                  > data = null;
                  > }
                  > if (_Data != null && data != null)
                  > _Data += data;
                  > if (_Data != null)
                  > if (_Data.EndsWith (">"))
                  > {
                  > _log.LogToFile( _Data, true);
                  > _Data = null;
                  > }
                  >>
                  >}
                  >>
                  >Depending on the kind of device, you must consider that you get strings
                  >like "789><12389 7"
                  >>
                  >mfG
                  >--stefan <--
                  >
                  That's interesting. What isn't being displayed in my post is the
                  start and end character - 0x02 and 0x03.
                  Then, again I will suggest ReadTo(). It looks as if your data may consist of a
                  fixed length ASCII string bracketed by start and end framing values. You could
                  use ReadTo() to read up to the next start byte, as per

                  string startPattern = Encoding.ASCII. GetString(new byte[]{2});
                  string input, junk;
                  while (1)
                  {
                  /*
                  Read previous previous input through end byte
                  (should be 20 bytes as per your example). Then
                  read and discard the start byte you just found.
                  */
                  input = myPort.ReadTo(s tartPattern);
                  junk = myPort.ReadByte (); //
                  }

                  If your data pattern is as simple as you indicate then this simple loop or
                  something very like it may work for you. You would probably want to add
                  validation of the start and end bytes plus code to recover your framing if you
                  happen, e.g., to get a short input string.

                  HTH,
                  -rick-

                  Comment

                  Working...