ESP32S3 Dev Kit keeps crashing when trying to receive serial commands

I'm trying to use a code I got from the internet to control 2 motors by receiving commands through serial communication, the goal is to have the ESP32 connected with a Raspberry Pi 4 that's running ROS2 Foxy in Ubuntu 20.04. I modified the code a bit to work with the ESP32 since it was made for arduino boards (I'm also using ZS-X11H BLDC motor drivers since I'm using hoverboard motors). I'm getting this in the serial monitor:

mode:DIO, clock div:1
load:0x3fce3818,len:0x508
load:0x403c9700,len:0x4
load:0x403c9704,len:0xad0
load:0x403cc700,len:0x29e4
entry 0x403c9880
ESP-ROM:esp32s3-20210327

Been looking online for solutions, like adding yield() or using Serial0 instead of Serial, but no fix. It's 5 am and I'm in desperate need of a solution, I need to show this project in 2 weeks to pass my mobile robotics class, the pressure build-up is insane. Here's the main code, for the other files of the program, they're attached in a .zip file in this discussion (https://github.com/espressif/arduino-esp32/discussions/9993) since I don't want to have to show a humongous text.

/*********************************************************************
 *  ROSArduinoBridge
 
    A set of simple serial commands to control a differential drive
    robot and receive back sensor and odometry data. Default 
    configuration assumes use of an Arduino Mega + Pololu motor
    controller shield + Robogaia Mega Encoder shield.  Edit the
    readEncoder() and setMotorSpeed() wrapper functions if using 
    different motor controller or encoder method.

    Created for the Pi Robot Project: http://www.pirobot.org
    and the Home Brew Robotics Club (HBRC): http://hbrobotics.org
    
    Authors: Patrick Goebel, James Nugen

    Inspired and modeled after the ArbotiX driver by Michael Ferguson
    
    Software License Agreement (BSD License)

    Copyright (c) 2012, Patrick Goebel.
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above
       copyright notice, this list of conditions and/or other materials
       provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

#define USE_BASE      // Enable the base controller code
// #undef USE_BASE     // Disable the base controller code

/* Define the motor controller and encoder library you are using */
#ifdef USE_BASE
   /* The Pololu VNH5019 dual motor driver shield */
   //#define POLOLU_VNH5019

   /* The Pololu MC33926 dual motor driver shield */
   //#define POLOLU_MC33926

   /* The RoboGaia encoder shield */
   //#define ROBOGAIA
   
   /* Encoders directly attached to Arduino board */
   #define ARDUINO_ENC_COUNTER

   /* ZS-X11H Motor driver*/
   #define ZS_X11H_MOTOR_DRIVER
#endif

//#define USE_SERVOS  // Enable use of PWM servos as defined in servos.h
#undef USE_SERVOS     // Disable use of PWM servos

/* Serial port baud rate */
#define BAUDRATE     115200

/* Maximum PWM signal */
#define MAX_PWM        255

#include <Arduino.h>

/* Include definition of serial commands */
#include "commands.h"

/* Sensor functions */
#include "sensors.h"

/* Include servo support if required */
#ifdef USE_SERVOS
   #include <Servo.h>
   #include "servos.h"
#endif

#ifdef USE_BASE
  /* Motor driver function definitions */
  #include "motor_driver.h"

  /* Encoder driver function definitions */
  #include "encoder_driver.h"

  /* PID parameters and functions */
  #include "diff_controller.h"

  /* Run the PID loop at 30 times per second */
  #define PID_RATE           30     // Hz

  /* Convert the rate into an interval */
  const int PID_INTERVAL = 1000 / PID_RATE;
  
  /* Track the next time we make a PID calculation */
  unsigned long nextPID = PID_INTERVAL;

  /* Stop the robot if it hasn't received a movement command
   in this number of milliseconds */
  #define AUTO_STOP_INTERVAL 2000
  long lastMotorCommand = AUTO_STOP_INTERVAL;
#endif

/* Variable initialization */

// A pair of varibles to help parse serial commands (thanks Fergs)
int arg = 0;
int cmdIndex = 0;

// Variable to hold an input character
char chr;

// Variable to hold the current single-character command
char cmd;

// Character arrays to hold the first and second arguments
char argv1[16];
char argv2[16];

// The arguments converted to integers
long arg1;
long arg2;

/* Clear the current command parameters */
void resetCommand() {
  cmd = NULL;
  memset(argv1, 0, sizeof(argv1));
  memset(argv2, 0, sizeof(argv2));
  arg1 = 0;
  arg2 = 0;
  arg = 0;
  cmdIndex = 0;
}

/* Run a command.  Commands are defined in commands.h */
int runCommand() {
  int i = 0;
  char *p = argv1;
  char *str;
  int pid_args[4];
  arg1 = atoi(argv1);
  arg2 = atoi(argv2);
  
  switch(cmd) {
  case GET_BAUDRATE:
    Serial0.println(BAUDRATE);
    break;
  case ANALOG_READ:
    Serial0.println(analogRead(arg1));
    break;
  case DIGITAL_READ:
    Serial0.println(digitalRead(arg1));
    break;
  case ANALOG_WRITE:
    analogWrite(arg1, arg2);
    Serial0.println("OK"); 
    break;
  case DIGITAL_WRITE:
    if (arg2 == 0) digitalWrite(arg1, LOW);
    else if (arg2 == 1) digitalWrite(arg1, HIGH);
    Serial0.println("OK"); 
    break;
  case PIN_MODE:
    if (arg2 == 0) pinMode(arg1, INPUT);
    else if (arg2 == 1) pinMode(arg1, OUTPUT);
    Serial0.println("OK");
    break;
  case PING:
    Serial0.println(Ping(arg1));
    break;
#ifdef USE_SERVOS
  case SERVO_WRITE:
    servos[arg1].setTargetPosition(arg2);
    Serial0.println("OK");
    break;
  case SERVO_READ:
    Serial0.println(servos[arg1].getServo().read());
    break;
#endif
    
#ifdef USE_BASE
  case READ_ENCODERS:
    Serial0.print(readEncoderLeft());
    Serial0.print(" ");
    Serial0.println(readEncoderRight());
    break;
   case RESET_ENCODERS:
    resetEncoders();
    resetPID();
    Serial0.println("OK");
    break;
  case MOTOR_SPEEDS:
    /* Reset the auto stop timer */
    lastMotorCommand = millis();
    if (arg1 == 0 && arg2 == 0) {
      setMotorSpeeds(0, 0);
      resetPID();
      moving = 0;
    }
    else moving = 1;
    leftPID.TargetTicksPerFrame = arg1;
    rightPID.TargetTicksPerFrame = arg2;
    Serial0.println("OK"); 
    break;
  case MOTOR_RAW_PWM:
    /* Reset the auto stop timer */
    lastMotorCommand = millis();
    resetPID();
    moving = 0; // Sneaky way to temporarily disable the PID
    setMotorSpeeds(arg1, arg2);
    Serial0.println("OK"); 
    break;
  case UPDATE_PID:
    while ((str = strtok_r(p, ":", &p)) != nullptr) {
       pid_args[i] = atoi(str);
       i++;
    }
    Kp = pid_args[0];
    Kd = pid_args[1];
    Ki = pid_args[2];
    Ko = pid_args[3];
    Serial0.println("OK");
    break;
#endif
  default:
    Serial0.println("Invalid Command");
    break;
  }
  yield(); // Add yield to allow other tasks to run
}

/* Setup function--runs once at startup. */
void setup() {
  Serial0.begin(BAUDRATE);

// Initialize the motor controller if used */
#ifdef USE_BASE
  initMotorController();
  resetPID();
  initEncoders();  // Initialize encoders
#endif

/* Attach servos if used */
  #ifdef USE_SERVOS
    int i;
    for (i = 0; i < N_SERVOS; i++) {
      servos[i].initServo(
          servoPins[i],
          stepDelay[i],
          servoInitPosition[i]);
    }
  #endif
}

/* Enter the main loop.  Read and parse input from the serial port
   and run any valid commands. Run a PID calculation at the target
   interval and check for auto-stop conditions.
*/
void loop() {
  while (Serial0.available() > 0) {
    
    // Read the next character
    chr = Serial0.read();

    // Terminate a command with a CR
    if (chr == 13) {
      if (arg == 1) argv1[cmdIndex] = NULL;
      else if (arg == 2) argv2[cmdIndex] = NULL;
      runCommand();
      resetCommand();
    }
    // Use spaces to delimit parts of the command
    else if (chr == ' ') {
      // Step through the arguments
      if (arg == 0) arg = 1;
      else if (arg == 1)  {
        argv1[cmdIndex] = NULL;
        arg = 2;
        cmdIndex = 0;
      }
      continue;
    }
    else {
      if (arg == 0) {
        // The first arg is the single-letter command
        cmd = chr;
      }
      else if (arg == 1) {
        // Subsequent args are the command parameters
        argv1[cmdIndex] = chr;
        cmdIndex++;
      }
      else if (arg == 2) {
        argv2[cmdIndex] = chr;
        cmdIndex++;
      }
    }
    yield(); // Add yield to allow other tasks to run
  }

#ifdef USE_BASE
  /* Are we due for another PID calculation? */
  if (millis() > nextPID) {
    updatePID();
    nextPID += PID_INTERVAL;
  }
  
  /* Have we exceeded the auto-stop interval? */
  if ((millis() - lastMotorCommand) > AUTO_STOP_INTERVAL) {
    setMotorSpeeds(0, 0);
    resetPID();
    moving = 0;
  }
  yield(); // Add yield to allow other tasks to run
#endif
}

Can you clarify which ESP do you have and how the RPi and the ESP32 are connected ?

do you have an USB to UART adapter ?

have you connected the ESP32 to the RPi using a USB-TTL(3.3V) dongle or via the GPIO 14 (UART TX) and GPIO15 (UART RX)

it is a good idea to test the Serial communication using a simple program such as (tested on a ESP32-S3 DevkitC-1 )

// ESP32-S3 DevkitC-1  Serial1 test - for loopback test connect pin GPIO17 U1TXD to pin GPIO18 U1RXD"
// ss https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg

#define RXD1 18
#define TXD1 17

void setup() {
  // initialize both serial ports:
  Serial.begin(115200);
  Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
  Serial.println();
  Serial.println("\n\nESP32-S3 DevkitC-1 serial1  test pin GPIO17 U1TXD pin GPIO18 U1RXD");
  Serial.write("   for loopback test connect pin GPIO17 U1TXD to pin GPIO18 U1RXD\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);
    Serial1.write(inByte);
  }
}

using a terminal emulator the RPi should be able to exchange text with the ESP32
once you know the serial communications is working you can then attempt to sort out your project code

doesn;t look like there is more much more code (e.g. pid)

suggest to disable various features using #ifdefs and enable them one at a time to isolate a problem

Hi, sorry it took so long to reply. I did this and found the problem to be bad pin configurations in one of the other files (the motor driver ones). I wasn't paying much attention to the program's default pins since I first wanted to establish communication, but that came to bite me back when least expected. These are the related files:

motor_driver.h:

#ifdef ZS_X11H_MOTOR_DRIVER
#include <Arduino.h>

// Define motor pins
const int motorL_pwm = 4; //26
const int motorL_dir = 8; //25
const int motorR_pwm = 6; //33
const int motorR_dir = 9; //32

// Function to initialize motor controller
void initMotorController();

// Function to set motor speeds
void setMotorSpeeds(int leftSpeed, int rightSpeed);
#endif

The commented out numbers were the previous pins used. The actual configuration for then are in motor_driver.ino:

#ifdef ZS_X11H_MOTOR_DRIVER
  // Function to initialize motor controller
  void initMotorController() {
    pinMode(motorL_pwm, OUTPUT);
    pinMode(motorL_dir, OUTPUT);
    pinMode(motorR_pwm, OUTPUT);
    pinMode(motorR_dir, OUTPUT);
  }

  // Function to set motor speeds
  void setMotorSpeeds(int leftSpeed, int rightSpeed) {
    // Left motor control
    if (leftSpeed >= 0) {
      digitalWrite(motorL_dir, HIGH);
      analogWrite(motorL_pwm, leftSpeed);
    } else {
      digitalWrite(motorL_dir, LOW);
      analogWrite(motorL_pwm, -leftSpeed);
    }

    // Right motor control
    if (rightSpeed >= 0) {
      digitalWrite(motorR_dir, HIGH);
      analogWrite(motorR_pwm, rightSpeed);
    } else {
      digitalWrite(motorR_dir, LOW);
      analogWrite(motorR_pwm, -rightSpeed);
    }
  }

#else
  #error A motor driver must be selected!
#endif

So the problem is that the ESP32-S3-DevKitC-1 doesn't have the previously used pins. So changing the pins solved the whole repeatedly crashing and I can actually communicate through serial now. But of course incomes another problem, one that I have no idea what's going on. Whenever the ESP32 is turned on or resets. It prints the previously repeated crash message just once:

18:28:48.177 -> Build:Mar 27 2021

18:28:48.177 -> rst:0x1 (POWERON),boot:0x28 (SPI_FAST_FLASH_BOOT)

18:28:48.177 -> SPIWP:0xee

18:28:48.177 -> mode:DIO, clock div:1

18:28:48.177 -> load:0x3fce3818,len:0x508

18:28:48.177 -> load:0x403c9700,len:0x4

18:28:48.177 -> load:0x403c9704,len:0xad0

18:28:48.177 -> load:0x403cc700,len:0x29e4

18:28:48.177 -> entry 0x403c9880

And I don't know if it's relevant, but every time I upload code it prints gibberish in the serial monitor once:

����������������������������������������������������������������������������������������������������������������������������������������������������������������

I try uploading the simplest of code and still does it, I upload an empty code and the problem persists:

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

}

