Vision + ESP32 2‑servo controller.
Video: https://youtu.be/oHfYfc69wVg
ServoVis has two parts:
- ESP32 hosts a tiny web server with a
/setendpoint that sets servo angles. - Python reads an IP camera stream, finds a dark dot in the image, and (optionally) sends angles to the ESP32.
- esp32code.ino — ESP32 Wi‑Fi web server + servo control
- pythonscript.py — OpenCV dot detection + optional tracking
- ESP32
- 2× hobby servos (base + joint)
- External 5V supply for servos (recommended)
Default pins (edit in esp32code.ino if needed):
- Base servo: GPIO 15
- Joint servo: GPIO 13
Important: share GND between ESP32 and the servo power supply.
- Open esp32code.ino in Arduino IDE.
- Set
ssidandpassword. - Upload.
- Open Serial Monitor @
115200and note the printed IP address.
You can also visit http://<esp32-ip>/ to use the built‑in UI.
python3 -m pip install -r requirements.txtUpdate the ESP32 and camera URLs (CLI flags shown here):
Demo mode (default): shows video and moves through 3 hardcoded poses.
python3 pythonscript.py --mode demo --esp32 http://192.168.10.5 --camera http://192.168.10.3:4747/videoView only: just see detection overlays.
python3 pythonscript.py --mode view --camera http://192.168.10.3:4747/videoTrack mode: follow the detected dot (press q to quit).
python3 pythonscript.py --mode track --esp32 http://192.168.10.5 --camera http://192.168.10.3:4747/videoSupported query formats:
/set?base=<0-180>&joint=<0-180>(used by the Python script)/set?joint=base&angle=<0-180>(used by the ESP32 web UI)
The function pixel_to_angles() in pythonscript.py linearly interpolates angles using corner_angles.
If your mechanics differ, adjust corner_angles to match the angles needed when the dot is in each corner.
- ESP32 UI loads but buttons do nothing: ensure the ESP32 is on the same network and you’re visiting
http://<esp32-ip>/. - Servo jitter / brownouts: power servos from a separate 5V supply and share GND with the ESP32.
- No video: confirm the IP camera URL plays in a browser/VLC.
- Detection is noisy: adjust the contour
areafilter and thresholding settings in pythonscript.py.
This can move unexpectedly. Keep hands clear and start with low-power / small servos while tuning.