# Dual Controller Sync

> Debug and synchronize communication between the robocar main controller (Heltec WiFi LoRa 32) and camera module (ESP32-CAM)

- Skill: `laurigates/dual-controller-sync` (Agent Skill)
- Install (CLI): `npx skillmds@latest add laurigates/dual-controller-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/laurigates/dual-controller-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: laurigates (https://skillmd.com/u/laurigates)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/laurigates/dual-controller-sync

---


# 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

```bash
# Build main controller
just robocar::build-main

# Build camera module
just robocar::build-cam

# Or build both
just robocar::build-all
```

## Monitor Both Controllers

### Two Terminal Setup

Open two terminals and monitor both:

**Terminal 1 - Main Controller:**
```bash
just robocar::monitor-main PORT=/dev/cu.usbserial-0001
```

**Terminal 2 - Camera Module:**
```bash
just robocar::monitor-cam PORT=/dev/cu.usbserial-0002
```

### Identifying Ports

If unsure which device is which:
```bash
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):**
```c
#define CAMERA_I2C_ADDR 0x55  // 7-bit address
```

**Camera module (slave):**
```c
#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

1. Main sends command byte
2. Camera processes command
3. Camera sends response
4. Main reads response

### Debug Logging

Enable verbose I2C logging in both projects:

```c
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:**
```c
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

```bash
# Flash main controller first
just robocar::flash-main PORT=/dev/cu.usbserial-0001

# Then flash camera (requires GPIO0 to GND)
# Connect GPIO0 to GND on ESP32-CAM
just robocar::flash-cam PORT=/dev/cu.usbserial-0002
# Disconnect GPIO0 from GND and reset
```

### Development Cycle

For rapid iteration:

1. Make code changes
2. Build: `just robocar::build-all`
3. Flash main: `just robocar::flash-main`
4. Flash camera (GPIO0→GND): `just robocar::flash-cam`
5. Monitor both in separate terminals

## Common Synchronization Issues

### Issue: Camera Not Responding

**Symptoms:**
- Main reports I2C timeout
- Camera not in monitor output

**Debug Steps:**
1. Verify camera is powered and running
2. Check I2C address matches
3. Verify GPIO pins for I2C slave
4. Check clock speed compatibility

### Issue: Corrupted Data

**Symptoms:**
- Data received but values wrong
- Checksum failures

**Debug Steps:**
1. Reduce I2C speed (try 100kHz)
2. Add pull-up resistors
3. Check for noise on long wires
4. Verify endianness of multi-byte data

### Issue: Timing Mismatch

**Symptoms:**
- Works sometimes, fails other times
- Camera not ready when main sends command

**Debug Steps:**
1. Add handshake mechanism
2. Increase timeout values
3. Use interrupt-based I2C on camera
4. Add ready signal GPIO

## Tools and Commands

```bash
# Show system info
just robocar::info

# Check environment
make check-environment

# Clean and rebuild
just robocar::clean-all
just robocar::build-all

# Full dev cycle for main
just robocar::develop-main PORT=/dev/xxx

# Full dev cycle for camera
just robocar::develop-cam PORT=/dev/xxx
```

