DanteTheEgregore
DanteTheEgregore

Reputation: 1540

SerialPort.DataReceived Returning Strange Results

I'm currently working with a device called a Fluke 5500A Multi-Product Calibration Device. I've written a small program in C# to interact with it and learn more about how it works but unfortunately SerialPort.DataReceived is giving me some very strange results. The program's not long so I'm going to post it in its entirety here:

class Program
{
    static public bool isExecuting = true;
    static private string serialCommand;
    static private string dataReceived;

    static void Main(string[] args)
    {
        SerialPortConnection serialPort = new SerialPortConnection();

        serialPort.OpenSerialConnection();

        while (isExecuting == true)
        {
            Console.WriteLine("Enter a command or type q to quit.");
            serialCommand = Console.ReadLine().ToUpper();

            if (serialCommand == "Q")
                isExecuting = false;
            else if (serialCommand == "CLEAR")
                Console.Clear();
            else
            {
                dataReceived = serialPort.WriteSerialConnection(serialCommand);
                Console.WriteLine(dataReceived);
            }
        }

        serialPort.CloseSerialConnection();
    }
}

}

And my SerialPortConnection class:

public class SerialPortConnection
{
    private SerialPort serialPort;
    private string dataReceived = "none";

    public SerialPortConnection(string comPort = "Com3", int baud = 9600, System.IO.Ports.Parity parity = System.IO.Ports.Parity.None, int dataBits = 8, System.IO.Ports.StopBits stopBits = System.IO.Ports.StopBits.One)
    {
        serialPort = new SerialPort(comPort, baud, parity, dataBits, stopBits);
    }

    public void OpenSerialConnection()
    {
        try
        {
            serialPort.Open();
        }
        catch (Exception e)
        {
            Console.Write("\nError");
            Console.Write(e);
        }
    }

    public string WriteSerialConnection(string SerialCommand)
    {
        try
        {
            serialPort.Write(String.Format(SerialCommand + "\r"));
            dataReceived = serialPort.ReadExisting();
            return dataReceived;
        }
        catch (Exception e)
        {
            Console.Write("\nError");
            Console.Write(e);
            return "Execution Unsuccessful";
        }
    }

    public void CloseSerialConnection()
    {
        try 
        {
            serialPort.Close();
        }
        catch (Exception e)
        {
            Console.Write("\nError");
            Console.Write(e);
        }
    }
}

My problem currently is the output to the console looks something like this:

Enter a command or type q to quit.
*IDN?

Enter a command or type q to quit.
OUT 50V <-- Command input
*IDN? <-- Previous command echoed back
FLUKE,5500A,8030005,2.61+1.3+2.0+* <-- Data received from previous command
161>
Enter a command or type q to quit.
OPER
OUT 50V
162>
Enter a command or type q to quit.
STBY
OPER
163>
Enter a command or type q to quit.
*RST
STBY
164>
Enter a command or type q to quit.

The commands execute just fine but the output to the console appears to be the last command that was executed and whatever data was returned by that command. I don't know why this could be.

EDIT:

Thanks to Robert P's answer I implemented the following code:

var received = "";
bool isReading = true;
while (isReading == true)
{
    try
    {
        received += serialPort.ReadExisting();
        if (received.Contains('>'))
            isReading = false;
    }
    catch (Exception e)
    {
    }
}
Console.WriteLine(received);

Upvotes: 2

Views: 2166

Answers (1)

Robert P
Robert P

Reputation: 15968

One part of your problem is that serial communication is far from instantaneous. The .ReadExisting() method pulls data out of the SerialPort object's buffer, but does nothing to assure that the device has finished issuing its command. Think of it like this:

+----+            +----------+           +------------+
|Your|--Command-->|Serial    |---UART--->|    Device  |
|Code|            |Port Obj  |           |            |
+----+            +----------+           +------------+

+----+            +----------+           +------------+
|Your|<--Read-----|Serial    |           |Device      |
|Code| (is empty) |          |           |(processing)|
+----+            +----------+           +------------+

+----+            +----------+           +------------+
|Your|            |Serial    |<-response-|Device      |
|Code|            |(has data)|           |(responding)|
+----+            +----------+           +------------+

+----+            +----------+           +------------+
|Your|--Command2->|Serial    |---UART--->|    Device  |
|Code|            |(has data)|           |            |
+----+            +----------+           +------------+

+----+            +----------+           +------------+
|Your|<--Read-----|Serial    |           |Device      |
|Code| (previous  |          |           |(processing)|
+----+  response) +----------+           +------------+

Instead, look for a pattern, token, or other identifying mark to know that transmission is complete BEFORE sending the next command. Keep reading (expect timeouts - they're thrown as an exception!) until you know you have received the entire reply. In this case, it might be that the > character represents "ready for more input". You can interpret it to also mean "Response is complete."

Upvotes: 2

Related Questions