Skip to content

Python UART

The ESP32 driver board exposes a USB-serial interface (via CP2102 or CH340 chip) for direct wired control. Serial commands use the same JSON protocol as WiFi and ESP-NOW.

Connect the ESP32 board to your computer via USB-C. The serial port appears as:

OSTypical Port
Linux/dev/ttyUSB0 or /dev/ttyACM0
macOS/dev/cu.usbserial-* or /dev/cu.SLAB_USBtoUART
WindowsCOM3, COM4, etc.
SettingValue
Baud rate115200
Data bits8
ParityNone
Stop bits1
Flow controlNone

Install pyserial:

Terminal window
pip install pyserial
import serial
import json
import time
# Open serial connection
ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=1)
time.sleep(2) # Wait for ESP32 boot
def send_command(cmd: dict) -> str:
"""Send a JSON command and read the response."""
payload = json.dumps(cmd) + "\n"
ser.write(payload.encode())
time.sleep(0.1)
response = ser.read(ser.in_waiting).decode(errors="ignore")
return response
# Move to home position
print(send_command({"T": 100}))
# Get current position
print(send_command({"T": 105}))
# Move to specific XYZ
print(send_command({"T": 104, "x": 200, "y": 50, "z": 150, "t": 1.57, "spd": 0.25}))
# Close gripper
print(send_command({"T": 106, "cmd": 3.14, "spd": 0, "acc": 0}))
ser.close()

The arm sends JSON responses back over serial. For position feedback:

response = send_command({"T": 105})
data = json.loads(response)
print(f"Position: x={data['x']}, y={data['y']}, z={data['z']}")
print(f"Torques: base={data['torB']}, shoulder={data['torS']}, elbow={data['torE']}")

For real-time control applications (e.g., joystick input, sensor-based reactions):

import serial
import json
import time
ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=0.1)
time.sleep(2)
try:
while True:
# Read current position
ser.write(b'{"T":105}\n')
time.sleep(0.05)
response = ser.read(ser.in_waiting).decode(errors="ignore")
# Process and send next command
cmd = {"T": 104, "x": 200, "y": 0, "z": 200, "t": 1.57, "spd": 0.5}
ser.write((json.dumps(cmd) + "\n").encode())
time.sleep(0.05) # 20 Hz update rate
except KeyboardInterrupt:
# Emergency stop on exit
ser.write(b'{"T":0}\n')
ser.close()

Control how much the firmware prints to serial:

{"T":605,"cmd":0}
ValueBehavior
0Suppress debug output
1Print debug info (default)
2Flow feedback mode
import serial
import json
def connect(port: str, retries: int = 3) -> serial.Serial:
for attempt in range(retries):
try:
ser = serial.Serial(port, 115200, timeout=1)
time.sleep(2)
# Test connection
ser.write(b'{"T":105}\n')
time.sleep(0.2)
if ser.in_waiting > 0:
return ser
except serial.SerialException:
if attempt < retries - 1:
time.sleep(1)
raise ConnectionError(f"Cannot connect to {port}")

Serial control reference from the Waveshare Python UART guide and firmware source.