Language: EN

esp32-uart

How to use the Serial Port (UART) on ESP32

The UART, or Serial Port as it is commonly known in the Arduino world, is a communication protocol that allows the transmission and reception of data asynchronously between devices.

Unlike synchronous communications, such as SPI or I2C, UART does not require an additional clock signal. This makes it a flexible and widely used option in a variety of applications.

UART ports allow us to communicate with other devices, such as other microcontrollers, computers, sensors, GPS modules, some types of screens, among others.

UART on ESP32

The ESP32 has more than one UART, depending on the model you are using. Specifically:

  • The ESP32 and ESP32-S3 have 3 UARTs
  • The ESP32-S3 and ESP32-C3 have 2 UARTs

These ports are called UART0, UART1, and UART2. Each of them can use four pins, RX, TX, CTS, and RTS. But the Arduino environment only uses RX and TX.

Another difference between the ESP32 and a conventional Arduino is that, thanks to its multiplexer, we can reassign the UART to any pin without loss of performance.

The UARTs come preconfigured to use certain pins. But we can, and sometimes must, change the pins.

These are the default assignments for the ESP32

UART PortTXRXRTSCTS
UART0132219
UART1109116
UART2171678

As we can see, the UART1 TX and RX pins coincide with those used to connect the SPI Flash memory. So if we want to use the UART, we will have to reassign the pins.

These are the default assignments for the ESP32-S3

UART PortTXRXRTSCTS
UART049501516
UART117181920
UART2----

In this case, UART2 comes without being associated with any pin by default. So if we want to use it, we will have to reassign it to a pin of our choice.

How to use UART on ESP32 in the Arduino environment

Using UART on the ESP32 in the Arduino environment is not too complicated, if we know what we are doing.

Basically, we have the same functions available as we would have on any Arduino, such as print(), println(), read(), available(), and others to send and receive data.

Serial.println("Hello, UART!");

If you have any doubts, check the links of the tutorials I mentioned before.

Using multiple UARTs on the ESP32

The only “mess” you are going to have is with the pins of UART1 and UART2. In an effort to make it easier, just as it is done in the Arduino Mega, the ESP32 Core for Arduino defines three UARTs as Serial, Serial1, and Serial2.

The “normal” Serial is an alias for UART0 and it will work without problems. It is used for programming and communication via the board’s USB. Therefore, changing its pins is neither necessary nor a good idea.

The situation changes with Serial1 and Serial2. Depending on your ESP32 model and your board, it is normal for them not to work.

The best thing you can do if you want to use more than one UART is to define the pins manually. In fact, I wouldn’t even think of using UART1 or UART2 without specifying which pins it is associated with.

The good news is that it is very easy to associate them. For this, we need the HardwareSerial library, which is the “guts” of what we call ‘Serial’ in Arduino.

The necessary steps are

  • Include the library
  • Define a new HardwareSerial
  • Initialize it with begin(...)

Here’s an example:

include <HardwareSerial.h>

HardwareSerial MySerial(1); // define a Serial for UART1
const int MySerialRX = 16;
const int MySerialTX = 17;

void setup() 
{
	// initialize the Serial to the pins
    MySerial.begin(11500, SERIAL_8N1, MySerialRX, MySerialTX);
}

void loop() 
{
	// here we could use our MySerial normally
    while (MySerial.available() > 0) {
        uint8_t byteFromSerial = MySerial.read();
        // and whatever
    }
   
    MySerial.write(...);
}