A machine vision-based robotic assembly system using the MechArm 270, NVIDIA Jetson Nano, and a custom ESP32 controller board for automated pick-and-place and miniature car assembly.
Controller is an open-source printed circuit board by Circuit-Digest, from the Circuit-Digest/machine-vision-robotic-assembly-system repository on GitHub, published under the MIT licence. It is a 2-layer board of 175 × 90 mm with 95 parts on 101 nets, routed with 489 tracks and 101 vias.
It is built around the ESP32-S3-WROOM-1-N8, LM2596S-3.3 and SI4463CDY-T1-GE3-VB, with the SP0504BAHTG, LL4148 and SS8550 among its other parts. Its parts include 32 resistors, 15 diodes, 13 connectors, 9 ICs and 6 capacitors. It belongs with the ESP32 boards of this library.
🤖 Machine Vision-Based Robotic Assembly System Using MechArm 270 and Jetson Nano
A real-time computer-vision system that drives a 6-DOF robotic arm + linear rail to autonomously assemble two toy cars, verifying every part placement using black-pixel ROI detection on an on-board webcam.
This system orchestrates a MechArm 270 6-DOF robotic arm mounted on a stepper-driven linear rail to perform automated, vision-verified pick-and-place assembly of two toy cars.
The arm visits five physical stations. At each inspection station it positions its wrist-mounted webcam over a part tray, and a real-time OpenCV pipeline verifies the correct component is present using black-pixel ROI analysis before the arm is allowed to pick it up. A missing part immediately halts the sequence, triggers a physical buzzer alert, and waits for an operator to place the correct component.
The entire stack — robot control, vision processing, rail control, and web dashboards — runs as a single Python process on port 5000, eliminating all inter-service network latency.
✨ Key Features
Feature
Description
🎥 Live MJPEG Stream
Real-time webcam feed with annotated ROI overlays served to the browser
🔍 Black-Pixel ROI Detection
Station-aware part detection using calibrated bounding boxes and HSV black masking
🤖 Wi-Fi Arm Control
Non-blocking TCP socket control of MechArm 270 via pymycobot
🚂 ESP32 Rail Control
HTTP-driven stepper linear rail with 5 presets (P1–P5)
🚦 Physical Indicators
Green/Red LED + buzzer relay control for workshop-audible alerts
✅ Assembly Checklist
Live progress bar and per-part checklist updating on every verification
🖥️ Three Dashboards
Home display, Operator dashboard, Waypoint editor — all browser-based
🛡️ Sim Mode Fallback
Full simulation when no hardware is connected — no code changes needed
💾 JSON Persistence
All waypoints, poses, ROIs, and network config survive server restarts
[!NOTE]
The system runs in full simulation mode if no hardware is connected. The camera stream is replaced by an animated mock feed, all Socket.IO events fire normally, and you can test the complete UI and checklist flow without any physical hardware.
💻 Software Requirements & Installation
1. Clone the repository
bash
git clone https://github.com/YOUR_USERNAME/machine-vision-robotic-assembly-system.git
cd machine-vision-robotic-assembly-system
2. Create a virtual environment (recommended)
bash
python -m venv venv
# Windows
venv\Scripts\activate
# Linux / macOS
source venv/bin/activate
3. Install dependencies
bash
pip install -r requirements.txt
Dependency Overview
Package
Purpose
flask
Web server & template rendering
flask-socketio
Real-time WebSocket transport
requests
HTTP calls to the ESP32 Rail API
pymycobot
MechArm 270 Wi-Fi TCP SDK
opencv-python
Video capture, black-pixel ROI masking, MJPEG stream
numpy
Array operations for vision pipeline
⚙️ Configuration
Step 1 — Set your network IPs
Edit config.py and update the two IP constants at the bottom of the file:
python
ARM_IP = "192.168.1.100"# Your MechArm270's Wi-Fi IP address
RAIL_IP = "192.168.1.101"# Your ESP32-C6 Rail controller IP
[!TIP]
You can also set these at runtime without restarting the server — open the Operator Dashboard, click the gear icon ⚙️, and enter your IPs. They are saved to robot_config.json and rail_config.json and take effect immediately.
Step 2 — Camera index
In config.py, set the correct USB camera index:
python
CAMERA_INDEX = 0# 0 = default (first USB camera)# 1 = second USB camera, etc.
Step 3 — Vision detection thresholds
Tune these in config.py to match your lighting and part colours:
python
# Black part detection
BLACK_HSV_LOWER = (0, 0, 0)# HSV lower bound for black
BLACK_HSV_UPPER = (180, 255, 50)# V < 50 = genuinely dark/black
BLACK_PIXEL_RATIO = 0.10# 10% of ROI must be black to count as "present"# Temporal hysteresis (noise suppression)
CONFIRM_FRAMES = 5# frames a part must be seen before "stable"
DISAPPEAR_FRAMES = 10# frames a part must be missing before "lost"
Step 4 — Runtime-persisted configuration files
The following JSON files are auto-generated and updated by the dashboards. They override the config.py defaults:
File
Contents
Editable via
robot_config.json
Arm IP, port, axis calibration offsets
Operator Dashboard ⚙️
rail_config.json
Rail ESP32 IP
Operator Dashboard ⚙️
camera_settings.json
Brightness, contrast, exposure, gain
Operator Dashboard 🎥
scan_poses.json
6-joint arm angles per inspection station
Waypoint Editor → Scan Poses
roi_boundaries.json
Per-part pixel bounding boxes (ROI)
Operator Dashboard → ROI Editor
zone_boundaries.json
Spatial zone definitions per station
Operator Dashboard → Zone Editor
waypoints.json
Full arm + rail motion sequence
Waypoint Editor
[!WARNING]
The waypoints.json included in this repository was recorded on a specific physical rig. Joint angles and positions will not transfer to a different robot or table layout. You must re-record all waypoints using the Waypoint Editor for your own setup.
🚀 Running the Server
bash
python main.py
The server starts on http://0.0.0.0:5000. Open a browser and navigate to:
URL
Dashboard
http://localhost:5000/
🏠 Home Display Dashboard
http://localhost:5000/camera_view
🖥️ Operator Dashboard
http://localhost:5000/editor
✏️ Waypoint Editor
On startup you will see:
text
======================================================================
Robotic Assembly System (MechArm 270 & Jetson Nano) -> http://localhost:5000
Robotic Arm + Stepper Linear Rail + Black-pixel ROI Vision Integrated.
======================================================================
The robot arm and rail connections are made in the background — if they fail the server continues in simulation mode and retries every 15 seconds.
🖥️ Dashboard Guide
🏠 Home Display Dashboard (/)
Clean status overview, suitable for display on a monitor during operation.
▶ Play Sequence — starts the full automated assembly run
⏹ Stop Arm — emergency halt
🖥️ Operator Dashboard (/camera_view)
Full-featured operator view for monitoring and controlling the assembly:
Live annotated stream — ROI boxes (grey → yellow → green), part labels, pixel-ratio readout, station overlay
Robot telemetry — 6 joint angles, XYZ coordinates updated every 200 ms
Assembly checklist — all parts for both cars, updating in real time
8-Switch Simulator Panel — toggle any part as "present" for dry-run testing without physical components
Halt/Error Panel — if the sequence stops on a missing part, this panel shows the reason and a restart button
✏️ Waypoint Editor (/editor)
Engineering tool for teaching the robot its motion sequence:
Jog controls — move each of the 6 joints or X/Y/Z coordinates from the browser
Record — save the current arm pose as a new waypoint (angles, coords, or both)
Edit sequence — rename, reorder, adjust speed, vacuum action, delay, and rail preset per waypoint
Scan Pose console — jog the arm to the perfect camera inspection angle, then click Set P1 (or P2/P4/P5) to save to scan_poses.json
Motor calibration — lock/unlock individual joints, adjust motor power levels
Network settings — change Arm IP, Rail IP, and speed without restarting the server
📐 Calibration Workflow
Follow this sequence when setting up on a new physical rig:
text
1. Physical setup
└─ Mount arm on rail, position part trays at stations P1, P2, P4, P5
2. Network configuration
└─ Set ARM_IP and RAIL_IP in config.py or via Operator Dashboard ⚙️
3. Camera verification
└─ Open /camera_view, check live stream
└─ Adjust CAMERA_INDEX in config.py if wrong camera opens
4. Scan pose recording (Waypoint Editor → 📸 Inspection Scan Poses)
└─ Jog arm to view P1 tray → click "Set P1 (Chassis)"
└─ Repeat for P2, P4, P5
5. ROI calibration (Operator Dashboard → ROI Editor)
└─ Move arm to scan pose for each station
└─ Draw bounding boxes around each part slot on the video frame
└─ Save → updates roi_boundaries.json
6. Detection threshold tuning (config.py)
└─ Adjust BLACK_PIXEL_RATIO until parts detect cleanly
└─ Use 8-Switch Simulator to verify checklist behaviour
7. Waypoint recording (Waypoint Editor)
👁️ Vision Pipeline
The vision system runs in a dedicated background thread at ~30 FPS using OpenCV.
Black-Pixel ROI Detection
The only detection method used is black-pixel ratio analysis within calibrated Region of Interest (ROI) bounding boxes:
text
Frame (BGR)
│
├─ GaussianBlur (5×5) → HSV conversion
│
└─ For each active part at current station:
Crop frame to ROI bounding box (from roi_boundaries.json)
Apply black HSV mask: H[0-180] S[0-255] V[0-50]
ratio = countNonZero(mask) / roi_area
present = ratio - ambient_baseline ≥ BLACK_PIXEL_RATIO (10%)
An adaptive ambient baseline is captured on the first frame after the arm settles at its scan pose. This compensates automatically for dim environments or dark surfaces in the background.
How Detection Works Per Station
Rail moves arm to station (e.g. P1)
Arm commands itself to pre-saved scan pose for that station (scan_poses.json)
Vision thread activates and begins checking only the parts registered to that station (STATION_PARTS in config.py)
For each active part slot, it crops the frame to the ROI (roi_boundaries.json) and measures the black-pixel ratio
Parts meeting the threshold are accumulated over frames; confirmed after CONFIRM_FRAMES consecutive detections
Hysteresis Filtering
Raw frame results are not immediately acted upon — a two-stage filter prevents false positives from motion blur, shadows, or lighting glitches:
text
MISSING ──[seen for 5 consecutive frames]──→ STABLE (detected)
STABLE ──[missing for 10 consecutive frames]──→ MISSING
Stream Annotation
During an active vision check, the live stream shows:
Grey boxes — ROI is active, part not detected
Yellow boxes — part seen but not yet stable (accumulating frames)
Green boxes — part confirmed stable (checkmark ✓ + ratio %)
Station panel — current station label + list of active part slots
Home Assistant Smart Home Alarm Control Panel with fingerprint reader, NFC/RFID card reader, motion radar, and touchscreen TFT display. It can control your smart home, not just your home security system.
Two-axis motorised GoPro mount with physical buttons, BLE camera control, and a built-in HTTPS web UI for live HDMI preview and gallery access. ESP32-S3 / SimpleFOC.
It measures 175 × 90 mm and has 2 copper layers, 1.6 mm thick.
What parts does the Controller use?
95 parts, built around the ESP32-S3-WROOM-1-N8, LM2596S-3.3, SI4463CDY-T1-GE3-VB and SP0504BAHTG. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
Where can I download the Controller KiCad files?
From the Circuit-Digest/machine-vision-robotic-assembly-system repository on GitHub, at the commit this page was made from: the board is hardware/controller.kicad_pcb and its schematic hardware/controller.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the Controller design in my own project?
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).