ESP32 and UNO - sending request via serial and responding

Hi, I would like to send request from ESP32 to UNO using serial line, on what would the UNO respond with answer also via serial line. Is it even possible? If not, are there any alternatives (3 wires only), that could do it?

It is perfectly possible, but be aware that the Uno is a 5V device and the ESP32 is a 3.3V device and you will need to take that into account when connecting the two of them

Why do you need them to communicate ?

I need to share data from first floor(uno), to second (esp32). The esp32 than send it to firebase database.

I have already written a working code, but I want to improve it. In my current version, the uno sends data every 10 seconds. I don't want it to be based on time, but on request from esp32.

#include <Arduino.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
#include <BME280I2C.h>
#include <Wire.h>

#define RX 16
#define TX 17

#define WIFI_SSID " "
#define WIFI_PASSWORD " "

#define API_KEY " "

#define DATABASE_URL " "

const byte numChars = 4;
char readBuf[numChars];
static byte ndx = 0;

unsigned long sendDataPrevMillis = 0;
unsigned long sendGraphDataPrevMillis = 0;

bool signupOK = false;


int tempf = 0;
int humif = 0;

int val = 0;

BME280I2C bme;
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial1.begin(9600, SERIAL_8N1, RX, TX);
  Wire.begin();
  bme.begin();
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  config.api_key = API_KEY;
  config.database_url = DATABASE_URL;

  if (Firebase.signUp(&config, &auth, "", "")) {
    Serial.println("ok");
    signupOK = true;
  }
  else {
    Serial.printf("%s\n", config.signer.signupError.message.c_str());
  }

  config.token_status_callback = tokenStatusCallback;

  Firebase.begin(&config, &auth);
  Firebase.reconnectWiFi(true);
}
void loop() {
  if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)) {
    sendDataPrevMillis = millis();
    sendGraphDataPrevMillis = millis();

    if (Serial1.available() > 0) {
      Serial.println("Processing Arduino values");
      while (val != 2) {
        char c = Serial1.read();
        if (c != '\n') {
          readBuf[ndx] = c;
          ndx++;
        }
        else {
          val += 1;
          switch (val) {
            case 1: {
                tempf = atoi(readBuf);
                readBuf[ndx] = '\0';
                ndx = 0;
                break;
              }
            case 2: {
                humif = atoi(readBuf);
                Serial.println(humif);
                Serial.println(tempf);
                readBuf[ndx] = '\0';
                ndx = 0;
                break;
              }
          }
        }
      }
      val = 0;
    }

    float temp(NAN), hum(NAN), pres(NAN);
    BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
    BME280::PresUnit presUnit(BME280::PresUnit_Pa);
    bme.read(pres, temp, hum, tempUnit, presUnit);
    pres = pres / 100;

    Firebase.RTDB.setFloat(&fbdo, "bme/teplota", temp);
    Firebase.RTDB.setFloat(&fbdo, "bme/tlak", pres);
    Firebase.RTDB.setInt(&fbdo, "dht/teplota", tempf);
    Firebase.RTDB.setInt(&fbdo, "dht/vlhkost", humif);


    if (millis() - sendGraphDataPrevMillis > 3600000000 || sendGraphDataPrevMillis == 0) {
      Firebase.RTDB.pushFloat(&fbdo, "graf/teplotag", temp);
      Firebase.RTDB.pushFloat(&fbdo, "graf/tlakg", pres);
      Firebase.RTDB.pushInt(&fbdo, "graf/teplotaf", tempf);
      Firebase.RTDB.pushInt(&fbdo, "graf/vlhkostf", humif);
      sendGraphDataPrevMillis == 0;
    }
  }
}

What will trigger the ESP32 to send a signal to the Uno so that the Uno will reply back?

When it comes time for the ESP32 to send a data request the ESP32 could send a serial message something like "<#RTS>" to the Uno. Which the Uno could receive on its serial line and then send to the ESP32 the requested information.

What will trigger the ESP32 to send a signal to the Uno so that the Uno will reply back?

every time void loop() runs again, esp32 will send request

