Interacting with the Arduino with C#

There are times where you may want to build a nice user interface for your Arduino program to monitor input/output. In this tutorial, I will show you how to use C# to send data to and receive data from the Arduino. This tutorial assumes basic knowledge of Arduino programming and C#. For testing purposes, we will create a vary basic “echo” program that takes an input and outputs the input.

[code lang="cpp"]void setup()
{
Serial.begin(9600);
}

void loop()
{
while(Serial.available()) {
Serial.write(Serial.read());
}
}[/code]

While there is data available, we read it, then write it to the output. Now open Visual Studio and create a new Windows Forms Application. I will name it ArduinoSerial.

From your toolbox, add two Label’s, two ComboBox’s, and a SerialPort. I have named them lblCOM, lblBaud, cboPorts, cboBaud, and serialPort1 respectively. ComboBox’s cboPorts and cboBaud which will allow the user to select which COM port the Arduino is using and the correct Baud rate to use.

To get the available serial ports, use the GetPortNames() method from System.IO.Ports.SerialPort. You can then add this array to cboPorts.

[code lang="cpp"]string[] serialPorts = System.IO.Ports.SerialPort.GetPortNames();
cboPorts.Items.AddRange(serialPorts);[/code]

For the Baud rate ComboBox I am simply going to enumerate the values.
[code lang="cpp"]cboBaud.Items.Add(2400);
cboBaud.Items.Add(4800);
cboBaud.Items.Add(9600);
cboBaud.Items.Add(14400);
cboBaud.Items.Add(19200);
cboBaud.Items.Add(28800);
cboBaud.Items.Add(38400);
cboBaud.Items.Add(57600);
cboBaud.Items.Add(115200);[/code]
The final constructor takes the following form:
[code lang="cpp"]public ArduinoSerial()
{
InitializeComponent();

string[] serialPorts = System.IO.Ports.SerialPort.GetPortNames();
cboPorts.Items.AddRange(serialPorts);

cboBaud.Items.Add(2400);
cboBaud.Items.Add(4800);
cboBaud.Items.Add(9600);
cboBaud.Items.Add(14400);
cboBaud.Items.Add(19200);
cboBaud.Items.Add(28800);
cboBaud.Items.Add(38400);
cboBaud.Items.Add(57600);
cboBaud.Items.Add(115200);

cboPorts.SelectedIndex = 0;
cboBaud.SelectedIndex = 2;
}[/code]

Next we are going to create a button called btnStart. This button will initiate the connection to the Arduino. In the code for the buttons click event, we first need to get the port from cboPorts. Then are are going to assign this value to the PortName attribute of the SerialPort object.
[code lang="cpp"]serialPort1.PortName = cboPorts.SelectedItem.ToString();[/code]
We are going to do the same for the BaudRate attribute.
[code lang="cpp"]serialPort1.BaudRate = Convert.ToInt32(cboBaud.SelectedItem.ToString());[/code]
Then we are going to open the connection (and toggle the Start/Stop buttons)
[code lang="cpp"]if (!serialPort1.IsOpen)
{
btnStart.Enabled = false;
btnStop.Enabled = true;
serialPort1.Open();
}[/code]
In the btnStop click event is very similar to the above.
[code lang="cpp"]private void btnStop_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
btnStart.Enabled = true;
btnStop.Enabled = false;
serialPort1.Close();
}
}[/code]
Now we can create a TextBox and a Button called txtInput and btnSend. These two controls will be responsible for sending data to the Arduino. In the btnSend click event add the following code.
[code lang="cpp"]if (!serialPort1.IsOpen) return;
serialPort1.Write(txtInput.Text + "\n");[/code]
The rest of the magic takes place in the SerialPorts DataReceived event. To get the data from the serial port we simply call the ReadExisting() function on the SerialPort object. Then we just need to append that text to a text box. However, we must make this thread safe to prevent any dead locks.

[code lang="cpp"]/**
* http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
*/
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.txtOutput.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.BeginInvoke(d, new object[] { text });
}
else
{
txtOutput.AppendText(text);
}
}

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
SetText(serialPort1.ReadExisting());
}

catch (Exception ex)
{
SetText(ex.ToString());
}

}[/code]

Related posts:

  1. HTML with Swing Components One useful feature of Swing GUI’s many people overlook is the ability to use simple HTML tags within swing components....

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.


6 Responses to “Interacting with the Arduino with C#”

  1. Chris

    I tried a lot of examples on the other sites
    and this is the most simple and easy to understand
    Thank you very much

    Reply |

  2. José Luis

    Thank's for the Excelent example! Just a question. If I want to replace the text not to append it, how I do it?

    Thank's again.

    Reply |

    • John

      José, I'm not quite sure as I haven't written a line of C# since I wrote this blog close to a year ago, but the line of particular interest is <code>txtOutput.AppendText(text);</code> – just glancing at the Microsoft documentation for it appears that if you call the Clear() method it will clear the text box, then once the text box is clear, appending the text should simulate replacing the text.

      http://msdn.microsoft.com/en-us/library/212w06c2(…

      So, perhaps something like:

      <code>

      else

      {

      txtOutput.Clear();

      txtOutput.AppendText(text);

      }

      </code>

      Reply |

      • José Luis

        Oh, yeah, I tried with that, but it did not work in a stable way, sometimes work, but sometimes return just one character, sometines no one. Finally I solved in a not very elegant way, I create a second textBox named txtTemp2 and in the TextChanged Event of txtOutput I wrote this:

        try //This try its because, sometimes the TextBox is clear, and the -4 generate an index error.

        {

        string temporalText = txtOutput.Text.Substring(txtOutput.Text.Length – 4, 2); //Minus 4 cause the last 2 characters are /r/n or something like that, so if we put minus 2, dont show anything.

        txtTemp2.Text = temporalText;

        }

        catch

        {}

        and before the append instruction I wrote this

        if (txtTemp.Text.Length>=2&&text.Length==2)

        txtTemp.Text = "";

        which clear the TextBox every 8 characters is written, avoiding an overflow or something if the program run a long time. I don't now if that is necesary, any way, this is working until now. That thing of the delegates its very interesting. Kind regards and sorry for my terrible english.

        Reply |

  3. Angelo

    Thanks for this, it's very helpful!

    Being a newbie at C# and Windows Forms Applications, I was pulling my hair out trying to figure out why the application was never receiving anything back from my Arduino; I had to add the following line of code to the ArduinoSerial constructor:

    <code>

    serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);

    </code>

    Otherwise, the serialPort1_DataReceived event handler never gets called. This is probably an obvious requirement to more advanced programmers, but hopefully it helps out other n00bs like me that come across your article.

    Thanks again!

    Reply |

  4. Pixel2life

    Thank you so much for submitting your tutorial to Pixel2life, your submission has been accepted :) I look forward to more tutorials from your site in the future!

    Reply |