Two-way UART communication between ESP32 С3 and Arduino Mega on the same TX/RX

Hello!

I'm trying to set up two-way communication between ESP32 and Arduino Mega via UART using only one UART port on both devices, as the other ports on Mega are busy. I connected TX ESP32 to RX Arduino Mega (pin 0) and RX ESP32 to TX Arduino Mega (pin 1)

But, unfortunately, Arduino Mega does not receive data from ESP32, or ESP32 does not see a response from Mega. I checked the connections and UART speed, and everything seems to be configured correctly.

Code Esp32 C3:

void setup() {
  Serial.begin(9600); 
}

void loop() {
  Serial.print("A"); 
  delay(500); 

  if (Serial.available()) {
    String received = Serial.readString(); 
    Serial.print("Answer from Arduino:");
    Serial.println(received);
  }

}

Code Arduino Mega:

void setup() {
  Serial.begin(9600); 
}

void loop() {

    Serial.print("B"); 
    delay(500); 
  if (Serial.available()) {
    String received = Serial.readString(); 
    Serial.print("Received from ESP32:");
    Serial.println(received);

  }
}

Serial Esp 32 sends the "A" character, Serial Arduino Mega sends the "B" character, both do not accept characters from each other

Bidirectional logic level shifters are generally required when connecting 3.3V and 5V MCU I/O pins. Damage to one or both can occur if you connect them directly.

3 Likes

First of all you are creating an infinite transmission loop between them if you had connected them to the proper pins, which i doubt. Secondly you should protect your ESP32-c3 RX pin against the 5v logic level of the Mega. This is very important. ESP32's are not 5v tolerant, and you should not try to prove otherwise.
The Mega has the USB to TTL converter connected to UART0 and that confuses the issue a little.
Also on the ESP32-c3, UART0 is connected to USB and UART1 is connected to GPIO pins. Which ones by default may depend a bit on the actual board (usually 20 & 21 i think) but these pins can be freely assigned by the user.
Check this
I suggest you just send a character from the ESP to the Mega and let the Mega reply to that, and send that to ESP32-c3 USB.
And use at least a voltage divider to reduce the 5v TX logic level from the Mega to the 3.3v ESP logic level on the ESP RX line !

2 Likes

ESP32 is powered by Arduino Mega (3.3 V and GND), and I made a separate power supply for Arduino Mega, so RX and TX Arduino will not interfere with USB.

I now have only a 1K ohm resistor and I connected it like this: * TX (Pin 1) Arduino Mega is connected to one side of the resistor (1 kHm).

  • The other end of the resistor is connected to GND ESP32. This will create a voltage divider.

  • RX pin ESP32 (GPIO 3) will be connected to the point where the resistor connects to the TX pin of the Arduino Mega.

I made such a code only to accept symbols

Code Esp32:

void setup() {
  Serial.begin(9600); 
}

void loop() {
  Serial.println("Hello from ESP32!"); 
  delay(1000); 
}

Code Arduino Mega:

void setup() {
  Serial.begin(9600); 
}

void loop() {
  if (Serial.available()) {
    String received = Serial.readString();
    Serial.println(received);
  }
}

No it won't, it creates a problem.

1 Like

I only have 1 kOhm resistors, and I connected two resistors in series to get 2 kOhm. I repeated your scheme, but so far Arduino does not see the symbols coming from ESP32.

It is quite OK to string two 1K resistors together, but maybe too late. I understand ESP32 are strictly 3.3v.

That's fine, just not what you said earlier

So you have 3x 1K resistors, that's all good.

Now about the code, did you see the link i posted

Clearly not.

void setup() {
   Serial.begin(9600);
   delay(100);
   Serial.println("ESP32 Test The UART");   // verify that something is coming out of the ESP to the monitor for starters
   Serial1.begin(9600,SERIAL_8N1, 4,5); //int8_t rxPin=4, int8_t txPin=5 
}

void loop() {
  Serial1.println("Hello from ESP32!"); 
  delay(1000); 
  if (Serial1.available()) {
    String received = Serial1.readString();
    Serial.println(received);
  }
}

Try that on the esp using pin 4 as RX & pin 5 as TX

1 Like

Unfortunately, I can't change tx rx, because I use a ready-made microcontroller esp32 c3 built-in display, but I have a scheme of this world controller:

I'll do RX-30 like this, Tx - 31?

It turns out that RX is GPIO20. TX-GPIO21

I changed the pin, now esp32 can accept symbols, but arduino still can't accept symbols
Esp32 code:

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("ESP32 Test The UART");
  Serial1.begin(115200, SERIAL_8N1, 20, 21);
}

void loop() {
  if (Serial1.available()) {
    String received = Serial1.readString();
    Serial.println(received);

    received.trim();

    if (received == "Hello") {
      Serial.println("A");
    }
  }
}

Arduino Code:

void setup() {
  Serial.begin(115200); 
}

void loop() {
  Serial.println("Hello");// "Hello world."
  delay(5000);
}

With the Mega you should be using the Serial1 or Serial2 or Serial3 pins to connect to the ESP32.
https://www.arduino.cc/reference/tr/language/functions/communication/serial/

1 Like

connecting ESP32 to Mega (using Serial1 pins 18 TX1 and 19 RX1)

