How to communicate between ESP32 CAM and arduino mega 2560

Hello,
I am doing a project to control the Arduino robot from Matlab through esp32 cam. But now I am having a problem in communication from ESP32 cam to Arduino mega.
This code of ESP32 cam is used to connect to wifi, receive a signal from Matlab, and output signal to serial (On ESP32 cam, the communication port is pin 3 (RX) and pin 1 (TX))

#include <WiFi.h>
#define SERVER_PORT 80
const char* ssid = "****";
const char* sspass = "****";
WiFiServer Myserver(SERVER_PORT);

String Data = "";
bool DataComplete = false;

#include <SoftwareSerial.h>
const byte RX_Pin = 3;
const byte TX_Pin = 1;
SoftwareSerial mySerial(RX_Pin,TX_Pin);
 

void setup() {
  pinMode(4, OUTPUT);
  Serial.begin(115200);
  mySerial.begin(115200);
  

  WiFi.begin(ssid, sspass);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP());
  Myserver.begin();
}

void loop() { //Doc tu matlab va dua den arduino
  WiFiClient client = Myserver.available();
  if (client.connected()) 
  {
    for (int i=0;i<3;i++)
     {
      digitalWrite(4,LOW);
      delay(50);
      digitalWrite(4, HIGH);
      delay(50);
    }
    while(1)
    {
      while(client.available())
      {
        char data = client.read();
        if(Serial.available()>0){
          mySerial.write(data);
        }
      }
      if(Myserver.hasClient())
      {
        return;
      }
    }
  }
}

This code of Arduino Mega 2560 is used to receive signals from the ESP32 cam and control the motors (There is a rather long paragraph below but it is not important).

String ESPString = "";
bool ESPComplete = false;

void setup(){
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);

  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop(){
  if(Serial.available()>0){
    char ESPSend = (char)Serial.read();
    Serial1.write(ESPSend);
    ESPString += ESPSend;
    if(ESPSend == '\n'){
    ESPComplete = true; 
    }
    if(ESPComplete){
      ControlByHand();
      ESPString = "";
      ESPComplete = false;
    }
  }
}

void ControlByHand(){
  if(ESPString.indexOf("w") >= 0){
    GoAway();
  }
  if(ESPString.indexOf("s") >= 0){
    GoBack();
  }
  if(ESPString.indexOf("a") >= 0){
    TurnLeft();
  }
  if(ESPString.indexOf("d") >= 0){
    TurnRight();
  }
  if(ESPString.indexOf("e") >= 0){
    Stop();
  }
}

I tried connecting, and it connected to wifi, received a signal from Matlab, and wrote out serial, but Arduino seems to have not received a signal from esp32 cam to control the motors.
Hope everyone can help me.
PS: For some reason, I have to use ESP32 CAM instead of ESP32 or ESP8266

Can you explain this ?


while(client.available())
      {
        char data = client.read();
        if(Serial.available()>0){
          mySerial.write(data);
        }
      }

Why do you check Serial (and never read it) to send something you got over wifi?

Awww dude! ESP32 CAM is a 3.3V device and is 5V intolerant. A Mega is a 5V device. Did you use logic level shifters?

And dude software serial on an ESP32, it just does not work very well when, the ESP32 has 3 different Serial Ports (UART). You can just use one of them. Also, software serial does not work very well at 115200.

Serial0: RX0 on GPIO3, TX0 on GPIO1
Serial1: RX1 on GPIO9, TX1 on GPIO10 (+CTS1 and RTS1)
Serial2: RX2 on GPIO16, TX2 on GPIO17 (+CTS2 and RTS2)

1 Like
void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == ‘>’)
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
              //
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == ‘<’ )
          {
            sSerial = “”; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );
  }
  vTaskDelete( NULL );
} //void fReceiveSerial_LIDAR( void * parameters  )

I found for the STMBluepill, Due, and ESP32 if ( LIDARSerial.available() >= 1 ) is a lot more realiable then if(Serial.available()>0).

Why use while(1) when loop() is a loop and runs continuously?

In main()

