Achieving Full-Duplex Serial Communication Between Two ESP32 Boards

 The ESP32 microcontroller, renowned for its robust features and wireless capabilities, enables seamless bidirectional communication through full-duplex communication. This article delves into implementing full-duplex communication between two ESP32 modules using the UART (Universal Asynchronous Receiver-Transmitter) interface. Which is also known as serial communication. We will explain the code for both the sender and receiver, exploring the intricacies of simultaneous data transmission and reception.

Component list

To establish a serial communication between esp32, we are going to need the following components:

  • ESP32 Modules: Two ESP32 microcontrollers for bidirectional communication.
  • USB Cable: For programming and power.
  • Jumper Wires: To connect TX and RX pins, and establish a common ground.
  • Power Source: Depending on your setup, you might need a power source for each ESP32.

Circuit Diagram from ESP32 to ESP32 UART Communication

Before we embark on the code explanation, it's essential to have a clear understanding of the hardware setup. Ensure you have two ESP32 modules available and connect them as follows:

  • Connect the TX pin of ESP32-A to the RX pin of ESP32-B.
  • Connect the TX pin of ESP32-B to the RX pin of ESP32-A.
  • Establish a common ground by connecting the GND pins of both ESP32 modules.
Achieving Full-Duplex Communication Between Two ESP32 Boards
Connection Diagram for ESP32 Serial Communication

Certainly! Let's delve into the code for both the sender and receiver ESP32 modules, providing a detailed explanation of each section.

Sender ESP32 Code

The following Arduino code is for the sender esp32 or esp32-A.

// Sender ESP32 Code
void setup() {
  Serial.begin(115200);       // Initialize serial communication for USB
  Serial2.begin(115200, SERIAL_8N1, 16, 17);  // Initialize Serial2 for external communication (TX: 16, RX: 17)
}
void loop() {
  if (Serial.available() > 0) {
    String message = Serial.readStringUntil('\n');  // Read message from USB serial
    Serial2.println("Sender says: " + message);   // Send message to Serial2
  }
  if (Serial2.available() > 0) {
    String message = Serial2.readStringUntil('\n'); // Read message from Serial2
    Serial.print("Received from Receiver: ");
    Serial.println(message);  // Print received message to USB serial
  }
}code-box

Explanation:

1. Serial Initialization:

   - Serial.begin(115200);: This line initializes the Serial object for USB communication with a baud rate of 115200.

2. Serial2 Initialization:

   - Serial2.begin(115200, SERIAL_8N1, 16, 17);: This line initializes Serial2 for external communication with a baud rate of 115200, 8 data bits, no parity, and 1 stop bit. The pins 16 and 17 are specified as the TX and RX pins, respectively.

3. Sender Input Handling:

   - if (Serial.available() > 0): This condition checks if there is any data available from the USB serial (connected to Serial). If true, it reads the message until a newline character is encountered using `Serial.readStringUntil('\n')`.

   - Serial2.println("Sender says: " + message);: This line sends the received message appended with "Sender says:" to Serial2, representing the outgoing message from the sender to the receiver.

4. Receiver Response Handling:

   - if (Serial2.available() > 0): This condition checks if there is any data available from Serial2 (external communication). If true, it reads the incoming message until a newline character is encountered.

   - Serial.print("Received from Receiver: "); Serial.println(message);: This line prints the received message from the receiver to the USB serial for monitoring and debugging.

Receiver ESP32 Code

The following Arduino code is for receiver esp32 or esp32-B.

//Receiver esp32 code
void setup() {
  Serial.begin(115200);       // Initialize serial communication for USB
  Serial2.begin(115200, SERIAL_8N1, 16, 17);  // Initialize Serial2 for external communication (TX: 16, RX: 17)
}
void loop() {
  if (Serial.available() > 0) {
    String message = Serial.readStringUntil('\n');  // Read message from USB serial
    Serial2.println("Receiver says: " + message); // Send message to Serial2
  }
  if (Serial2.available() > 0) {
    String message = Serial2.readStringUntil('\n'); // Read message from Serial2
    Serial.print("Received from Sender: ");
    Serial.println(message);  // Print received message to USB serial
  }
}code-box

Receiver esp32 code Explanation:

The receiver code follows a similar structure to the sender code.

