Arduino to C# using socket

by luca
27 comments

When you want to make Arduino “talk” on your network, you usually choose the HTTP protocol, that allows to use a web browser  (IE, Firefox…) as a client. Sometimes however you need Arduino to send data to other applications: in this case you can implement a socket connection.

This tutorial is split in two parts:

[checklist]

  • in the first one, I’m going to show how to write a socket application using C#
  • in the second one, I’m going to show how to write a sketch for your Arduino

[/checklist]

Socket server in C#

The .Net framework  can work with sockets in two modes: synchronous and asynchronous.

Synchronous methods are blocking: the thread in which they are called stops until the method finishes. If, for example, you call the Receive() method to read data from a socket, that method will block the execution until some bytes are available or until a timeout triggers.

Asynchronous method instead ask the framework to manage the request, passing the callback object that has to be called at the end of the request. Usually those methods start with Begin (for example BeginReceive()). Programming using asynchronous methods is more complex: for this tutorial I’m going to show you the synchronous approach, but using a different thread to avoid blocking my application’s GUI.

The SocketServer application is therefore composed by two elements:

  • the GUI (Form1.cs) to interact with the user

  • the SocketHandler class (Program.cs) to receive socket connections from Arduino

My program will receive from Arduino the room temperature and it will display it both in text and in graphical form (with a progress bar); I also added a text area to write a debug log.

The Socket class

.Net framework uses the Socket class to manage incoming/outgoing connections.

First, include the package System.Net.Sockets, then – when the user clicks the Start listening button – configure a Socket instance to listen on the specified TCP port:

IPAddress listeningIp = IPAddress.Any;
IPEndPoint listeningEndPoint = new IPEndPoint(listeningIp, listeningPort);
listeningSocket = new Socket(listeningIp.AddressFamily, SocketType.Stream, 
  ProtocolType.Tcp);
listeningSocket.Bind(listeningEndPoint);
listeningSocket.Listen(10);

Create a new IPEndPoint object, specifying the IP address on which to listen from connections (in our code Any, that is any network interface of your PC) and the port. Then create a new Socket object for TCP protocol. Finally bind that object to the endpoint and start listening, waiting for new incoming connections (10 is the maximum number of connections in the queue).

SocketHandler socketHandler = new SocketHandler(listeningSocket, this);
serverThread = new Thread(new ThreadStart(socketHandler.startListening));
serverThread.Start();

To avoid blocking the program, start a new Thread running the SocketHandler object that will manage each incoming connection:

