Can't connect to Arduino from C# WIndows host on first try

Hi all,

I am using C# 2010, Windows 7 and an Arduino Nano CH340G (serial USB interface) as a serial data source.

The Arduino is configured such that when I send it an asterisk it will respond with a plus sign. This code works and I tested it using the Arduino IDE Serial monitor and Putty.

In the form load event of the Windows Forms app I get a list of comm ports and then I traverse this list looking for the one corresponding to the Arduino test device. The odd behavior that I am experiencing is that when I first connect the serial device and run my app the program does not detect the Arduino. However, if I run the app again it locates it without any problems.

I got it to work by "polling" the comm port twice. The first time around it fails; the second time around it succeeds. Here is the working C# code:

private void frmMain_Load(object sender, EventArgs e)
{

      int iCboIdx;
      int iLoop = 0;

      //Get serial ports into list.
      List<String> lsPorts = new List<String>(System.IO.Ports.SerialPort.GetPortNames());

      lsPorts.Sort();
      
      foreach (string sPort in lsPorts){

        //Add the COM id to the dropdown list, get the list index.
        iCboIdx = cboPort.Items.Add(sPort);

        //Test whether the Arduino reader is connected to this port. Return True if so
        //or False if not.

        iLoop = 0;

        //I need to do this loop because for some unknown reason the software does not locate
        //the reader on the first attempt right after the reader has been connected to the PC.
        //It always seems to work on the second attempt though.
        do
          if (comTest4Reader(sPort))
          {
            //Yes, set selected index for this item.
            cboPort.SelectedIndex = iCboIdx;

            lblStatus.Text = "Reader found on " + sPort;
            break;
          }
          else
          {
            iLoop++;
            Thread.Sleep(500);
          }
        while(iLoop<2);

        }
}

I found that this code does not work if the Sleep statement is removed or too low. This gives me a suspicion that the issue is time based, but I am unable to see how.

The C# code for the function follows:

    Boolean comTest4Reader(string sCOMPort)
    {
      //Routine that tests to see whether the COM port corresponds to the Arduino Reader.
      
      //Use a local serial port object.
      SerialPort serRdr = new SerialPort(sCOMPort, 9600);

      try
      {

        if (!serRdr.IsOpen)
        {
          string sRetMsg = "";
          serRdr.ReadTimeout = 1000;

          //bad serRdr.DtrEnable = true;

          serRdr.Open();

          serRdr.Write("*");
          Thread.Sleep(1000);

          if (serRdr.BytesToRead > 0)
          {
            byte[] buffer = new byte[3];

            // There is no accurate method for checking how many bytes are read
            // unless you check the return from the Read method.
            int iBytesRead = serRdr.Read(buffer, 0, buffer.Length);

            sRetMsg = System.Text.Encoding.Default.GetString(buffer);
          }

          serRdr.Close();

          return sRetMsg.Contains("+");

        }
        else
        {
          //Port already open, can't do test.

          return false;
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
        return false;
      }
    }

I can't seem to figure out what effect the above function has on the serial port leaving it functional on the second run. Before putting in the loop I would simply run the app, let it fail, exit and run it again, succeeding on the second try. It seems it initializes the serial port in some way that I am not able to determine. I will be testing with a different Arduino just to discard the possibility of it being the CH340G serial/USB interface. I can also test it on a different computer.

I am aware of the issue surrounding this USB/serial interface chip, but so far have been able to make this Arduino (technically it is called a DCcduino) work with the Ardiuno IDE and aside from this odd glitch the app works fine.

Has any one experienced this behavior? Any suggestions on what sort of initialization procedure I can follow with each comm port? I would like to remove the loop that performs each test twice as this slows down the start of the app. Thanks all for your help and orientation. Saga

What happens if you close the Arduino Serial port, send a message from Visual Studio, and then open the Arduino com port. Do you see anything?

Thanks econjack.

I changed the code, removed the Sleep function from the main Do loop and instead put in a MessageBox.Show() that displays a message. The code ran dine, but it still took two tries to locate the Arduino port. Saga

I wrote this some time ago, but see if it sheds any light for you:

using System;
using System.Threading;
using System.IO.Ports;
using System.IO;
using System.Windows.Forms;


public class frmMain : Form
{
  SerialPort currentPort;
  bool portFound;

  #region Windows-generated code

  private void InitializeComponent()
  {

  }
  #endregion

  public frmMain()
  {
    InitializeComponent();
    SetComPort();
  }
  [STAThread]
  public static void Main()
  {
    frmMain main = new frmMain();
    Application.Run(main);
  }

  private void SetComPort()
  {
    try
    {
      string[] ports = SerialPort.GetPortNames();
      foreach (string port in ports)
      {
        currentPort = new SerialPort(port, 9600);
        currentPort.Parity = Parity.None;
        currentPort.DataBits = 8;
        currentPort.StopBits =  (StopBits) 1;

        if (DetectArduino())
        {
          portFound = true;
          break;
        }
        else
        {
          portFound = false;
        }
      }
    }
    catch (Exception e)
    {
    }
  }
  private bool DetectArduino()
  {
    try
    {
      //The below setting are for the Hello handshake
      byte[] buffer = new byte[5];
      buffer[0] = Convert.ToByte(16);
      buffer[1] = Convert.ToByte(128);
      buffer[2] = Convert.ToByte(0);
      buffer[3] = Convert.ToByte(0);
      buffer[4] = Convert.ToByte(4);
      int intReturnASCII = 0;
      char charReturnValue = (char)intReturnASCII;
      currentPort.Open();
      currentPort.Write(buffer, 0, 5);
      Thread.Sleep(1000);
      int count = currentPort.BytesToRead;
      string returnMessage = "";
      while (count > 0)
      {
        intReturnASCII = currentPort.ReadByte();
        returnMessage = returnMessage + Convert.ToChar(intReturnASCII);
        count--;
      }
      
      //ComPort.name = returnMessage;
      currentPort.Close();
      if (returnMessage.Contains("HELLO FROM ARDUINO"))
      {
        return true;
      }
      else
      {
        return false;
      }
    }
    catch (Exception e)
    {
      return false;
    }
  }
}

Thanks again econjack,

I recognized the code that you posted. When looking how to recognize the Arduino found the page that lists that code. In fact, if you'll notice, the code that I posted is a derivative of that original code. It was very helpful!

Update: I tested my C# app using an original Arduino Uno and the codes works perfectly, so now I begin to suspect that it is some idiosyncratic detail that I am missing dealing specifically with the CH340G chip. Saga