Dual-Controller Synchronization Guide
When to Use This Skill
Apply this skill when the user:
-
Has issues with I2C communication between main and camera controllers
-
Needs to debug the dual-ESP32 robocar architecture
-
Wants to monitor both controllers simultaneously
-
Experiences timing or synchronization issues
Architecture Overview
┌─────────────────────┐ I2C ┌─────────────────────┐ │ Main Controller │◄────────────►│ Camera Module │ │ Heltec WiFi LoRa │ │ ESP32-CAM │ │ │ │ │ │ - AI decisions │ │ - Image capture │ │ - Motor control │ │ - Vision analysis │ │ - LoRa comms │ │ - I2C slave │ └─────────────────────┘ └─────────────────────┘
Build Both Controllers
Build main controller
make robocar-build-main
Build camera module
make robocar-build-cam
Or build both
make robocar-build-all
Monitor Both Controllers
Two Terminal Setup
Open two terminals and monitor both:
Terminal 1 - Main Controller:
make robocar-monitor-main PORT=/dev/cu.usbserial-0001
Terminal 2 - Camera Module:
make robocar-monitor-cam PORT=/dev/cu.usbserial-0002
Identifying Ports
If unsure which device is which:
ls -la /dev/cu.usbserial-* /dev/ttyUSB*
Look for:
-
Device that appears first after connecting main controller
-
Device that appears after connecting camera module
I2C Communication Debugging
Common I2C Issues
Symptom Possible Cause Solution
No response Wrong address Verify 7-bit address format
Timeout Missing pull-ups Add 4.7K resistors on SDA/SCL
Corrupted data Speed too fast Reduce I2C clock frequency
Intermittent Loose connection Check wiring
I2C Address Configuration
Ensure both controllers use the same address:
Main controller (master):
#define CAMERA_I2C_ADDR 0x55 // 7-bit address
Camera module (slave):
#define I2C_SLAVE_ADDR 0x55 // Must match master
Verify I2C Wiring
Main Controller Camera Module SDA (21) ◄──────────► SDA (GPIO) SCL (22) ◄──────────► SCL (GPIO) GND ◄──────────► GND
Pull-up resistors (4.7K) on SDA and SCL to 3.3V.
Protocol Debugging
Expected Communication Pattern
-
Main sends command byte
-
Camera processes command
-
Camera sends response
-
Main reads response
Debug Logging
Enable verbose I2C logging in both projects:
esp_log_level_set("i2c", ESP_LOG_DEBUG);
Look for matching transactions:
-
Main: "Sent command 0x01 to 0x55"
-
Camera: "Received command 0x01"
Timing Issues
If commands arrive too fast:
Add delay between commands:
i2c_master_cmd_begin(I2C_NUM, cmd, pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(10)); // Wait for slave to process
Flash Workflow
Flash Both Controllers
Flash main controller first
make robocar-flash-main PORT=/dev/cu.usbserial-0001
Then flash camera (requires GPIO0 to GND)
Connect GPIO0 to GND on ESP32-CAM
make robocar-flash-cam PORT=/dev/cu.usbserial-0002
Disconnect GPIO0 from GND and reset
Development Cycle
For rapid iteration:
-
Make code changes
-
Build: make robocar-build-all
-
Flash main: make robocar-flash-main
-
Flash camera (GPIO0→GND): make robocar-flash-cam
-
Monitor both in separate terminals
Common Synchronization Issues
Issue: Camera Not Responding
Symptoms:
-
Main reports I2C timeout
-
Camera not in monitor output
Debug Steps:
-
Verify camera is powered and running
-
Check I2C address matches
-
Verify GPIO pins for I2C slave
-
Check clock speed compatibility
Issue: Corrupted Data
Symptoms:
-
Data received but values wrong
-
Checksum failures
Debug Steps:
-
Reduce I2C speed (try 100kHz)
-
Add pull-up resistors
-
Check for noise on long wires
-
Verify endianness of multi-byte data
Issue: Timing Mismatch
Symptoms:
-
Works sometimes, fails other times
-
Camera not ready when main sends command
Debug Steps:
-
Add handshake mechanism
-
Increase timeout values
-
Use interrupt-based I2C on camera
-
Add ready signal GPIO
Tools and Commands
Show system info
make robocar-info
Check environment
make check-environment
Clean and rebuild
make robocar-clean make robocar-build-all
Full dev cycle for main
make robocar-develop-main PORT=/dev/xxx
Full dev cycle for camera
make robocar-develop-cam PORT=/dev/xxx