Question

I am new to the world of C# and Serial communication. Having read a few tutorials, I have managed to get the communication working. I asked another similar question here but I dont think I asked the correct question. I followed the advice given in the last question and changed my code a bit so that I am now sending, from my micro controller a serial message that looks like this:

SxxxxxxxxxxxxxxxxxxxxxxxxE

The x's stand for different numbers, plus and minus signs and commas. The string I send will always be the same length and will always start with an S and end with an E (if this is bad I can change it). The problem that I am having is that when I try to read the serial line I get only parts of the message at a time, so something like this:

Sxxxxxxx
xxxxx
xxxxESxxx

I am sending this information continuously from the micro controller but only want to access it at certain times, so in other words I am trying to write a function that recieves all parts of the message, puts it back to gether and then returns it from my function. The problem is is that I have no idea how to do that at the moment.

Any help would be greatly appreciated!

This is the code I have been playing around with:

    SerialPort serialHC = new SerialPort(); // serial connection dealing with Hand Controller

     public string receiveCommandHC()
    {

        string messageHC = "";
        if (serialHC.IsOpen)
        {
            //serialHC.DiscardInBuffer();
            //messageHC = serialHC.ReadLine();
            messageHC = serialHC.ReadTo("*");
            //tempMsgHC = serialHC.ReadTo("*");
            //i = tempMsgHC.IndexOf("S");
            //tempMsgHC.Remove(0,i);
            //messageHC = tempMsgHC;

            //serialHC.Read(bufferHC = new byte[serialHC.BytesToRead], 0, serialHC.BytesToRead);
        }
        return messageHC;

I used to have the end of message being a "*"

Just tried following an example here this is what I get from that. Serial Message Received

This is what I'm sending (using Putty to check) enter image description here

Was it helpful?

Solution

It looks like you can't really act when you receive data. You won't necessarily have the complete message. So you'll need to buffer what you read until you have detected that you have a complete message.

There may be more efficient ways to do this but I'm not too familiar with them. So here's a naive algorithm to handle this. It can be implemented as a simple state machine.

Initialization:

  1. Allocate a buffer large enough to hold the largest message possible. This will hold the message as you read in the incoming data until you're ready to process it.

  2. Allocate a fixed-size buffer to read the data in to.

  3. Enter the "Waiting for a message" state.

Waiting for a message:

  1. Read each symbol until you find an "S" or the end of the message is reached.
  2. If an "S" is found, enter the "Reading in message" state.
  3. If an "S" is not found, wait for next message.

Reading in message:

  1. Copy every symbol in the data into the message buffer until an "E" is found or the end of the message is reached.
  2. If an "E" is found, schedule the contents of the message buffer to be processed, clear it and enter the "Waiting for a message" state.
  3. If an "E" is not found, wait for the next message.

Here's some code that captures the essence of the algorithm:

enum ReadState { Waiting, Reading, Finished }
static string ReadMessage(SerialPort port)
{
    var messageBuffer = new StringBuilder("S");
    var state = ReadState.Waiting;
    while (state != ReadState.Finished)
    {
        switch (state)
        {
        case ReadState.Waiting:
            if (port.ReadChar() == 'S')
            {
                state = ReadState.Reading;
            }
            break;
        case ReadState.Reading:
            messageBuffer.Append(port.ReadTo("E"));
            state = ReadState.Finished;
            break;
        }
    }
    return messageBuffer.ToString();
}

I was initially thinking of this at a much more lower level, the SerialPort class appears to have some methods that makes this a bit easier.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top