while(1){
loop();
}

If you only want that code to run once put it in setup and take the while(1) out of setup().

yes in general.

My understanding of the code:

Here OP wants the 3 blinks in case a client connects - so part of the loop.

The while(1) is meant to handle the case where you've exhausted the client.available() data because you read the buffer faster than the data was incoming, yet you don't want to go blink again. Once the client is done and has closed the connection, the Myserver.hasClient() test will allow to return to the main loop and wait for a new client.

The while could be while(Myserver.hasClient()) though and I would had a yield() somewhere in there just to pat the dog.

Yea, I'm familiar with the use of while see below:

void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == ‘>’)
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
              //
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == ‘<’ )
          {
            sSerial = “”; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );
  }
  vTaskDelete( NULL );
} //void fReceiveSerial_LIDAR( void * parameters  )

My question is that the while loop will not exit the way it is wrote. loop() is already in a while loop, so why nest a while in a while when it's not necessary and causes the rest of the code in loop() to not ever run again.

hum, the test

if(Myserver.hasClient())
      {
        return;
      }

will break the while(1)

not sure what you mean. and if you don't loop, you'll get the blinking again because the client is still connected.

the code of the loop in plain English is:

LOOP
  if there is an incoming client 
    blink 3 times
    as long as the client is connected, send the incoming data to the Serial line

the while(1) is there to represent this as long as the client is connected
The LOOP is there to handle the next client.
sure you could use the loop to feed the serial line, but you would need an extra test to not blink again

Oh thanks everyone who answered my question.
I have solved this problem.
Here is my code after editing .
The first is the ESP code

#include <WiFi.h>
#define SERVER_PORT 80
const char* ssid = "";
const char* sspass = "";
WiFiServer Myserver(SERVER_PORT);

String DataReceive = "";
bool ReceiveComplete = false;


long Delay = 0;
int k ;
int Request;
int Percent;

#include <SoftwareSerial.h>

SoftwareSerial mySerial(3,1);
 

void setup() {
  pinMode(4, OUTPUT);
  Serial.begin(115200);
  while(!Serial);
  mySerial.begin(115200);
  while(!mySerial);
  

  WiFi.begin(ssid, sspass);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP());
  Myserver.begin();
  Delay = millis();
}

void loop() {
  From_Matlab();
  if(millis() - Delay >= 1000){
    From_Mega();
    Delay = millis();
  }
}

void From_Mega(){
  while (mySerial.available()){
    char FromMega = (char)mySerial.read();
    DataReceive += FromMega;
    if (FromMega == '\n'){
      ReceiveComplete = true;
    }
    if(ReceiveComplete){
      k = DataReceive.toInt();
      Request = DataReceive.toInt();
      Percent = DataReceive.toInt();
      DataReceive = "";
      ReceiveComplete = false;
    }
  }
}
void From_Matlab(){
  WiFiClient client = Myserver.available();
  if (client.connected()) 
  {
    for (int i=0;i<3;i++)
     {
      digitalWrite(4,LOW);
      delay(50);
      digitalWrite(4, HIGH);
      delay(50);
    }
    while(client.available())
      {
        char data = (char)client.read();
        mySerial.print(data);
        Serial.println(data);
      }
    }
      if (client.connected()){
          client.write(k);
          client.write(Request);
          client.write(Percent);
   }
}

MEGA's code is still the same.
I have been able to control the arduino from matlab through esp32 CAM

Hi,
I've given the ESP32 CAM a 5V power supply and it's been working fine, no signs of heating up or anything unfortunate happening.

Oh, so your not going to use logic level shifters. Good luck with that.

On an ESP software serial does not work reliably.

The ESP32 has 4 hardware serial ports. Hardware serial is faster.

And I say poo! that your ESP32 code is working. SoftwareSerial mySerial(3,1); on an ESP32 GPIO_NUM_1 and GPIO_NUM3 are the serial programming port pins. Using the programing port pins of the ESP32 as serial pins will create issues. Of course the simulator does not know about the programming port and that the ESP32 does not work well with softwareserial.

Yet.

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