APorter
APorter

Reputation: 11

C# Virtual Serial Port Issue! Does not recover after bad command

I am a beginner programmer and am currently working on a project with virtual serial ports. This is my first time working with them and I am still learning. Right now, I am just trying to basically create my own version of putty--something where I can just confidently read and write from a port.

I am trying to get force data back from a load cell. They respond to a command set I was given, (like "w" returns weight) and if the command is not recognized it responds with an "E".

A lot of the time my code works--as long as I do not give it a command it does not recognize, it responds as it should. However, once I send a bad command, it will only respond with "E" from there on out, even to correct commands. Closing and re-opening the port within my code has not helped--it still only responds with the "E".

The only way I have been able to "reset" the situation has been to open and close a session in Putty. Then I can get good data from my program again. The load cell responds as it should in Putty 100% of the time, and is able to recover after a bad command.

What could Putty be doing to "reset" the situation, that I am not already doing in my code? I am closing the port... Help!!!

    static SerialPort firstSerialPort;
    static bool myContinue;

    static void Main(string[] args)
    {
        string message;
        Thread readThread = new Thread(Read);

        //Initializing a SerialPort object
        firstSerialPort = new SerialPort("COM3", 9600, Parity.None,8,StopBits.One);

        //Checking if serial ports are initially open
        Console.WriteLine("First serial port is open: {0}", firstSerialPort.IsOpen);

        //Selecting the properties
        firstSerialPort.Handshake = Handshake.XOnXOff;
        firstSerialPort.DtrEnable = false;
        firstSerialPort.RtsEnable = false;

        //Opening the ports
        Console.WriteLine("Attempting to open the ports!");
        firstSerialPort.Open();

        //Clearing the buffers
        firstSerialPort.DiscardOutBuffer();
        firstSerialPort.DiscardInBuffer();
        firstSerialPort.BaseStream.Flush();

        myContinue = true;
        readThread.Start();
        Console.WriteLine("First serial port is open: {0}", firstSerialPort.IsOpen);

        Console.WriteLine("Type QUIT to exit"+"\n");

        while (myContinue) {
            message = Console.ReadLine();
            if (message == "QUIT")
            {
                myContinue= false;
            }
            else
            {
                firstSerialPort.WriteLine(message + "\r");
            }
        }

        Console.WriteLine("\n"+ "Attempting to close the ports!");
        firstSerialPort.Close();

        Console.WriteLine("First serialPort is open: {0}", firstSerialPort.IsOpen);

        //Holding console open
        Console.WriteLine("Press any key to continue.");
        Console.ReadKey();
    }

    public static void Read()
    {
        while (myContinue) 
        {
            while (firstSerialPort.IsOpen)
            {
                Thread.Sleep(100); //This adds a delay. Commands will not work without this

                try
                {
                    //Reading back data 
                    string firstMessage = firstSerialPort.ReadLine();

                    Console.WriteLine("firstMessage: {0}", firstMessage);

                    Console.WriteLine();

                }
                catch (System.IO.IOException error)
                {
                    return;
                }
                catch (System.InvalidOperationException error)
                {
                    return;
                }
            }
        }
    }

Upvotes: 1

Views: 450

Answers (1)

Baddack
Baddack

Reputation: 2053

I've written a few terminal programs, similar to putty and hyperterminal. To elaborate on my comment, here is some code to help:

My forum has a Keypress event, in which I take whatever key was pressed and write it to the serialport. Note that this is just a simple example, but should get you going in the right direction:

public const int WM_VSCROLL = 0x0115;
public const int SB_BOTTOM = 7;

[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    try
    {
        //scroll terminal to latest char
        richTextBoxConsole.SelectionStart = richTextBoxConsole.Text.Length;
        SendMessage(richTextBoxConsole.Handle, WM_VSCROLL, SB_BOTTOM, 0);

        //Send character to port
        serialPort1.Write(e.KeyChar.ToString());
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Here is my datarecieved event:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string data = serialPort1.ReadExisting();

    //DataReceived event is on it's own thread, need to invoke to update the UI
    this.Invoke((MethodInvoker)delegate
    {
        foreach (char c in data)
        {
            richTextBoxConsole.AppendText(c + "");

            if (c == '\b')
            {
                //backspace, erase a char
                richTextBoxConsole.Text = richTextBoxConsole.Text.Substring(0, richTextBoxConsole.Text.Length - 2);
            }
        }

        richTextBoxConsole.SelectionStart = richTextBoxConsole.Text.Length;
        SendMessage(richTextBoxConsole.Handle, WM_VSCROLL, SB_BOTTOM, 0);
    });
}

Upvotes: 1

Related Questions