1. Serial Initialization:

   - Serial.begin(115200);: Initializes the Serial object for USB communication with a baud rate of 115200.

2. Serial2 Initialization:

   - Serial2.begin(115200, SERIAL_8N1, 16, 17);: Initializes Serial2 for external communication with the same configuration as the sender.

3. Receiver Input Handling:

   - if (Serial.available() > 0): Checks if there is any data available from the USB serial. If true, it reads the message until a newline character is encountered.

   - Serial2.println("Receiver says: " + message);: Sends the received message appended with "Receiver says:" to Serial2, representing the outgoing message from the receiver to the sender.

4. Sender Response Handling:

   - if (Serial2.available() > 0): Checks if there is any data available from Serial2 (communication from the sender). If true, it reads the incoming message until a newline character is encountered.

   - Serial.print("Received from Sender: "); Serial.println(message);: Prints the received message from the sender to the USB serial for monitoring and debugging.

Testing Full-Duplex Communication Between ESP32

Upload Code:

   - Upload the sender code to ESP32-A and the receiver code to ESP32-B using the Arduino IDE.

Serial Monitor:

   - Open the Serial Monitor for both ESP32-A and ESP32-B to observe the bidirectional communication. Messages sent by the sender should be received by the receiver, and vice versa.

Key Points to Note

Simultaneous Communication:

   - The code in both the sender and receiver modules allows for simultaneous communication. The sender can send messages to the receiver, and vice versa, without interrupting the flow of communication.

UART Configuration:

   - The `Serial2.begin(115200, SERIAL_8N1, 16, 17);` line initializes the second hardware serial (`Serial2`) with a baud rate of 115200, 8 data bits, no parity, and 1 stop bit. Adjust these parameters based on your specific requirements.

Message Handling:

   - Messages are sent and received using the `Serial.println` and `Serial2.println` functions. The newline character (`'\n'`) delimits messages, enabling the receiver to read complete messages.

Adaptability:

   - The provided code is a foundation that can be adapted for various projects. Whether you're working on IoT applications, sensor networks, or remote control systems, understanding full-duplex communication is crucial.

 Conclusion

Implementing full-duplex communication between ESP32 modules enhances the capabilities of your projects by enabling simultaneous data transmission and reception. By leveraging the UART interface and understanding the intricacies of the code, you have the flexibility to adapt the communication protocol to suit the specific requirements of your applications. As you explore the vast possibilities of bidirectional communication, you'll be well-equipped to build sophisticated and interconnected systems using ESP32 microcontrollers.

4/Post a Comment/Comments

  1. Can you provide examples of practical applications for bidirectional communication between ESP32 devices?

    ReplyDelete
    Replies
    1. Certainly! Bidirectional communication between ESP32 devices opens up a wide range of practical applications across various domains. For instance, in smart homes, ESP32 devices can enable seamless communication between sensors and actuators, allowing for automated responses based on environmental changes. In industrial settings, bidirectional communication facilitates real-time monitoring and control of machinery, optimizing operational efficiency. Moreover, ESP32 modules are ideal for creating wireless sensor networks, enabling the transmission of environmental data for applications such as agriculture or weather monitoring. Other examples include remote control systems, collaborative IoT devices, health monitoring systems, vehicle tracking and communication, interactive multimedia installations, security systems, and mesh networking. The versatility of bidirectional communication makes ESP32 devices valuable for building intelligent and interconnected systems in diverse fields.

      Delete
  2. Can I apply this full-duplex communication technique to control devices remotely using ESP32?

    ReplyDelete
    Replies
    1. Absolutely! Full-duplex communication between ESP32 devices can be applied effectively to remotely control devices. By establishing bidirectional communication, you enable real-time interaction between the controlling device and the remotely managed devices.

      For instance, you can implement a remote control system where an ESP32 acting as a remote controller sends commands to another ESP32 connected to a device (e.g., a robot, a smart appliance, or an actuator). Simultaneously, the device can provide feedback or status updates back to the remote controller, creating a responsive and interactive control system.

      Key considerations include defining a communication protocol for the commands and responses, ensuring the security of the communication, and addressing latency issues if real-time control is critical. Additionally, power consumption and the choice of communication frequency should be optimized for efficient and reliable remote control applications. With proper implementation, full-duplex communication with ESP32 can indeed enhance the capability to control devices remotely.

      Delete

Post a Comment