try
 {
  // Wait for incoming connection
  handlerSocket = listeningSocket.Accept();
  handlerSocket.ReceiveTimeout = 5000;
  IPAddress clientAddress = ((IPEndPoint)handlerSocket.RemoteEndPoint).Address;

The Accept() method is blocking: the thread will wait for a new connection… when this arrives, set 5 seconds as read timeout and get the connecting client’s IP address.

while (true)
{
  // Save received bytes
  byte[] buffer = new byte[1024];
  int bytesRec = handlerSocket.Receive(buffer);
  message += Encoding.ASCII.GetString(buffer, 0, bytesRec);
 
  // Message completed? Parse it...
  if (message.Contains("\r"))
  {
    myForm.setTemp(message.Replace('.', ','));
    myForm.log(" message received: " + message);
    break;
  }
}

Read the incoming data with the Receive method (this is blocking too: if no data is available in 5 seconds, a timeout exception is raised) until you receive the “carriage return” char (\r) that indicates the end of the message. Now you can parse what you received and display the temperature.

Tips

The complete source code is available on Github; before looking at the Arduino’s sketch here are a couple of tips:

– if you use more than one thread, you need to pay attention to how you update the GUI elements: these indeed can be updated only by the same thread that created them. From a different thread you therefore have to call delegate methods of the main thread:

myForm.setTemp(message.Replace('.', ','));
[...]
public delegate void setTempCallback(string temperature);
public void setTemp(string temperature)
{
  if (InvokeRequired) this.Invoke(new setTempCallback(setTemp), 
    new object[] { temperature });
  else
  {                
    float floatTemp;

– calling the Abort() method of a thread waiting in Accept() state is not enough to close that thread; you have to invoke the Close() method of the Socket object before aborting the thread:

listeningSocket.Close();
serverThread.Abort();
log("Listening stopped");

Related Posts

27 comments

lucadentella.it – Da Arduino a C# via socket | scatol8® | Scoop.it Friday February 1st, 2013 - 08:35 PM

[…] Quando Arduino deve comunicare via rete, spesso si sceglie il protocollo HTTP perché consente di utilizzare come client un semplice browser web (IE, Firefox…). A volte però è necessario che Arduino invii dei dati ad altre …  […]

Reply
pixel Thursday March 14th, 2013 - 03:23 PM

Ciao Luca,
non riesco a trovare lo sketch puoi darmi maggiori indiaczioni? Puoi anche fornire l’eseguibile c#?

Grazie

Reply
luca Thursday March 14th, 2013 - 09:18 PM

ciao, trovi tutto nel Repository su GitHub.

Reply
lucadentella.it – enc28J60 e Arduino (14) Monday April 22nd, 2013 - 07:27 PM

[…] Nell’esempio, leggerò con Arduino la temperatura dell’ambiente tramite il sensore DS18B20 di cui vi ho già parlato in questo articolo. […]

Reply
igor Friday May 3rd, 2013 - 03:28 PM

Domanda, non ho capito a cosa serve:
>> Stash::prepare(PSTR(“$H”), sd);
?

Reply
luca Friday May 3rd, 2013 - 08:45 PM

ciao, serve a preparare il pacchetto che poi invierai con tcpSend(). Il contenuto del pacchetto è soltanto “sd”, ovvero l’oggetto stash creato prima che contiene la temperatura e il terminatore di riga \r. $H è un “segnaposto” per la variabile che specifichi dopo (“sd”). Se guardi gli altri esempi vedrai pacchetti più complessi, con una parte fissa (“GET…”) e alcune variabili ($H, $F…).

Reply
wolf Wednesday September 25th, 2013 - 03:09 AM

Hi Luca.
nice tutorial, do the job very well.
I’m write the PC side (your C#) in Perl. the work is the same, the look and feel not.

Reading your tutorial, analizing the TCP packages, working with my perl socket script, I can see how the TCP port open and close for every temperature send by the arduino.

It is possible (I don’t know how) open permanently the port and send the text over and over the same open port?

It is possible open the port and do something bidirectinally (receive and send data over TCP to the arduino)

anyway, Thanks a lot for every tutorial in our webpage. it’s rocks

Reply
mourinhothinh Monday October 14th, 2013 - 03:26 AM

hi Luca
I had download you code. I replace the sensor data by code: float float_temp = 27.5; because i don’t have the sensor and the library.
But when i build the code in arduino and C#, nothing happen. it’s not connect between the arduino and pc.
Can you help me?

Reply
luca Wednesday October 23rd, 2013 - 09:40 PM

Hi, are you sure the IP address of Arduino and of your PC (running the demo app) are in the same network? Are you able to ping the Arduino address from your PC?

Reply
mourinhothinh Sunday October 20th, 2013 - 10:59 AM

hi Luca,

I want to send data from C# to arduino. i try function :
ether.tcpReply() but the arduino don’t receive anything. can you help me?

if you have any example can you post it to your website?
thank so much!

Reply
luca Wednesday October 23rd, 2013 - 09:36 PM

Hello!

you use the tcpReply() to send data FROM Arduino… to receive data (sent from a C# app) to Arduino you can follow the examples as it was a webserver, like this one.

Reply
Maximiliano El,izondo Saturday October 26th, 2013 - 03:25 PM

Hi! Nice work! 😉
I am working with Arduino and C# but I need to work in a asyncronous way… do you have any example? Do you know if there is some web site or book to find some good information? Thank you very much!

Reply
luca Saturday October 26th, 2013 - 04:20 PM

Hi Maximiliano,

what do you mean for “asyncronous” way? c# side, using the non-blocking socket methods?

Reply
Salinda Saturday November 16th, 2013 - 05:54 PM

Hi Luca i’m working on RFID with LAN, i downloaded your program, and c# code works fine when i test i with a c# client (on my LAN using different PC ), but my Arduino does not send any data, but i can ping to it, this setup is on LAN no internet is that a problem? Thanx in advance

Reply
luca Saturday November 16th, 2013 - 07:53 PM

Hi Salinda,

no, it doesn’t need an Internet access to work… did you use the exact Arduino sketch that is in my repository? Which ethernet shield are you using?

Reply
salinda Sunday November 17th, 2013 - 03:14 AM

no i change it litte, coz i dont have a dhcp so i use Static setup function, and for the float i give fixed value. my problem is pings works, but there is no coming data to c# , this is the shield i use
http://dereenigne.org/wp-content/uploads/ENC28J60.jpg

Reply
Salinda Sunday November 17th, 2013 - 04:37 AM

Hi Luca, i got it solved, it’s the Ether Card new Library, i use the old library form here https://github.com/vworp/OldEthercard

i test it with both dhcp and static works fine, new library is not working for both(at the moment),

can you please help me on how to send a data back, like Acknowledgmentt back to Arduino when i recive a data.(ex RFID recived and display a username on lcd)

Reply
luca Sunday November 17th, 2013 - 10:39 AM

Good! Very strange the new library doesn’t work… anyway I’m working on a bidirectional example!

Reply
mourinhothinh Wednesday November 20th, 2013 - 02:03 AM

Hi luca,
I have a propblem. I send data from arduino to C# app. I use ether.tcpSend() function like you example. It work. But it just work about 5 minute or send about 32 times and then it doesn’t work. it don’t send data from arduino(ENC28j60) to C# app any more. I don’t know how?

thank so much!

Reply
mourinhothinh Wednesday November 20th, 2013 - 10:07 AM

I think the buffer is full. can you tell me how to clear the buffer?

thanks!

Reply
rafael Tuesday July 8th, 2014 - 01:51 AM

Hello Lucas. I am working on a project where the Arduino is a client and have to send and receive data received by the serial port to ethernet ENC28J60 like the example you have in C #. Could you please help me?

Reply
luca Tuesday July 8th, 2014 - 08:11 AM

Hi Rafael, what help do you need?

Reply
rafael Tuesday July 8th, 2014 - 10:43 PM

I just need to send and receive against a set of strings through an ethernet connection client, already tried several examples but none worked so they send the data but not receive anything.

Reply
Bogdan Wednesday August 5th, 2015 - 12:18 PM

Can you please put libraries you used on github or just send them to my email. nmarbm@gmail.com. I im using W5100 ethernet shield and cant really just upload your sketch to arduino adn I dont really understand code that well to change your code to work on my shield.

Reply
luca Thursday August 6th, 2015 - 12:27 PM

Hi! The library I use for my shield is the Ethercard one from Jeelabs: https://github.com/jcw/ethercard

Reply
Fernando Wednesday September 4th, 2019 - 04:53 AM

Buon pomeriggio, nel codice di c # non riesco a trovare dove configurare su quale porta il software PC ascolta. È il PC che funge da server e Arduino come client, giusto?

Reply
luca Friday September 20th, 2019 - 09:25 AM

corretto, la porta è configurabile da GUI (nel mio esempio è la 1000)

Reply

Leave a Comment

18 + 17 =