Skip to menu

Robotics with Object Pascal

ESP32-S3 super mini experience

Extra Hardware Serial + JSON servo control

2025.09.22 23:05

me Views:139

It gets message from Orange Pi 5 via UART in JSON format.

 

Then, it control 3 servos.

 

The connection setting is as this : 

Opi5_ESP32_Comm.png

 

 

========  ESP32-S3 Code ==========

#include <ESP32Servo.h>

#include <ArduinoJson.h>

#include <HardwareSerial.h>

 

// Define the UART pins for the Orange Pi 5 (Communication Bus)

#define COMM_RX_PIN 11

#define COMM_TX_PIN 10

 

// Define the UART pins for the LiDAR (Data Bus)

#define LIDAR_RX_PIN 13

#define LIDAR_TX_PIN 12

 

// Servo pin definitions

const int servoPinRW = 5;

const int servoPinLW = 6;

const int servoPinLidar = 7;

 

// Servo objects

Servo servoRW;

Servo servoLW;

Servo servoLidar;

 

// Custom neutral points

const int leftServoNeutralPoint = 1480;

const int rightServoNeutralPoint = 1500;

 

// HardwareSerial instances

HardwareSerial myCommSerial(1); // For Orange Pi 5

HardwareSerial myLidarSerial(2); // For LiDAR

 

// Define the safe movement range for the LiDAR servo

const int LidarMinAngle = 20;  // Tilts to the floor (front)

const int LidarMaxAngle = 110; // Tilts backward.  (Do not go over this)

 

void setServoSpeeds(int leftSpeed, int rightSpeed, int lidarAngle) {

  // --- WHEEL SERVO LOGIC ---

  int leftPWM = map(leftSpeed, -100, 100, 1200, 1760); 

  int rightPWM = map(rightSpeed, -100, 100, 1240, 1760); 

 

  servoLW.writeMicroseconds(leftPWM);

  servoRW.writeMicroseconds(rightPWM);

 

  // --- LIDAR SERVO SAFEGUARD ---

  int safeLidarAngle = constrain(lidarAngle, LidarMinAngle, LidarMaxAngle);

  int lidarPWM = map(safeLidarAngle, 0, 180, 2500, 500); 

 

  servoLidar.writeMicroseconds(lidarPWM);

 

  // Print the values for debugging

  Serial.print("Left Speed: ");

  Serial.print(leftSpeed);

  Serial.print(" | Right Speed: ");

  Serial.print(rightSpeed);

  Serial.print(" | Lidar Angle: ");

  Serial.println(safeLidarAngle);

}

 

void setup() {

  Serial.begin(115200);

  // Initialize communication with Orange Pi 5

  myCommSerial.begin(115200, SERIAL_8N1, COMM_RX_PIN, COMM_TX_PIN);

  // Initialize communication with LiDAR

  myLidarSerial.begin(115200, SERIAL_8N1, LIDAR_RX_PIN, LIDAR_TX_PIN);

 

  servoRW.attach(servoPinRW);

  servoLW.attach(servoPinLW);

  servoLidar.attach(servoPinLidar);

 

  Serial.println("ESP32-S3 ready. Waiting for commands from Orange Pi 5...");

}

 

void loop() {

  // Check for commands from the Orange Pi 5

  if (myCommSerial.available()) {

    String jsonString = myCommSerial.readStringUntil('\n');

    DynamicJsonDocument doc(200);

    DeserializationError error = deserializeJson(doc, jsonString);

 

    if (error) {

      Serial.print(F("deserializeJson() failed: "));

      Serial.println(error.f_str());

      return;

    }

 

    int leftSpeed = doc["leftSpeed"];

    int rightSpeed = doc["rightSpeed"];

    int lidarAngle = doc["lidarAngle"];

 

    setServoSpeeds(leftSpeed, rightSpeed, lidarAngle);

  }

}

 

// Custom map function

long map(long x, long in_min, long in_max, long out_min, long out_max) {

  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

}

 

============  Python Code from Orange Pi 5 ==============

import serial

import time

import json

 

# Configure the serial port and baud rate

# Make sure the baud rate (115200) matches what you set in the ESP32 code.

serial_port = serial.Serial('/dev/ttyS0', 115200)

 

print("Robot Controller Starting...")

 

def send_command(left_speed, right_speed, lidar_angle):

    """

    Sends a JSON command to the ESP32-S3 over the serial port.

    """

    command = {

        "leftSpeed": left_speed,

        "rightSpeed": right_speed,

        "lidarAngle": lidar_angle

    }

    

    # Convert the dictionary to a JSON string

    json_string = json.dumps(command)

    

    # Add a newline character to signify the end of the command

    message = json_string + "\n"

    

    print(f"Sending: {message.strip()}")

    

    # Encode the message and send it over the serial port

    serial_port.write(message.encode('utf-8'))

    

try:

    while True:

        # --- TEST 1: Forward Arc Turn ---

        print("Commanding a right arc turn...")

        send_command(50, 25, 100)

        time.sleep(4)  # Run for 4 seconds

 

        # --- TEST 2: Stop ---

        print("Commanding a full stop...")

        send_command(0, 0, 90)

        time.sleep(2)  # Wait for 2 seconds

 

        # --- TEST 3: Backward Arc Turn ---

        print("Commanding a left backward arc turn...")

        send_command(-25, -50, 30)  # 30 for lidar will make it 100% forward.

        time.sleep(4)  # Run for 4 seconds

 

        # --- TEST 4: Stop ---

        print("Commanding a full stop...")

        send_command(0, 0, 90)

        time.sleep(5)  # Wait for 2 seconds

 

except KeyboardInterrupt:

    print("Communication stopped by user.")

finally:

    # Close the serial port when finished

    serial_port.close()

    print("Serial port closed.")

=============================================================

 

No. Subject Author Date Views
Notice For the first time user of ESP32-S3 super mini users. me 2025.04.25 806
16 Other Approach proposed by Gemini me 2025.10.02 96
15 Data Route me 2025.10.02 100
» Extra Hardware Serial + JSON servo control file me 2025.09.22 139
13 Wheel Arc movement with continous servos file me 2025.09.21 154
12 3 Servo Test file me 2025.09.21 131
11 Object Pascal App getting data from ESP32-S3 (Parsing) file me 2025.04.29 592
10 Sound Sensor Test file me 2025.04.27 603
9 Laser distance sensor VL53L0X file me 2025.04.27 626
8 9DOF : Getting Pitch & Roll with ICM20948 v2 file me 2025.04.27 604
7 Formating output file me 2025.04.27 592
6 Blinking Built-in RGB without delay() me 2025.04.25 3802
5 Built-in RGB led Demo me 2025.04.25 683
4 Servo Demo me 2025.04.25 585
3 HMC5883L Compass demo file me 2025.04.25 648
2 I2C Address Search file me 2025.04.25 632
1 Serial Sample (ASCII Table) file me 2025.04.25 673