I can't figure out how the communication between esp32 and uno works, when both have to send and read from serial line, because my code doesn't work.

//UNO
char Mymessage[5] = "Hello";
 
  void setup() {
    Serial.begin(9600);
  }
  void loop() {
    Serial.write(Mymessage,5);
    delay(1000);
  }
//ESP32
#define RXp2 16
#define TXp2 17
char Mymessage[5];   

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXp2, TXp2);
}
  void loop() {
    Serial2.readBytes(Mymessage,5);
    Serial.println(Mymessage);
    delay(1000);
  }

But the loop() function should run thousands of times a second. What will make it run slower ?

I meant here, once in 15 seconds.

if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 15000 ..){
//...
//my code
}

So not actually

Why only output I got in esp32 serial monitor is blank newline?

//UNO
void setup() {
  Serial.begin(9600);
}
void loop() {
  if (Serial.available() > 0 && Serial.read() == "SEND DATA") {
    Serial.write("HELLO");
  }
}
//ESP32
#define RXp2 16
#define TXp2 17
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXp2, TXp2);
}
void loop() {
  Serial2.write("SEND DATA"); 
  delay(500);
  if (Serial2.available() > 0) {
    Serial.println("Message Received: ");
    Serial.println(Serial2.readString());
  }
}

Apart from anything else you are reading from Serial without checking whether anything is available

Have you got the Rx to Tx connections the right way round and have you taken the difference in voltages into consideration ?

Well, as I said earlier, I have already written a working code and the there was no problem in voltages and I am sure the wiring is fine too.

Does that include connecting the grounds of both boards together?

yes

I finally managed to establish communication between ESP32 and UNO.

//ESP32
#define RXp2 16
#define TXp2 17
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600, SERIAL_8N1, RXp2, TXp2);
}
void loop() {
  Serial.write(124);
  delay(1000);
  if (Serial.available() > 0) {
    Serial.println(Serial.read());
  }
}
//UNO
void setup() {
  Serial.begin(9600, SERIAL_8N1);
}
void loop() {
  if (Serial.available() > 0 && (char)Serial.read() == 124) {
    Serial.write(73); 
  }
}

There's another problem. I'm trying to add request commands, but for some reason the output in serial monitor is corrupted. The idea is, that I compare the readBuf character array (containing the current serial line command) with the options in the msgStr character array(each option/command has a pointer and after match option is found, pointer value is stored in enum value so, I can use a switch case with enumerated values later). Any advice?

Code:

//UNO
const byte numChars = 9;
char readBuf[numChars];
static byte ndx = 0;
static byte arnum = 0;
enum Message {
  SEND_BAK = 0,
  SEND_TEM = 1,
  SEND_HUM = 2,
  SEND_PRE = 3
} msg;
const char* msgStr[9] = {"", "SEND_TEM\n", "SEND_HUM\n", "SEND_PRE\n"};
void setup() {
  Serial.begin(9600, SERIAL_8N1);
}
void loop() {
  while (Serial.available() > 0) {
    char rc = Serial.read();
    if (rc != '\n') {
      readBuf[ndx] = rc;
      ndx++;
    }
  }
  Serial.println(String(readBuf));
  while (strcmp(msgStr[arnum], readBuf[numChars]) != 0) {
    arnum++;
  }
  msg = int(arnum);
  switch (msg) {
    case SEND_BAK:
      break;
    case SEND_TEM:
      Serial.println(26.26);
      break;
    case SEND_HUM:
      Serial.println(82.82);
      break;
    case SEND_PRE:
      Serial.println(990.990);
      break;
    default:
      Serial.println("NOT A VALID COMMAND");
      break;
  }
  readBuf[ndx] = '\0';
  ndx = 0;
  arnum = 0;
}
//ESP32
#define RXp2 16
#define TXp2 17
long sendRequestMillis = 0;
float humi;
static byte ndx = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600, SERIAL_8N1, RXp2, TXp2);
}
void loop() {
  Serial.println("SEND_HUM");
  delay(10000);
  while (Serial.available() > 0) {
    char rc = Serial.read();
  }
}

