Robulus Hardware Configuration Guide
Audience: Robot builders, LLMs assisting with hardware setup, and anyone configuring a Robulus unit in Juvantia Fabrica.
1. What is Robulus?
Robulus is a remotely-controlled robotic unit managed through the Juvantia ecosystem. Each unit is built around an ESP32-S3 microcontroller and is controlled in real-time from a web-based Deck Control interface (deck.juvantia.org) via WebSocket over Wi-Fi.
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ ESP32-S3 (Dual Core) │
│ │
│ ┌─────────────────────┐ ┌───────────────────────────┐ │
│ │ CORE 0 │ │ CORE 1 │ │
│ │ (SYSTEM — locked) │ │ (USER CODE — editable) │ │
│ │ │ │ │ │
│ │ • Wi-Fi connection │ │ • user_setup() │ │
│ │ • WebSocket client │ │ • user_loop() │ │
│ │ • Heartbeat │ │ • deck() command handler │ │
│ │ • Command routing │ │ • Custom functions │ │
│ │ • OTA updates │ │ • Sensor reads │ │
│ │ │ │ • Motor/LED/Servo control │ │
│ └─────────────────────┘ └───────────────────────────┘ │
│ │
│ GPIO Pins ──────────────────────────── Physical World │
└─────────────────────────────────────────────────────────┘
│
│ WebSocket (Wi-Fi)
▼
┌─────────────────────┐
│ Deck Control │
│ deck.juvantia.org │
│ • Joysticks │
│ • Buttons │
│ • Telemetry view │
└─────────────────────┘2. Supported Microcontroller
ESP32-S3
| Property | Value |
|---|---|
| Chip | ESP32-S3 (Xtensa LX7, dual-core) |
| Clock | 240 MHz |
| RAM | 512 KB SRAM + 8 MB PSRAM (board-dependent) |
| Flash | 16 MB (board-dependent) |
| Wi-Fi | 802.11 b/g/n 2.4 GHz |
| USB | Native USB-OTG + UART |
| ADC | 2× 12-bit SAR ADC (up to 20 channels) |
| DAC | None (use PWM / LEDC instead) |
| PWM / LEDC | 8 channels, 14+ bit resolution |
| I2C | 2 buses |
| SPI | 4 buses |
| UART | 3 interfaces |
| GPIO count | 45 (GPIO 0–21, 33–48; GPIO 22–32 do not exist) |
| Operating voltage | 3.3V logic |
⚠ The ESP32-S3 does NOT have GPIO 22 through 32. These pin numbers simply don't exist on this chip. Never reference them.
Reference Board: GOOUUU ESP32-S3-CAM (V1.3)
This is the primary development board used in the Juvantia ecosystem. It has:
- 40 pin headers (2 rows × 20)
- Camera connector (FPC)
- Two USB-C ports: one for USB-UART (programming), one for USB-OTG
- RST and BOOT buttons
- Onboard Flash LED
3. GPIO Pin Map
Full Pinout Table
| GPIO | Available? | Notes | Board Label (Left) | Board Label (Right) |
|---|---|---|---|---|
| 0 | ❌ RESERVED | Boot strapping pin. Internal pull-up. Must not be LOW at boot. | — | G0 |
| 1 | ✅ Free | ADC1_CH0 | — | — |
| 2 | ✅ Free | ADC1_CH1 | — | G2 |
| 3 | ✅ Free | ADC1_CH2 | G3 | — |
| 4 | ✅ Free | ADC1_CH3 | G4 | — |
| 5 | ✅ Free | ADC1_CH4 | G5 | — |
| 6 | ✅ Free | ADC1_CH5 | G6 | — |
| 7 | ✅ Free | ADC1_CH6 | G7 | — |
| 8 | ✅ Free | ADC1_CH7 | G8 | — |
| 9 | ✅ Free | ADC1_CH8 | G9 | — |
| 10 | ✅ Free | ADC1_CH9, SPI | G10 | — |
| 11 | ✅ Free | ADC2_CH0, SPI | G11 | — |
| 12 | ✅ Free | ADC2_CH1, SPI | G12 | — |
| 13 | ✅ Free | ADC2_CH2, SPI | G13 | — |
| 14 | ✅ Free | ADC2_CH3 | G14 | — |
| 15 | ✅ Free | ADC2_CH4 | G15 | — |
| 16 | ✅ Free | ADC2_CH5 | G16 | — |
| 17 | ✅ Free | ADC2_CH6 | G17 | — |
| 18 | ✅ Free | ADC2_CH7 | G18 | — |
| 19 | ❌ RESERVED | USB D− (native USB-OTG) | — | G19 |
| 20 | ❌ RESERVED | USB D+ (native USB-OTG) | — | G20 |
| 21 | ✅ Free | General purpose | — | G21 |
| 22–32 | ❌ N/A | Do not exist on ESP32-S3 | — | — |
| 33 | ✅ Free | General purpose | — | — |
| 34 | ✅ Free | General purpose | — | — |
| 35 | ✅ Free | General purpose | — | G35 |
| 36 | ✅ Free | General purpose | — | G36 |
| 37 | ✅ Free | General purpose | — | G37 |
| 38 | ✅ Free | General purpose | — | G38 |
| 39 | ✅ Free | General purpose | — | G39 |
| 40 | ✅ Free | General purpose | — | G40 |
| 41 | ✅ Free | General purpose | — | G41 |
| 42 | ✅ Free | General purpose | — | G42 |
| 43 | ❌ RESERVED | UART TX0 (programming/debug) | — | TX0 |
| 44 | ❌ RESERVED | UART RX0 (programming/debug) | — | RX0 |
| 45 | ❌ RESERVED | Strapping pin (VDD_SPI voltage select) | — | G45 |
| 46 | ❌ RESERVED | Strapping pin (boot mode / log verbosity) | G46 | — |
| 47 | ✅ Free | General purpose | — | G47 |
| 48 | ✅ Free | General purpose, onboard LED on some boards | — | G48 |
Reserved Pins — DO NOT USE
These 7 pins are locked by the system and cannot be assigned to axes or buttons:
| GPIO | Reason |
|---|---|
| 0 | Boot strapping — pulling LOW prevents boot |
| 19 | USB D− — used by native USB-OTG |
| 20 | USB D+ — used by native USB-OTG |
| 43 | UART TX — used for serial programming and debug |
| 44 | UART RX — used for serial programming and debug |
| 45 | VDD_SPI strapping — controls flash voltage |
| 46 | Boot mode strapping — controls boot behavior |
💡 The Fabrica UI will not let you select reserved pins. They appear as red in the board diagram.
Power Pins (on board headers)
| Label | Description |
|---|---|
| 3V3 | 3.3V power output (regulated) |
| 5V | 5V power input/output (from USB or external) |
| GND | Ground (multiple pins) |
| EN | Chip Enable — pull LOW to reset the chip |
| RST | Reset button (same as EN, active LOW) |
4. Axes vs Buttons
What is an Axis?
An axis represents an analog control — a value that ranges from -100 to +100. It models continuous controls like:
| Example | Negative | Zero | Positive |
|---|---|---|---|
| Drive | Full reverse (-100) | Stop (0) | Full forward (+100) |
| Steering | Full left (-100) | Center (0) | Full right (+100) |
| Throttle | Idle (0) | — | Maximum (+100) |
| Camera pan | Left (-100) | Center (0) | Right (+100) |
Input sources from Deck Control:
- Joystick (analog stick on gamepad)
- Keyboard (WASD — mapped to -100/0/+100)
- On-screen virtual joystick (touch / mouse)
Typical hardware connected to axes:
- DC motors via motor drivers (L298N, TB6612, BTS7960)
- Servo motors (mapped to angle)
- PWM-controlled speed controllers (ESC)
What is a Button?
A button represents a digital control — a value that is either 0 (OFF) or 1 (ON). Two modes exist:
| Mode | Behavior | Example |
|---|---|---|
| Momentary | ON while pressed, OFF when released | Horn, boost, fire |
| Toggle | Click ON, click again OFF | Headlights, arm/lock |
Input sources from Deck Control:
- Keyboard keys (mapped buttons)
- Gamepad buttons
- On-screen toggle switches (touch / mouse)
Typical hardware connected to buttons:
- LEDs / LED strips (on/off or trigger animation)
- Relays (for high-power devices)
- Buzzers / Horns
- Solenoids, electromagnets
- Weapon systems (launchers, grippers)
5. How Pin Assignment Works
Step-by-step in Fabrica UI
- Go to Step 2 (Hardware Config) in the Robulus creation wizard.
- Add Axes — click
+to add a new analog axis:- Enter a name (e.g., "Drive", "TurretRotation")
- Select a GPIO pin from the dropdown
- Add Buttons — click
+to add a new digital button:- Enter a name (e.g., "Headlights", "Horn")
- Select a GPIO pin
- Choose mode:
momentaryortoggle
- The board diagram below will update in real-time:
- 🟣 Purple pins = assigned to an axis
- 🟡 Amber pins = assigned to a button
- 🔴 Red pins = reserved (cannot select)
- ⬜ Gray pins = free (available)
Conflict Prevention
- Each GPIO can be assigned to exactly one axis or button
- The dropdown only shows pins that are not yet used and not reserved
- If you reassign a pin, the old assignment is cleared first
What Happens With Your Pin Assignments
When you proceed to Step 3 (Code), the system generates #define constants:
#define PIN_DRIVE 5
#define PIN_STEERING 6
#define PIN_HEADLIGHTS 12
#define PIN_HORN 13These constants are pre-filled into the code template. You use them in your code with pinMode(), digitalWrite(), analogWrite(), etc.
When you reach Step 4 (Compile), the system:
- Injects your pin assignments into a firmware template on Core 0
- Core 0's WebSocket router knows which commands map to which pins
- When Deck Control sends
"Drive" = 75, Core 0 callsdeck("AXIS", "Drive", 75)on Core 1 — your code handles it
6. How Many Pins Can I Use?
Available GPIOs for User Hardware
Total GPIOs on ESP32-S3: 45 (GPIO 0–21, 33–48) Reserved by system: 7 (GPIO 0, 19, 20, 43, 44, 45, 46) Available for user: 38 GPIOs
Practical Limit
Most robot projects use 4–12 GPIOs. For example:
| Component | Pins Used | Example GPIOs |
|---|---|---|
| Motor Driver (L298N) — 2 motors | 4 pins (2× EN + 2× DIR) | 5, 6, 7, 8 |
| Servo (pan/tilt) | 2 pins | 9, 10 |
| LED strip (WS2812) | 1 data pin | 48 |
| Ultrasonic sensor | 2 pins (TRIG + ECHO) | 11, 12 |
| Buzzer / Horn | 1 pin | 13 |
| Headlights (LED) | 1 pin | 14 |
| Total | 11 pins | — |
7. Common Motor Driver Wiring
L298N (2 DC Motors)
L298N ESP32-S3
───── ────────
ENA ──────── GPIO 5 (PWM speed for Motor A)
IN1 ──────── GPIO 6 (Direction A1)
IN2 ──────── GPIO 7 (Direction A2)
ENB ──────── GPIO 8 (PWM speed for Motor B)
IN3 ──────── GPIO 9 (Direction B1)
IN4 ──────── GPIO 10 (Direction B2)
GND ──────── GND
5V ──────── 5V (or external battery)In Fabrica, you'd set up:
- Axis "Drive" → GPIO 5 (ENA, PWM speed)
- Axis "Steering" → GPIO 8 (ENB, PWM speed)
- The direction pins (IN1–IN4) are managed in your code
BTS7960 (High-Power, 1 Motor)
BTS7960 ESP32-S3
──────── ────────
RPWM ─────── GPIO 5 (Forward PWM)
LPWM ─────── GPIO 6 (Reverse PWM)
R_EN ─────── GPIO 7 (Enable, or tie HIGH)
L_EN ─────── GPIO 8 (Enable, or tie HIGH)
GND ─────── GNDServo Motors
Servo ESP32-S3
───── ────────
Signal ────── GPIO 9
VCC ─────── 5V (external, NOT from ESP32)
GND ─────── GND⚠ Never power servos from the ESP32's 3V3 or 5V pins. They draw too much current. Use a separate BEC or battery.
WS2812 / NeoPixel LED Strip
LED Strip ESP32-S3
───────── ────────
DIN ─────── GPIO 48 (data)
VCC ─────── 5V (external power supply)
GND ─────── GND (must share ground with ESP32)💡 Use a 330Ω resistor between GPIO and DIN. Add a 1000µF capacitor across VCC/GND of the strip.
8. GPIO Capabilities Reference
Which Pins Support PWM (LEDC)?
All GPIOs on ESP32-S3 support PWM output via the LEDC peripheral. Use analogWrite() or ledcWrite().
Which Pins Support Analog Input (ADC)?
| ADC Unit | Channels | GPIOs |
|---|---|---|
| ADC1 | 10 channels | GPIO 1–10 |
| ADC2 | 10 channels | GPIO 11–20 |
⚠ ADC2 is used by Wi-Fi. When Wi-Fi is active (always, in our case), ADC2 channels may give unreliable readings. Prefer ADC1 (GPIO 1–10) for analog sensors.
Which Pins Support Touch?
GPIO 1–14 support capacitive touch sensing.
Which Pins Support I2C?
Any GPIO can be used for I2C (software-configurable). Default I2C pins:
- SDA: GPIO 8
- SCL: GPIO 9
Which Pins Support SPI?
Any GPIO can be used for SPI (software-configurable). Default SPI:
- MOSI: GPIO 11
- MISO: GPIO 13
- SCK: GPIO 12
- CS: GPIO 10
9. Important Warnings
⚠ Voltage Levels
The ESP32-S3 operates at 3.3V logic. Connecting 5V signals directly to GPIO pins will damage the chip. Use a level shifter (e.g., TXS0108E) or a voltage divider when interfacing with 5V peripherals.
⚠ Maximum Current Per Pin
Each GPIO can source/sink approximately 40 mA. For higher loads (motors, relays, powerful LEDs), use a transistor (MOSFET/BJT) or a motor driver.
⚠ Boot Behavior
Several pins have specific states during boot:
- GPIO 0: Must be HIGH at boot (has internal pull-up)
- GPIO 45: Controls flash voltage (do not connect)
- GPIO 46: Controls boot mode (do not connect)
- GPIO 3: Has internal pull-up
If you connect external hardware to these pins, ensure it does not pull them to unexpected states during boot, or the chip may fail to start.
⚠ ADC2 and Wi-Fi
ADC2 (GPIO 11–20) cannot be reliably used for analog reads while Wi-Fi is active. Since Robulus always uses Wi-Fi for Deck Control communication, use ADC1 pins (GPIO 1–10) for any analog sensors (potentiometers, light sensors, etc.).
10. Glossary
| Term | Definition |
|---|---|
| GPIO | General Purpose Input/Output — a programmable digital pin |
| PWM | Pulse Width Modulation — simulates analog output via rapid on/off switching |
| ADC | Analog-to-Digital Converter — reads analog voltage (0–3.3V → 0–4095) |
| LEDC | LED Control peripheral on ESP32 — hardware PWM generator |
| Axis | A continuous control channel (-100 to +100) from Deck Control |
| Button | A discrete control channel (0 or 1) from Deck Control |
| Momentary | Button mode: active only while pressed |
| Toggle | Button mode: alternates state on each press |
| Motor Driver | External circuit that controls motors using small logic signals from the MCU |
| Level Shifter | Converts between 3.3V and 5V logic levels |
| BEC | Battery Eliminator Circuit — voltage regulator for servos |
| Strapping Pin | GPIO that determines chip behavior at boot (must not be externally driven) |
| Deck Control | Web-based remote control interface at deck.juvantia.org |
| Core 0 | First CPU core — runs system firmware (Wi-Fi, WebSocket) — user cannot modify |
| Core 1 | Second CPU core — runs user code (your logic) |
| deck() | The callback function on Core 1 that receives commands from Deck Control |
| Fabrica | Web portal for configuring, coding, compiling, and flashing Robulus units |