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

SerialPort.DataReceived

Serial port

  • Please log in to reply
4 replies to this topic

#1 Jamo

Jamo

    Member

  • Members
  • PipPip
  • 13 posts

Posted 29 June 2013 - 11:38 AM

Can anyone explain how the SerialPort.DataReceived works?

 

I have a serial port read GPS signals but it also fills up the buffer with 0's.

 

My Netduino 1 Tx and Rx are connected to a small circuit that coverts a single wire serial GPS. It could be that the setup is causing an issue but I'm not sure if that is the case or where to look.

 

My code is as follows...

namespace SerialPortHelper{    public class SerialPortClass    {        static SerialPort serialPort;        const int bufferMax = 1024*8;        static byte[] buffer = new Byte[bufferMax];        static int bufferLength = 0;        public SerialPortClass(string portName = SerialPorts.COM1, int baudRate = 4800, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One)        {            serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);            serialPort.ReadTimeout = 10; // Set to 10ms            serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);            serialPort.Open();        }        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            lock (buffer)            {                int bytesReceived = serialPort.Read(buffer, bufferLength, bufferMax - bufferLength);                if (bytesReceived > 0)                {                    bufferLength += bytesReceived;                    if (bufferLength >= bufferMax)                        throw new ApplicationException("Buffer Overflow.  Send shorter lines, or increase line BufferMax.");                }            }        }        public string ReadLine()        {            string line = "";            lock (buffer)            {                //-- Look for Return char in buffer --                for (int i = 0; i < bufferLength; i++)                {                    //-- Consider EITHER CR or LF as end of line, so if both were received it would register as an extra blank line. --                    if (buffer[i] == 'r' || buffer[i] == 'n')                    {                        buffer[i] = 0; // Turn NewLine into string terminator                        line = "" + new string(Encoding.UTF8.GetChars(buffer)); // The "" ensures that if we end up copying zero characters, we'd end up with blank string instead of null string.                        //Debug.Print("LINE: <" + line + ">");                        bufferLength = bufferLength - i - 1;                        Array.Copy(buffer, i + 1, buffer, 0, bufferLength); // Shift everything past NewLine to beginning of buffer                        break;                    }                }            }            return line;        }        public string ReadGPSLine()        {            string line = "";            lock (buffer)            {                //-- Look for Return char in buffer --                for (int i = 0; i < bufferLength; i++)                {                    //-- Consider EITHER CR or LF as end of line, so if both were received it would register as an extra blank line. --                    if (buffer[i] == '$')                    {                        line = "" + new string(Encoding.UTF8.GetChars(buffer));                    }                    else if (buffer[i] == 'r' || buffer[i] == 'n')                    {                        buffer[i] = 0; // Turn NewLine into string terminator                        line = "" + new string(Encoding.UTF8.GetChars(buffer)); // The "" ensures that if we end up copying zero characters, we'd end up with blank string instead of null string.                        //Debug.Print("LINE: <" + line + ">");                        bufferLength = bufferLength - i - 1;                        Array.Copy(buffer, i + 1, buffer, 0, bufferLength); // Shift everything past NewLine to beginning of buffer                        break;                    }                }            }            return line;        }...


#2 ziggurat29

ziggurat29

    Advanced Member

  • Members
  • PipPipPip
  • 244 posts

Posted 29 June 2013 - 09:25 PM

Hi Jamo; your handler looks sensible to my eyes, though I haven't run the code.

 

The DataReceived is meant to be fired when there is data available in the internal buffers, that you can retrieve with Read().  You need to retrieve all that is available, because you will not get another event fired until a new received byte comes in (i.e., merely having some unread data will not stimulate the event).

 

This seems to be how you interpreted it yourself, so maybe look for some bugs in managing your write index into your application buffer, or maybe in how you are pulling lines and and doing the bookkeeping of that pointer.

 

That being said, I do want to mention that I (and others) have had problems with DataReceived ceasing to function inexplicably after some time.  I seems to be somehow related to how much other stuff you've got going on in your app.  (some folks have it happen as soon as they do ethernet in another thread, and for me it just seems to be the number of threads while running several serial ports).  So heads-up on looking out for that.

 

Lastly, someone else had a serial port question, and coincidentally they were using a GPS, and also coincidentally I wrote some code that does the serial stuff of reading and emitting the NMEA lines.  Maybe that sample will be useful in some way:

 

http://forums.netdui...roblem/?p=47392

 

(don't worry, there is still be plenty of coding to do; that sample does not interpret the NMEA, it just assembles the lines from the incoming data and emits them for something else to handle).



#3 MikeR

MikeR

    New Member

  • Members
  • Pip
  • 1 posts

Posted 29 June 2013 - 10:41 PM

Jamo:

 

You are not handling the data received event properly. You can make no assumptions about the number of bytes that are ready to be read. You can determine the number of bytes in the internal buffers by the serialPort.BytesToRead property. You should then read that many bytes.

 

I use the following code

while (serialPort.BytesToRead > 0){     serialPort.Read(buffer, bufferIndex, serialPort.BytesToRead);     .... process bytes}


#4 Jack Chidley

Jack Chidley

    Advanced Member

  • Members
  • PipPipPip
  • 99 posts

Posted 30 June 2013 - 02:39 PM

Is acting on the data when you get it necessary for your application or would some kind of polling work instead?

 

I'm polling once a second (the update frequency of the GPS) and then logging the data to an SD card (N1 Plus).  Works for me.

 

You could write your own GPS Parser but there are plenty available.  Stefan has one in his toolbox for example.

 

When I've been looking at these GPS problems I've used both a USB/Serial device (USB BUB II) and / or Saleae Logic analyser to confirm what's going on.  Wiring issues make me want to tear my hair out.



#5 Skyrmir

Skyrmir

    New Member

  • Members
  • Pip
  • 4 posts

Posted 02 July 2013 - 07:46 PM

As an aside, if you're going to be porting this code to a linux system using Mono at any point in the future, the datarecieved event doesn't work in Mono.  So converting to a polling method is probably a good idea.







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.