Skip to content

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

PropertyValue
ChipESP32-S3 (Xtensa LX7, dual-core)
Clock240 MHz
RAM512 KB SRAM + 8 MB PSRAM (board-dependent)
Flash16 MB (board-dependent)
Wi-Fi802.11 b/g/n 2.4 GHz
USBNative USB-OTG + UART
ADC2× 12-bit SAR ADC (up to 20 channels)
DACNone (use PWM / LEDC instead)
PWM / LEDC8 channels, 14+ bit resolution
I2C2 buses
SPI4 buses
UART3 interfaces
GPIO count45 (GPIO 0–21, 33–48; GPIO 22–32 do not exist)
Operating voltage3.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

GPIOAvailable?NotesBoard Label (Left)Board Label (Right)
0❌ RESERVEDBoot strapping pin. Internal pull-up. Must not be LOW at boot.G0
1✅ FreeADC1_CH0
2✅ FreeADC1_CH1G2
3✅ FreeADC1_CH2G3
4✅ FreeADC1_CH3G4
5✅ FreeADC1_CH4G5
6✅ FreeADC1_CH5G6
7✅ FreeADC1_CH6G7
8✅ FreeADC1_CH7G8
9✅ FreeADC1_CH8G9
10✅ FreeADC1_CH9, SPIG10
11✅ FreeADC2_CH0, SPIG11
12✅ FreeADC2_CH1, SPIG12
13✅ FreeADC2_CH2, SPIG13
14✅ FreeADC2_CH3G14
15✅ FreeADC2_CH4G15
16✅ FreeADC2_CH5G16
17✅ FreeADC2_CH6G17
18✅ FreeADC2_CH7G18
19❌ RESERVEDUSB D− (native USB-OTG)G19
20❌ RESERVEDUSB D+ (native USB-OTG)G20
21✅ FreeGeneral purposeG21
22–32❌ N/ADo not exist on ESP32-S3
33✅ FreeGeneral purpose
34✅ FreeGeneral purpose
35✅ FreeGeneral purposeG35
36✅ FreeGeneral purposeG36
37✅ FreeGeneral purposeG37
38✅ FreeGeneral purposeG38
39✅ FreeGeneral purposeG39
40✅ FreeGeneral purposeG40
41✅ FreeGeneral purposeG41
42✅ FreeGeneral purposeG42
43❌ RESERVEDUART TX0 (programming/debug)TX0
44❌ RESERVEDUART RX0 (programming/debug)RX0
45❌ RESERVEDStrapping pin (VDD_SPI voltage select)G45
46❌ RESERVEDStrapping pin (boot mode / log verbosity)G46
47✅ FreeGeneral purposeG47
48✅ FreeGeneral purpose, onboard LED on some boardsG48

Reserved Pins — DO NOT USE

These 7 pins are locked by the system and cannot be assigned to axes or buttons:

GPIOReason
0Boot strapping — pulling LOW prevents boot
19USB D− — used by native USB-OTG
20USB D+ — used by native USB-OTG
43UART TX — used for serial programming and debug
44UART RX — used for serial programming and debug
45VDD_SPI strapping — controls flash voltage
46Boot 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)

LabelDescription
3V33.3V power output (regulated)
5V5V power input/output (from USB or external)
GNDGround (multiple pins)
ENChip Enable — pull LOW to reset the chip
RSTReset 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:

ExampleNegativeZeroPositive
DriveFull reverse (-100)Stop (0)Full forward (+100)
SteeringFull left (-100)Center (0)Full right (+100)
ThrottleIdle (0)Maximum (+100)
Camera panLeft (-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:

ModeBehaviorExample
MomentaryON while pressed, OFF when releasedHorn, boost, fire
ToggleClick ON, click again OFFHeadlights, 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

  1. Go to Step 2 (Hardware Config) in the Robulus creation wizard.
  2. Add Axes — click + to add a new analog axis:
    • Enter a name (e.g., "Drive", "TurretRotation")
    • Select a GPIO pin from the dropdown
  3. Add Buttons — click + to add a new digital button:
    • Enter a name (e.g., "Headlights", "Horn")
    • Select a GPIO pin
    • Choose mode: momentary or toggle
  4. 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:

cpp
#define PIN_DRIVE              5
#define PIN_STEERING           6
#define PIN_HEADLIGHTS         12
#define PIN_HORN               13

These 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:

  1. Injects your pin assignments into a firmware template on Core 0
  2. Core 0's WebSocket router knows which commands map to which pins
  3. When Deck Control sends "Drive" = 75, Core 0 calls deck("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:

ComponentPins UsedExample GPIOs
Motor Driver (L298N) — 2 motors4 pins (2× EN + 2× DIR)5, 6, 7, 8
Servo (pan/tilt)2 pins9, 10
LED strip (WS2812)1 data pin48
Ultrasonic sensor2 pins (TRIG + ECHO)11, 12
Buzzer / Horn1 pin13
Headlights (LED)1 pin14
Total11 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   ───────  GND

Servo 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 UnitChannelsGPIOs
ADC110 channelsGPIO 1–10
ADC210 channelsGPIO 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

TermDefinition
GPIOGeneral Purpose Input/Output — a programmable digital pin
PWMPulse Width Modulation — simulates analog output via rapid on/off switching
ADCAnalog-to-Digital Converter — reads analog voltage (0–3.3V → 0–4095)
LEDCLED Control peripheral on ESP32 — hardware PWM generator
AxisA continuous control channel (-100 to +100) from Deck Control
ButtonA discrete control channel (0 or 1) from Deck Control
MomentaryButton mode: active only while pressed
ToggleButton mode: alternates state on each press
Motor DriverExternal circuit that controls motors using small logic signals from the MCU
Level ShifterConverts between 3.3V and 5V logic levels
BECBattery Eliminator Circuit — voltage regulator for servos
Strapping PinGPIO that determines chip behavior at boot (must not be externally driven)
Deck ControlWeb-based remote control interface at deck.juvantia.org
Core 0First CPU core — runs system firmware (Wi-Fi, WebSocket) — user cannot modify
Core 1Second CPU core — runs user code (your logic)
deck()The callback function on Core 1 that receives commands from Deck Control
FabricaWeb portal for configuring, coding, compiling, and flashing Robulus units

Operated by Juvantia Foundation