In serial monitor output is lot of '\n' and once in 10 seconds, when ESP32 sends request, the corrupted data is displayed.

are you attempting something along the lines of

// ESP32

#define RXp2 16
#define TXp2 17
long sendRequestMillis = 0;
float humi;
static byte ndx = 0;
void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
  Serial1.begin(9600, SERIAL_8N1, RXp2, TXp2);
}
void loop() {
  Serial1.println("SEND_HUM");
  delay(10000);
  while (Serial1.available() > 0) {
    char rc = Serial1.read();
    Serial.print(rc);
  }
}
//UNO
#include <AltSoftSerial.h>

//SIM800L TXD to UNO RX pin 8
//SIM800L RXD to UNO TX pin 9

AltSoftSerial mySerial;

const byte numChars = 9;
char readBuf[numChars];
static byte ndx = 0;
static byte arnum = 0;
enum Message {
  SEND_BAK = 0,
  SEND_TEM = 1,
  SEND_HUM = 2,
  SEND_PRE = 3
} msg;
const char* msgStr[9] = { "", "SEND_TEM", "SEND_HUM", "SEND_PRE" };
void setup() {
  Serial.begin(115200);
  mySerial.begin(9600);
}
void loop() {
  if (mySerial.available() == 0) return;
  if (mySerial.readBytesUntil('\n', readBuf, 8) >= 8) {
    Serial.print("received ");
    Serial.println(readBuf);
    while (strcmp(msgStr[arnum], readBuf) != 0) {
      arnum++;
    }
    msg = int(arnum);
    switch (msg) {
      case SEND_BAK:
        break;
      case SEND_TEM:
        Serial.println(26.26);
        break;
      case SEND_HUM:
        Serial.println(82.82);
        break;
      case SEND_PRE:
        Serial.println(990.990);
        break;
      default:
        Serial.println("NOT A VALID COMMAND");
        break;
    }
  }
  readBuf[0] = 0;
  ndx = 0;
  arnum = 0;
  while (mySerial.available()) mySerial.read();  // flush input buffer
}

connected ESP32 GPIO17 to UNO pin 8
UNO serial monitor displays every 10 seconds

received SEND_HUM
82.82
received SEND_HUM
82.82
received SEND_HUM
82.82
received SEND_HUM
82.82
received SEND_HUM
82.82
1 Like

Thanks, that works pretty well.

this version more like orignal coping characters into array until \n found

//UNO
#include <AltSoftSerial.h>

//SIM800L TXD to UNO RX pin 8
//SIM800L RXD to UNO TX pin 9

AltSoftSerial mySerial;

const byte numChars = 9;
char readBuf[50];
static byte ndx = 0;
static byte arnum = 0;
enum Message {
  SEND_BAK = 0,
  SEND_TEM = 1,
  SEND_HUM = 2,
  SEND_PRE = 3
} msg;
const char* msgStr[9] = { "", "SEND_TEM", "SEND_HUM", "SEND_PRE" };
void setup() {
  Serial.begin(115200);
  mySerial.begin(9600);
}
void loop() {
  // loop reading characters into array
  while (mySerial.available() > 0) {
    char rc = mySerial.read();
    if (rc != '\n') {       // if \n process command
      if(rc < ' ')return;   // if other control character return
      readBuf[ndx] = rc;    // add to array
      readBuf[++ndx] = 0;   // add null termunator
      //Serial.print(rc);
    } else {
      Serial.println(readBuf);
      while (strcmp(msgStr[arnum], readBuf) != 0) {
        arnum++;
      }
      msg = int(arnum);
      switch (msg) {
        case SEND_BAK:
          break;
        case SEND_TEM:
          Serial.println(26.26);
          break;
        case SEND_HUM:
          Serial.println(82.82);
          break;
        case SEND_PRE:
          Serial.println(990.990);
          break;
        default:
          Serial.println("NOT A VALID COMMAND");
          break;
      }
    readBuf[0] = 0;
    ndx = 0;
    arnum = 0;
    }
  }  
}

displays

SEND_HUM
82.82
SEND_HUM
82.82
SEND_HUM
82.82

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