Amir Abbas
Amir Abbas

Reputation: 49

C# scanning COM ports for specific input

I'm making a program that can control an Arduino board through C#. Here is the steps the program needs to take:

  1. Scan COM Ports
  2. Receive inputs from the devices
  3. When an input has a specific phrase such as "connectAlready",
  4. Close all ports and create a new one on the port that received the phrase.
  5. Now that the program knows what COM port the Arduino is on, it can carry on its tasks and send it commands through SerialPorts.

Below is the code i have so far for the connect() method.

public void connect()
    {
        string[] ports = SerialPort.GetPortNames();
        SerialPort[] serialport = new SerialPort[ports.Length];
        foreach(string p in ports)
        {
            int i = Array.IndexOf(ports, p);
            serialport[i].PortName = p;
            serialport[i].BaudRate = 9600;
            serialport[i].Open();
            //Scan inputs for "connectAlready"
        }

Not much i know, and i keep getting a "System.NullReferenceException" at serialport[i].PortName = p;

How can I make this program work? Thank you for all the help

Upvotes: 1

Views: 3121

Answers (2)

Ian
Ian

Reputation: 30813

Firstly, you need to declare new serial port object for each serial port which you create:

    string[] ports = SerialPort.GetPortNames();
    SerialPort[] serialport = new SerialPort[ports.Length];
    foreach(string p in ports)
    {
        int i = Array.IndexOf(ports, p);
        serialport[i] = new SerialPort(); //note this line, otherwise you have no serial port declared, only array reference which can contains real SerialPort object
        serialport[i].PortName = p; 
        serialport[i].BaudRate = 9600;
        serialport[i].Open();
        //Scan inputs for "connectAlready"
    }

And then, you need at least four things to get and to handle your data:

  1. Event handler for DataReceived for your serial port

    serialport[i].DataReceived += serialPort_DataReceived; //This is to add event handler delegate when data is received by the port
    
    private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //This is to handle the data when it comes
        //Do something on data received
    }
    
  2. Get the data from the underlying stream of the port.

    private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) {
        SerialPort serialPort1 = sender as SerialPort; 
        byte[] data = new byte[serialPort1.BytesToRead]; //this is to provide the data buffer
        Stream portStream = serialPort1.BaseStream;
        portStream.Read(data, 0, data.Length); //You get your data from serial port as byte[]
        //Do something on your data
    }
    
  3. Encoding.UTF8.GetString to convert the input data from byte[] to ASCII characters (Edit: consider of changing/skip this step and step 2 if the data received is not byte[] but ASCII)

    private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) {
        SerialPort serialPort1 = sender as SerialPort;
        byte[] data = new byte[serialPort1.BytesToRead]; //this is to provide the data buffer
        Stream portStream = serialPort1.BaseStream;
        portStream.Read(data, 0, data.Length); //You get your data from serial port as byte[]
        string dataString = Encoding.UTF8.GetString(data); //here is your data in string
        //Do something on your data
    }
    
  4. Check if the data string contains the data that you want

    bool hasData = dataString.Contains("connectAlready"); //this is to check if your data has this, if it doesn't do something
    

And as a last note, beware that the data from your serial port doesn't come together (like "conne" and then "ctAlready"). In such case, you need to copy your received data in a global buffer first then have additional checking (use Buffer.BlockCopy)

byte[] globalBuffer = new byte[4000]; //large buffer, put globally

//In your data received, use Buffer.BlockCopy to copy data to your globalBuffer
//Beware the index

if (globalBuffer.Length >= 14){ //less than this length, then the data is incomplete
     //Do the checking if length is at least 14
}

Upvotes: 2

Anup Sharma
Anup Sharma

Reputation: 2083

At this Point

SerialPort[] serialport = new SerialPort[ports.Length];

You are initializing the Array here. However at this point in for loop,

serialport[i].PortName = p;

The SerialPort object at that location is not Initialized. Hence the Null Reference Exception

So try adding this in the for loop before assigning anything to Serial port

serialport[i]=new SerialPort()

Using any constructor you need off-course.

Upvotes: 2

Related Questions