Assignment: Networked Node with I/O Devices
For this week's networking assignment, I designed and built a networked node system as part of the BRAINROT 9000 autonomous robot from Machine Week. The system uses wireless communication (WiFi) to connect an ESP32 camera node with a Flask server, enabling vision-guided autonomous navigation.
Network Architecture
System Overview
The networking system consists of three communicating nodes:
- ESP32-CAM Node (wireless client) - Captures images, sends via WiFi, receives drive commands
- Flask Server (wireless server) - Processes images, runs YOLO detection, computes motor commands
- Motor Driver Node (wired serial) - Receives step commands from ESP32 via high-speed serial
Network Addressing
The system uses standard IP networking on the local WiFi network:
- ESP32 Address: Dynamic DHCP assignment (e.g., 192.168.10.X)
- Flask Server: Static local IP 192.168.10.138:80
- Network: EDS_Shop_24 (2.4 GHz WiFi)
Wireless Communication (WiFi)
ESP32 WiFi Implementation
The ESP32-CAM connects to the local WiFi network and acts as an HTTP client. I worked with TA Quentin on the firmware that handles the WiFi connection and image streaming:
// WiFi configuration
const char* ssid = "EDS_Shop_24";
const char* password = "eds12345";
// Server endpoint
#define SERVER_IP "192.168.10.138"
#define SERVER_PORT "80"
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println(WiFi.localIP());
HTTP POST Communication
The ESP32 captures camera frames and posts them as JPEG images to the Flask server using HTTP:
HTTPClient http;
http.begin("http://192.168.10.138:80/esp32_upload");
http.addHeader("Content-Type", "image/jpeg");
// Send image
int httpCode = http.POST((uint8_t *)fb->buf, fb->len);
if (httpCode == 200) {
String payload = http.getString();
// Parse JSON response for motor commands
}
This implements a request-response pattern where each image upload receives immediate motor command feedback. See detailed system architecture in Machine Week documentation.
WiFi Performance Considerations
Latency: Measured round-trip time from image capture to motor command receipt was 80-120ms, which proved acceptable for tracking slow-moving targets.
Bandwidth optimization: To reduce latency, I configured the ESP32 camera to:
- Use QVGA resolution (320×240) instead of VGA
- JPEG quality setting of 60% (balance between size and detection accuracy)
- Frame rate ~10 FPS (adequate for human tracking)
Flask Server (Network Application Layer)
HTTP Server Implementation
I implemented the Flask server that acts as the network hub for the robot. It provides multiple HTTP endpoints:
@app.route('/esp32_upload', methods=['POST'])
def esp32_upload():
# Receive JPEG image
img_data = request.get_data()
img = Image.open(io.BytesIO(img_data))
# Run YOLO detection
detector = get_detector()
results = detector.predict(img, silent=True)
# Compute motor commands
detections = process_detections(results)
# Return JSON response
return jsonify({
'status': 'ok',
'detections': detections
})
JSON Response Format
The server responds with structured JSON containing motor commands:
{
"status": "ok",
"detections": [
{
"bbox": [x1, y1, x2, y2],
"label": "person",
"confidence": 0.87,
"drive_command": {
"v_left": 0.12,
"v_right": 0.08,
"stop": false
}
}
]
}
The ESP32 parses this JSON using the ArduinoJson library and extracts the velocity commands for motor control.
Serial Communication (Wired)
High-Speed Serial to Motor Drivers
The ESP32 communicates with the stepper motor drivers using asynchronous serial at 2 Mbaud (2,000,000 baud). This high speed is necessary for real-time motor control updates at 1kHz.
// Serial configuration
#define PIN_SER_TX 6
#define PIN_SER_RX 7
Serial1.begin(2000000UL, SERIAL_8N1, PIN_SER_RX, PIN_SER_TX);
Binary Protocol
The serial protocol uses a custom binary format for efficiency. Each motor command is 2 bytes:
- Byte 1:
0x80 | (step_value & 0x7F)- Motor 1 command with flag bit - Byte 2:
step_value & 0x7F- Motor 2 command (7-bit signed value)
// Send motor commands
Serial1.write(MASK_FLAG | (s1 & MASK_7BITS)); // Motor 1
Serial1.write(s2 & MASK_7BITS); // Motor 2
This protocol allows step values from -63 to +63, where positive values drive forward and negative drive backward. The flag bit (0x80) helps the receiver synchronize to the start of each 2-byte packet.
Serial vs. Wireless Trade-offs
Using wired serial for motor control instead of WiFi provides:
- Deterministic timing: 1kHz update rate with minimal jitter
- Reliability: No packet loss or WiFi interference issues
- Lower latency: Microseconds vs. milliseconds for WiFi
Network Protocols & OSI Layers
Protocol Stack
The BRAINROT 9000 system uses multiple networking protocols across different OSI layers:
| OSI Layer | Protocol/Technology | Purpose in System |
|---|---|---|
| Layer 7: Application | HTTP, JSON | Image upload, motor command responses |
| Layer 4: Transport | TCP | Reliable delivery of HTTP requests/responses |
| Layer 3: Network | IPv4 | Addressing and routing on local network |
| Layer 2: Data Link | 802.11 (WiFi), UART | WiFi MAC addressing, serial framing |
| Layer 1: Physical | 2.4 GHz RF, RS-232 | Wireless electromagnetic waves, serial voltage levels |
Wireless Physical Layer
The ESP32 uses 802.11b/g/n WiFi operating in the 2.4 GHz ISM band:
- Frequency: 2.4 GHz (2400-2483.5 MHz)
- Channel: Auto-selected by access point
- Modulation: OFDM (Orthogonal Frequency-Division Multiplexing)
- Max range: ~30m indoors with obstacles
Error Handling
The system implements error handling at multiple layers:
- WiFi layer: Automatic retransmission of lost packets (802.11 ACK)
- TCP layer: Checksums and sequence numbers ensure data integrity
- Application layer: HTTP status codes (200 OK, 500 Error) for request validation
- Serial layer: Flag bits for packet synchronization
Local Input/Output Devices
ESP32 Node I/O
The ESP32 node includes both input and output devices:
- Input: OV2640 camera module (captures 320×240 JPEG images at ~10 FPS)
- Output: Serial TX to motor drivers (binary command protocol at 2 Mbaud)
Server Node I/O
The Flask server node provides network I/O and processing:
- Input: HTTP POST requests with JPEG image data
- Processing: YOLO11n object detection on received images
- Output: JSON responses with drive commands
Network Performance Metrics
| Metric | Value | Notes |
|---|---|---|
| Image upload size | 8-15 KB | JPEG at 60% quality, 320×240 |
| Upload time | 40-60 ms | Varies with WiFi signal strength |
| YOLO processing time | 20-30 ms | On laptop CPU |
| JSON response size | ~200 bytes | Compact format |
| Total round-trip latency | 80-120 ms | Acceptable for human tracking |
| Serial command rate | 1000 Hz | 2 bytes per command |
Comparison: Wired vs. Wireless
Why WiFi for Vision?
WiFi was chosen for camera-to-server communication because:
- Robot is mobile - wired connection would limit movement
- Bandwidth requirement (80-120 kbps) is well within WiFi capability
- Latency tolerance allows for wireless (human movement is slow)
- Infrastructure already available (existing WiFi network)
Why Wired Serial for Motors?
High-speed serial was chosen for motor control because:
- Short distance (ESP32 to drivers ~10 cm) makes wiring practical
- Deterministic timing required for smooth motor control
- No wireless interference or packet loss concerns
- Lower complexity than wireless motor control protocol
Summary
This networking assignment demonstrates a practical multi-node system combining wireless (WiFi/HTTP) and wired (high-speed serial) communication. The ESP32-CAM node captures and transmits images, the Flask server processes them and computes commands, and the motor drivers receive control signals - all coordinated through network protocols. The system successfully enables autonomous robot navigation through networked vision processing.
For complete system details, see Machine Week documentation.