void loop() {
  // Serial.println("Nothing");
  // delay(1000);

}

Really confusing stuff

I'm using ESP32-S3-DevKitC-1, I've been testing directly connecting it to my pc or to the RPi with regular USB cables using the miniterm tool in the terminal. Like I said in another reply I solved the problem but a new one came out. And now whenever I try to use miniterm it does send the command to the ESP32 and gets the "OK" reply, but it immediately crashes and any kind of new input results in an endless stream of 0s. Here's an example of it:

o 127 -60
OK
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x42002921  PS      : 0x00060230  A0      : 0x820029bc  A1      : 0x3fcebca0  
A2      : 0x3fc96054  A3      : 0x3fcebce9  A4      : 0x00000004  A5      : 0x00000004  
A6      : 0x00000009  A7      : 0x00000004  A8      : 0x00000000  A9      : 0x3fcebc90  
A10     : 0x00000002  A11     : 0x3fcebceb  A12     : 0x00000002  A13     : 0x0000ff00  
A14     : 0x00ff0000  A15     : 0xff000000  SAR     : 0x00000020  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x0000000c  LBEG    : 0x400570e8  LEND    : 0x400570f3  LCOUNT  : 0x00000000  


Backtrace: 0x4200291e:0x3fcebca0 0x420029b9:0x3fcebcc0 0x420029f7:0x3fcebd10 0x42002a10:0x3fcebd30 0x42002290:0x3fcebd50 0x420023c0:0x3fcebd90 0x42004c84:0x3fcebdb0 0x4037e3fa:0x3fcebdd0




ELF file SHA256: 565f1278bd8b0f03

␂xx�x␀x�x�x�x��x�x�xx�x�xx␀�xESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x9 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403798de
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x508
load:0x403c9700,len:0x4
load:0x403c9704,len:0xad0
load:0x403cc700,len:0x29e4
entry 0x403c9880

What’s the baud rate on your terminal ? The ESP might be sending stuff through the Serial line upon booting and you just have the wrong baud rate to see it