note the potential divider on Mega pin 18 TX1 (5V logic) to the ESP32 Rx (3.3V logic)

the above is for an ESP32 but similar circuit would work with a ESP32C3
with ESP32C3 I tend to use Serial1 on pins 2 and 3, e.g.

// ESP32-C3-MINI-1 Serial1 test - for loopback test connect pins 2 and 3

// note GPIO20 U0RXD and GPIO21 U0TXD are used for Serial programming/debugging

#define RXD1 3
#define TXD1 2

void setup() {
  // initialize both serial ports:
  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, RXD1, TXD1);
  Serial.println();
  Serial.println("\n\nESP32-C3 serial1  test Rx pin 3 Tx pin 2");
  Serial.write("   for loopback test connect pin 3 to pin 2\n");
}

void loop() {
  // read from port 1, send to port 0:
  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.write(inByte);
  }

  // read from port 0, send to port 1:
  if (Serial.available()) {
    int inByte = Serial.read();
    //Serial.write(inByte);   //echo keyboard
    Serial1.write(inByte);
  }
}

2 Likes

Those are defaiult pins for UART0, but you can define the pins as you like. UART0 is always connected to USB as well. (on an ESP32-C3 that is. it has native USB, on most other boards the pins decide what is connected to USB)
If your hardware is connected to those pins you should use those i suppose.

try
Arduino Code:

void setup() {
  Serial.begin(115200); 
}

void loop() {
  if (Serial.available()) {
    char c = Serial.read();
    if (c == 'A') {
      Serial.println("Received 'A' from ESP");
    }
  }
  else {   // like this you ensure that anything incoming is dealt with
     Serial.print("Hello");   // use just 'print' or the NL character is also send and then you should test upon reception
    delay(5000);
  }
}

Esp32 code:

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("ESP32 Test The UART");
  Serial1.begin(115200, SERIAL_8N1, 20, 21);
}

void loop() {
  if (Serial1.available()) {
    String received = Serial1.readString();
    Serial.println(received);

    received.trim();

    //if (received == "Hello") {  // omit the test just in case it doesn't match, respond every time a message is received.
      Serial.println("A");
    //}
  }
}

As long as you are not trying to use USB at the same time, Serial is fine to use as well.

1 Like

As all the hardware UART Ports (UART0 - UART3) of MEGA have been utilized, you can comfortably create a software UART Port (SUART) on MEGA and connect it with the UART1 Port of ESP32 C3 for data excage. Leave the UART0 of both MEGA and ESP32 C3 connected with the PC/SM.

1. Make the following hardware setup (Fig-1):



Figure-1:

2. Upload the following sketch into ESP32 C3:

char myData[10];

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600, SERIAL_8N1, 20, 21); //RX1 = 20, TX1 = 21
  delay(1000);
}

void loop()
{
  byte n = Serial.available();
  if (n != 0)
  {
    byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0'; //insert null character
    Serial.println(myData);
    //-----------------------
    Serial1.println(myData);
  }
  n = Serial1.available();
  if (n != 0)
  {
    byte m = Serial1.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0'; //insert null character
    Serial.println(myData);
    //-----------------------
  }
}

3. Upload the following sketch into MEGA.

#include<SoftwareSerial.h>
SoftwareSerial SUART(10, 11);  //SRX = 10, STX = 11
char myData[10];

void setup()
{
  Serial.begin(9600);
  SUART.begin(9600);
}

void loop()
{
  byte n = Serial.available();
  if (n != 0)
  {
    byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0'; //insert null character
    Serial.println(myData);
    //-----------------------
    SUART.println(myData);
  }
  n = SUART.available();
  if (n != 0)
  {
    byte m = SUART.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0'; //insert null character
    Serial.println(myData);
    //-----------------------
  }
}

4. Open Serial Monitor of ESP32 C3 at Bd = 9600 and Newline option.

5. Open Serial Monitor of MEGA at Bd = 9600 and Newline option.

6. Press Reset Buttons of oth Arduinos.

7. Enter ESP32 C3 from the InputBox of the Serial Monitor of ESP32 C3. Check that the message as appered on the OutputBox of the Serial Monitor of MEGA.

8. Enter MEGA from the InputBox of te Serial Monitor of MEGA. Check that the message has appered on the OutputBox of the Serial Monitor of ESP32 C3.

9. OUTPUT:

ESP32 C3
MEGA


1 Like

Do we not read the above as: "A" string?

1 Like

Thank you all very much, I got a lot of knowledge here and it turned out like this:

Esp32 code:

void setup() {
  Serial.begin(115200);         
  delay(100);
  Serial.println("ESP32 Test The UART");
  Serial1.begin(115200, SERIAL_8N1, 20, 21); 
}

void loop() {
  if (Serial1.available()) {
    String received = Serial1.readString(); 
    Serial.println(received);                

    received.trim();                

    if (received == "Hello") {        
      Serial1.println("How");                
    }
  }
}

Arduino code:

void setup() {
  Serial.begin(115200);        
  Serial1.begin(115200);       
}

void loop() {
  Serial1.println("Hello");      
  delay(5000);                 
 
  if (Serial1.available()) {
    String received = Serial1.readString(); 
    Serial.println(received); 
    received.trim();                         

    if (received == "How") {                
      Serial.println("ok");                
    }
  }
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.