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 asynchronous transmission and reception of data 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 micros, the computer, sensors, GPS modules, some types of displays, among others.

The UART in the ESP32

The ESP32 has more than one UART, depending on the model we 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 of the ESP32 compared to 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. Therefore, if we want to use the UART, we will necessarily have to reassign the pins.

These are the default assignments for the ESP32-S3

UART PortTXRXRTSCTS
UART049501516
UART117181920
UART2----

In this case, UART2 is not associated with any pin by default. Therefore, if we want to use it, we will again have to reassign it to some pin of our choice.

How to use UART on the ESP32 in the Arduino environment

Using UART on the ESP32 in the Arduino environment is not too complicated (if we are clear about what we are doing).

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

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

If you have questions, check the tutorial links I provided earlier.

Using multiple UARTs on the ESP32

The only “mess” you will have is with the pins of UART1 and UART2. In an effort to make it simpler, just like it is done on 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 will work without problems. It is used for programming and communication via the board’s USB (so, changing the pins is neither necessary nor a good idea).

Things change with Serial1 and Serial2. Depending on your ESP32 model and board, it is normal that the Serial1 and Serial2 syntax may not work for you.

The best thing you can do if you want to use more than one UART is to manually define the pins. 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 simple 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 you have 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 else
    }
   
    MySerial.write(...);
}