title: Unable to read from Serial Port using C# Mono (RaspberryPi)
body: <p>I'm attempting to write a C# library which looks at all available USB serial ports on a Raspberry Pi so that I can enumerate, identify and communicate with a set of Arduinos connected to the Pi via a USB hub.</p>
  
  <p>I am able to make this work on my windows machine (several Arduinos connected to my desktop computer) and have even been able to make it work on my Pi however, I am struggling to understand how to generalize the fix.</p>
  
  <p>If I attempt to run the program by itself on the Pi, I am able to open the serial port and send data however, I cannot receive anything from the Arduinos: I get timeout exceptions. I understand that Mono's implementation of SerialPort is limited and I must use SerialPort.ReadByte() instead of Readline() and the data received events (my solution is based on code from <a href="http://www.mono-project.com/HowToSystemIOPorts" rel="nofollow noreferrer">HowToSystemIOPorts</a>). My Serial port enumeration is using a method outlined in another stack exchange response <a href="https://stackoverflow.com/questions/434494/serial-port-rs232-in-mono-for-multiple-platforms">here</a>. </p>
  
  <p>My timeout is currently set to 4 seconds, which is several orders of magnitude longer than I expect to receive the message. </p>
  
  <p>After a lot of googling, I came across mention of using minicom to initialize the serial port <a href="https://stackoverflow.com/questions/5347962/how-to-connect-to-a-terminal-to-serial-usb-device-on-ubuntu-10-10">here</a>, which to my surprise allowed me to receive data from the Arduino. The biggest drawback is that I need to initialize the port using minicom and leave the process opening each time I boot the Pi. I also can't seem to figure out how to make this work with multiple Arduinos.</p>
  
  <hr>
  
  <h2>Here is what I have tried so far:</h2>
  
  <ul>
  <li>Updated the Pi firmware and software to their latest versions</li>
  <li>Attempted to use both an Arduino MEGA 2560 R3 and Arduino UNO</li>
  <li>Changed the owner of the tty* ports (ttyACM0 and ttyUSB0 in this case) to both my user and group</li>
  <li>Successfully configured the port via minicom, left the process running and start the program and read/wrote data. A manual process which only seems to work for one Arduino at a time</li>
  <li>Successfully run the program in Windows without fault</li>
  <li>Verified the Arduinos are recognized by the Pi running "dmesg | grep tty"</li>
  </ul>
  
  <hr>
  
  <h2>Here is what I hope to solve:</h2>
  
  <ul>
  <li>Automatic setup/initialization of the Arduino serial ports. Whether through a shell script run before the main program or within Mono code so that the code below can run as intended.</li>
  </ul>
  
  <hr>
  
  <h2>Here is my connection code:</h2>
  
  <pre><code>    public bool StartArduinoComms()
      {
          string[] ports = GetPortNames();
          foreach (string port in ports)
          {
              mLogger.LogMessage(ProsthesisCore.Utility.Logger.LoggerChannels.Arduino, string.Format("Found serial port {0}", port));
          }
  
          bool foundCorrectArduino = false;
  
          var idPacket = new ArduinoMessageBase();
          idPacket.ID = ArduinoMessageValues.kIdentifyValue;
  
          string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(idPacket);
  
          foreach (string port in ports)
          {
              SerialPort serialPort = new SerialPort(port, kArduinoCommsBaudRate);
              serialPort.Parity = Parity.None;
              serialPort.DataBits = 8;
              serialPort.StopBits = StopBits.One;
  
              //Only check unopened ports
              if (!serialPort.IsOpen)
              {
                  serialPort.Open();
  
                  //Disable telemtry just incase
                  var toggle = new { ID = ArduinoMessageValues.kTelemetryEnableValue, EN = false };
                  string disableTelem = Newtonsoft.Json.JsonConvert.SerializeObject(toggle);
                  serialPort.Write(disableTelem);
  
                  //Discard any built up data
                  serialPort.DiscardInBuffer();
                  serialPort.Write(jsonOutput);
                  serialPort.ReadTimeout = kIDTimeoutMilliseconds;
  
                  string response = string.Empty;
                  for (int i = 0; i &lt; kNumRetries; ++i)
                  {
                      try
                      {
                          //This is guaranteed to timeout if not configured through minicom
                          response = ReadLine(serialPort);
                          break;
                      }
                      //Catch case where the serial port is unavailable. MOve to next port
                      catch (TimeoutException)
                      {
                          continue;
                      }
                  }
  
                  if (!string.IsNullOrEmpty(response))
                  {
                      //Perform response validation
                  }
                  else
                  {
                      //Got no response
                  }
  
                  if (!foundCorrectArduino)
                  {
                      serialPort.Close();
                  }
              }
          }
  
          return foundCorrectArduino;
      }
      /// &lt;summary&gt;
      /// From https://stackoverflow.com/questions/434494/serial-port-rs232-in-mono-for-multiple-platforms
      /// &lt;/summary&gt;
      /// &lt;returns&gt;&lt;/returns&gt;
      private static string[] GetPortNames()
      {
          int p = (int)Environment.OSVersion.Platform;
          List&lt;string&gt; serial_ports = new List&lt;string&gt;();
  
          // Are we on Unix?
          if (p == 4 || p == 128 || p == 6)
          {
              string[] ttys = System.IO.Directory.GetFiles("/dev/", "tty*");
              foreach (string dev in ttys)
              {
                  //Arduino MEGAs show up as ttyACM due to their different USB&lt;-&gt;RS232 chips
                  if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
                  {
                      serial_ports.Add(dev);
                  }
              }
          }
          else
          {
              serial_ports.AddRange(SerialPort.GetPortNames());
          }
  
          return serial_ports.ToArray();
      }
  </code></pre>