Repository navigation
Expand file tree
/
Copy pathespnow.py
More file actions
158 lines (129 loc) · 5.12 KB
/
Copy pathespnow.py
File metadata and controls
158 lines (129 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python3
"""
ESP32 Serial Terminal — Jetson
Sends JSON commands to the ESP32 transmitter over UART,
which forwards them to the rover via ESP-NOW.
Usage:
python3 esp32_terminal.py [port] [baud]
port — defaults to /dev/ttyUSB0
baud — defaults to 115200
Examples:
python3 esp32_terminal.py
python3 esp32_terminal.py /dev/ttyUSB1
python3 esp32_terminal.py /dev/ttyUSB0 115200
"""
import serial
import serial.tools.list_ports
import threading
import sys
import time
# ── Config ────────────────────────────────────────────────────────────
DEFAULT_PORT = "/dev/ttyTHS1" # Jetson Nano onboard UART (ttyTHS1) is usually connected to ESP32
DEFAULT_BAUD = 115200
# ── Preset commands (type the shortcut instead of full JSON) ──────────
PRESETS = {
"stop": '{"T":1,"L":0,"R":0}',
"fwd": '{"T":1,"L":0.5,"R":0.5}',
"back": '{"T":1,"L":-0.5,"R":-0.5}',
"left": '{"T":1,"L":-0.3,"R":0.3}',
"right": '{"T":1,"L":0.3,"R":-0.3}',
"fwd_fast": '{"T":1,"L":1.0,"R":1.0}',
"back_fast": '{"T":1,"L":-1.0,"R":-1.0}',
}
# ─────────────────────────────────────────────────────────────────────
def list_ports():
"""Print all available serial ports."""
ports = serial.tools.list_ports.comports()
if not ports:
print(" No serial ports found.")
for p in ports:
print(f" {p.device:20s} — {p.description}")
def reader_thread(ser):
"""Background thread — prints anything the ESP32 sends back."""
while True:
try:
if ser.in_waiting:
line = ser.readline().decode("utf-8", errors="replace").strip()
if line:
print(f"\n ← {line}")
print(" > ", end="", flush=True)
except serial.SerialException:
print("\n[!] Serial connection lost.")
break
except Exception:
pass
time.sleep(0.01)
def send(ser, cmd):
"""Send a command string, appending newline."""
cmd = cmd.strip()
if not cmd:
return
ser.write((cmd + "\n").encode("utf-8"))
print(f" → {cmd}")
def print_help():
print("""
── Commands ──────────────────────────────────────────
Any JSON string Send raw JSON to rover
e.g. {"T":1,"L":0.5,"R":0.5}
── Presets ───────────────────────────────────────────""")
for k, v in PRESETS.items():
print(f" {k:15s} → {v}")
print("""
── Terminal commands ─────────────────────────────────
help Show this message
ports List available serial ports
quit / exit / q Exit
─────────────────────────────────────────────────────
""")
def main():
port = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_PORT
baud = int(sys.argv[2]) if len(sys.argv) > 2 else DEFAULT_BAUD
print(f"\n ESP32 Serial Terminal")
print(f" Connecting to {port} at {baud} baud...\n")
# Auto-detect if default port doesn't exist
try:
ser = serial.Serial(port, baud, timeout=0.1)
except serial.SerialException as e:
print(f" [!] Could not open {port}: {e}")
print("\n Available ports:")
list_ports()
print("\n Run with: python3 esp32_terminal.py /dev/ttyUSBx\n")
sys.exit(1)
time.sleep(2) # Wait for ESP32 to boot / reset after serial connect
ser.reset_input_buffer()
print(f" Connected. Type 'help' for commands.\n")
# Start background reader
t = threading.Thread(target=reader_thread, args=(ser,), daemon=True)
t.start()
try:
while True:
try:
user_input = input(" > ").strip()
except EOFError:
break
if not user_input:
continue
low = user_input.lower()
if low in ("quit", "exit", "q"):
# Send stop before exiting for safety
send(ser, PRESETS["stop"])
print("\n Bye.\n")
break
elif low == "help":
print_help()
elif low == "ports":
print("\n Available ports:")
list_ports()
print()
elif low in PRESETS:
send(ser, PRESETS[low])
else:
# Treat as raw JSON
send(ser, user_input)
except KeyboardInterrupt:
send(ser, PRESETS["stop"])
print("\n\n Interrupted — stop sent. Bye.\n")
finally:
ser.close()
if __name__ == "__main__":
main()