Language: EN

esp32-net6-serial

How to connect an ESP32 with NET6 via serial port

We are launching a series of entries aimed at seeing the different ways to connect an ESP32 with a computer through an application made in NET6, written in C#.

Let’s remember that NET6 is cross-platform and, therefore, is available on computers with Windows, Android, Linux, or Mac, as well as on x86/x64 and ARM7 or higher architectures.

This means that we can run the same program, for example, on our desktop computer with Windows or Linux, as well as on our Android mobile, or on our Raspberry Pi. All this without the need to make any changes to the code.

And we start the series by looking at one of the simplest forms of communication, which is to use a serial port (or UART).

ESP32 Code

For this series of entries, I am going to use an M5 Stick C device, which has a built-in screen and an accelerometer, because it is very useful for developing content. But any device similar to an Arduino with Wifi, such as any model of the ESP32 family, will serve us.

In the Github repo, I leave you the complete examples, with the code of the ESP32 and the NET. You have a link at the end of the entry. Here we are going to comment only on the relevant parts. In the repo, you have four examples:

  • 00_Timer
  • 01_Button
  • 02_Accelerometer
  • 03_Receive

In the first three examples, the ESP32 sends data to the NET6 application. The first example is the simplest, and we simply send the commands with a timing. In the second, when we press a button. In the third, we send the command based on whether the device is vertical or lying down, using the accelerometer of the M5 Stick C.

If we look, for example, at the code for the accelerometer case, the sending part is done in the Update() function,

void Update()
{
  if(isOn == false && GetIsTumbado() == false)
  {
    isOn = true;
    Serial.println("A");
  }
  else if(isOn == true && GetIsTumbado() == true)
  {
    isOn = false;
    Serial.println("B");
  }
}

We simply use Serial.println(…) to send the data to the NET6 application, where I am basically using the accelerometer to detect when the device is lying down or standing up.

That simple. The other two examples have a similar Update(…) function, with small variations depending on the particular case. But the serial communication part is basically just as simple.

In the fourth example, ‘Receive’, the ESP32 receives data sent from the application. In this case, the ‘Update()’ function would be the following,

void Update()
{
  if (Serial.available())
  {
    auto content = Serial.readStringUntil(‘\n’);
    if(content == "A") isOn = true;
    if(content == "B") isOn = false;

    Render();
  }
}

Where we simply check if there is pending data to receive, using the newline separator ‘\n’. Next, we read the content and perform the necessary actions. In the example, we simply change the screen to red or green, depending on the received value.

NET6 Code

On the other hand, moving to the NET6 side, we create a simple console application. Then, we add the System.IO.Port assembly.

To maintain a minimum of cleanliness, we encapsulate the program logic associated with the serial port in an independent object. I leave you a basic structure in the ArduinoPort.cs file. You can reuse it in your project, or modify it according to your needs.

With this, the code to send from NET6 to the ESP32 would be as follows,

ArduinoPort arduinoPort = new ArduinoPort();
arduinoPort.DataArrived += ArduinoPort_DataArrived;

// USB port example on Windows
arduinoPort.Open("COM4", 115200);

// USB port example on Linux
//arduinoPort.Open("/dev/ttyUSB0", 115200);

Console.ReadLine();

void ArduinoPort_DataArrived(object? sender, EventArgs? e)
{
  var lastRecieved = arduinoPort.LastRecieved;
  Console.WriteLine(lastRecieved);
}

We compile the code and run it, either on a computer with Windows, a Raspberry Pi, or any other available platforms. We just have to keep in mind that we must replace the COMx or ttyUSBx port with the name of the port on our device.

Now, with the device connected via USB, when we lay the device down, we see the ‘A’ and ‘B’ received in the console application. With this, we would take the necessary actions. Just as we could send ‘A’ and ‘B’ or any other information, as we have seen in the numerous entries about the serial port on the blog.

In the case of wanting the NET6 application to send information to the ESP32, which would correspond to example 03_Receive.ino, we can use the ‘arduinoPort.Write(…)’ function;

For example, with the following code, we would alternately send ‘A’ and ‘B’ every two seconds, so the screen connected to the ESP32 would change from green to red.

var isOn = false;
var timer = Observable.Interval(TimeSpan.FromSeconds(2))
  .Subscribe(async _ =>
  {
    var message = isOn ? "A" : "B";
    isOn = !isOn;
    
    arduinoPort.Write(message);
    Console.WriteLine(message);
  });

That’s how simple we could communicate an ESP32 with a NET6 application written in C#. In the next entry in the series, we will move on to wireless communication via WiFi, seeing how to use HTTP requests.

Download the code

All the code from this post is available for download on Github. github-full