Skip to main content

๐Ÿ”ง Arduino & ESP32 Setup

DEJA.js ships three Arduino-family firmware variants that all share the same io/scripts/lib/bundle.ts builder, the same C++ command handlers, and the same DEJA Cloud configuration pipeline. Pick the variant that matches your hardware:

Device typeBoardTransportSketch source
๐ŸŸข deja-arduinoArduino Mega 2560 (or compatible AVR)USB serial @ 115200io/src/deja-arduino/
๐ŸŸ  deja-esp32ESP32 Dev ModuleUSB serial @ 115200io/src/deja-arduino/ (shared sketch)
๐Ÿ›œ deja-esp32-wifiESP32 Dev ModuleWiFi + MQTTio/src/deja-esp32-wifi/

๐Ÿค deja-esp32 reuses the deja-arduino sketch โ€” same JSON-over-serial protocol, just compiled for ESP32 hardware with a different FQBN and a faster upload speed (460800 baud).

๐Ÿ›œ deja-esp32-wifi is the wireless variant โ€” same ESP32 hardware, but it talks to the DEJA Server over MQTT instead of USB serial. See Pico W Setup for the Raspberry Pi Pico W equivalent (deja-mqtt), which uses the same MQTT topology.


๐Ÿ› ๏ธ Hardware Requirements

๐ŸŸข deja-arduino (Arduino Mega)

  • Arduino Uno, Mega, or Nano (any ATmega-based board โ€” Mega 2560 recommended for higher pin counts)
  • USB cable (Type-A to Type-B for Uno/Mega, Mini-USB for Nano)
  • Adafruit PCA9685 16-Channel PWM Servo Driver (optional, for servo-driven turnouts)
  • Jumper wires for connecting outputs and sensors

๐ŸŸ  deja-esp32 (ESP32 over USB)

  • ESP32 Dev Module (any standard ESP32 dev board with USB)
  • USB cable (typically USB-C or Micro-USB depending on the board)
  • Adafruit PCA9685 (optional, for servos)

๐Ÿ›œ deja-esp32-wifi (ESP32 over WiFi/MQTT)

  • ESP32 Dev Module (same hardware as deja-esp32)
  • WiFi network reachable from the device
  • MQTT broker (Mosquitto recommended) running somewhere on the same network as the DEJA Server
  • USB cable for the initial flash โ€” after that the board can run on any 5V power source

๐Ÿ”Œ Wiring the PCA9685

If you're using servo-driven turnouts, connect the PCA9685 to your board over I2C:

PCA9685 PinArduino MegaESP32 (default)
VCC5V3V3
GNDGNDGND
SDA20GPIO 21
SCL21GPIO 22

Power the servo rail separately with a 5โ€“6V power supply โ€” do not power servos from the board's onboard regulator.


โš™๏ธ Firmware Configuration

The deja deploy wizard generates config.h from your DEJA Cloud device entry, but you can also create one by hand from config.default.h. The shape differs slightly between the USB-serial variants and the WiFi variant.

๐ŸŸข๐ŸŸ  deja-arduino / deja-esp32 โ€” io/src/deja-arduino/config.h

// ๐Ÿท๏ธ Device identity
#define DEVICE_ID "my-arduino-device"

// ๐Ÿšฆ Feature toggles โ€” enable what your hardware supports
#define ENABLE_PWM true        // ๐ŸŽ›๏ธ PCA9685 servo driver
#define ENABLE_OUTPUTS true    // ๐Ÿ’ก Digital output pins
#define ENABLE_SIGNALS true    // ๐Ÿšฆ Signal head outputs
#define ENABLE_SENSORS true    // ๐Ÿ“ก Sensor input pins
#define ENABLE_TURNOUTS true   // ๐Ÿ”ง Servo-driven turnouts

// ๐Ÿช› Pin assignments
int OUTPINS[] = {8, 9, 10, 11};           // GPIO pins for digital outputs
int SIGNALPINS[] = {4, 5, 6, 7};          // GPIO pins for signal heads
int SENSORPINS[] = {A0, A1, A2};          // GPIO pins for sensors

๐Ÿ›œ deja-esp32-wifi โ€” io/src/deja-esp32-wifi/config.h

The WiFi variant adds WiFi/MQTT credentials that get baked in at build time. The deja deploy wizard prompts for these and generateEsp32WifiConfig() writes them in:

// ๐Ÿ“ถ WiFi credentials
#define WIFI_SSID "YourNetwork"
#define WIFI_PASSWORD "YourPassword"

// ๐Ÿ“ฌ MQTT broker
#define MQTT_BROKER "192.168.1.100"
#define MQTT_PORT 1883
#define MQTT_USERNAME ""
#define MQTT_PASSWORD ""

// ๐Ÿท๏ธ Device identity
#define DEVICE_ID "my-esp32-wifi"
#define LAYOUT_ID "tamarack"
#define TOPIC_ID "DEJA"

// ๐Ÿšฆ Feature toggles โ€” same semantics as deja-arduino
#define ENABLE_PWM true
#define ENABLE_OUTPUTS true
#define ENABLE_SIGNALS true
#define ENABLE_SENSORS true
#define ENABLE_TURNOUTS true

// ๐Ÿช› Pin assignments
int OUTPINS[] = {18, 19, 21, 22};
int SIGNALPINS[] = {25, 26, 27, 32};
int SENSORPINS[] = {34, 35, 36, 39};

๐Ÿ›œ Unlike the Pico W (which reads settings.toml at runtime), the ESP32 WiFi firmware bakes credentials into config.h at compile time. If you change WiFi or MQTT credentials, you have to re-flash the device.

๐Ÿ”ง Turnout Configuration

Turnouts are defined as TurnoutPulser objects with a servo channel, closed angle, and thrown angle. This is identical for all three Arduino-family variants:

TurnoutPulser turnouts[] = {
  TurnoutPulser(0, 45, 135),   // ๐Ÿ”ง Servo channel 0: 45ยฐ closed, 135ยฐ thrown
  TurnoutPulser(1, 50, 130),   // ๐Ÿ”ง Servo channel 1: 50ยฐ closed, 130ยฐ thrown
};

See Configuration Reference for the full list of config.h fields per variant.


๐Ÿš€ Flashing the Firmware

The easiest path is the deploy wizard:

cd io
pnpm deploy

The wizard auto-detects connected boards, fetches your device config from Firebase, generates config.h, and uses arduino-cli to compile and upload. For deja-esp32-wifi and deja-mqtt it also prompts for WiFi/MQTT credentials.

If you'd rather flash by hand, every bundle drops out a self-contained directory at io/dist/<layoutId>/arduino/<deviceId>/ that works with PlatformIO, Arduino CLI, or the Arduino IDE. The exact CLI commands depend on the device type โ€” these match getCliDeployCommands() in packages/modules/device-config/cli-commands.ts (the single source of truth shown in DEPLOYMENT.md and the Cloud app device details page):

๐ŸŸข deja-arduino

cd io/dist/<layoutId>/arduino/<deviceId>

# Option A: PlatformIO
platformio run -e megaatmega2560 --target upload --upload-port /dev/cu.usbserial-*

# Option B: Arduino CLI
arduino-cli compile --fqbn arduino:avr:mega:cpu=atmega2560 deja-arduino && \
  arduino-cli upload -p /dev/cu.usbserial-* --fqbn arduino:avr:mega:cpu=atmega2560 deja-arduino

# Option C: Arduino IDE
# File โ†’ Open โ†’ deja-arduino/deja-arduino.ino
# Tools โ†’ Board โ†’ Arduino AVR Boards โ†’ Arduino Mega or Mega 2560
# Tools โ†’ Processor โ†’ ATmega2560 (Mega 2560)

๐ŸŸ  deja-esp32

cd io/dist/<layoutId>/arduino/<deviceId>

# Option A: PlatformIO
platformio run -e esp32dev --target upload --upload-port /dev/cu.usbserial-*

# Option B: Arduino CLI
arduino-cli compile --fqbn esp32:esp32:esp32 \
  --build-property "compiler.cpp.extra_flags=-std=c++17" deja-arduino && \
  arduino-cli upload -p /dev/cu.usbserial-* \
  --fqbn esp32:esp32:esp32:UploadSpeed=460800 deja-arduino

# Option C: Arduino IDE
# File โ†’ Open โ†’ deja-arduino/deja-arduino.ino
# Tools โ†’ Board โ†’ ESP32 Arduino โ†’ ESP32 Dev Module
# Tools โ†’ Upload Speed โ†’ 460800

๐Ÿ›œ deja-esp32-wifi

cd io/dist/<layoutId>/arduino/<deviceId>

# Option A: PlatformIO
platformio run -e esp32dev --target upload --upload-port /dev/cu.usbserial-*

# Option B: Arduino CLI
arduino-cli compile --fqbn esp32:esp32:esp32 \
  --build-property "compiler.cpp.extra_flags=-std=c++17" deja-esp32-wifi && \
  arduino-cli upload -p /dev/cu.usbserial-* \
  --fqbn esp32:esp32:esp32:UploadSpeed=460800 deja-esp32-wifi

# Option C: Arduino IDE
# File โ†’ Open โ†’ deja-esp32-wifi/deja-esp32-wifi.ino
# Tools โ†’ Board โ†’ ESP32 Arduino โ†’ ESP32 Dev Module
# Tools โ†’ Upload Speed โ†’ 460800

๐Ÿ›œ Before flashing deja-esp32-wifi by hand: confirm WIFI_SSID, WIFI_PASSWORD, MQTT_BROKER, DEVICE_ID, LAYOUT_ID, and TOPIC_ID are set correctly in deja-esp32-wifi/config.h. The deploy wizard bakes these in automatically; non-interactive pnpm build:firmware runs leave them empty.


๐Ÿ”Œ Connecting to the Server

๐ŸŸข๐ŸŸ  USB-serial variants (deja-arduino / deja-esp32)

  1. Plug the board into the server machine via USB
  2. In the Cloud app, register a device with the matching type (deja-arduino or deja-esp32) and your DEVICE_ID
  3. The DEJA Server auto-detects the serial port and connects at 115200 baud
  4. Open the Monitor app to verify the device appears and responds to commands

๐Ÿ›œ deja-esp32-wifi

  1. Make sure your MQTT broker is running and reachable on the IP you set in config.h
  2. Make sure the DEJA Server has ENABLE_MQTT=true in its .env
  3. Power on the ESP32 โ€” it connects to WiFi, subscribes to DEJA/{layoutId}/{deviceId}, and publishes a status message to โ€ฆ/messages
  4. In the Cloud app, register a device with type deja-esp32-wifi and the matching DEVICE_ID
  5. Open the Monitor app to verify the device shows as connected

๐Ÿ“จ Command Format

๐ŸŸข๐ŸŸ  USB-serial variants

deja-arduino and deja-esp32 receive JSON arrays over serial at 115200 baud:

[
  { "action": "pin", "payload": { "pin": 8, "state": 1 } },
  { "action": "servo", "payload": { "servo": 0, "value": 90, "current": 45 } },
  { "action": "turnout", "payload": { "turnout": 0, "state": true } }
]

๐Ÿ›œ deja-esp32-wifi

deja-esp32-wifi receives single JSON objects over MQTT, matching the Pico W (deja-mqtt) format:

{
  "action": "pin",
  "device": "my-esp32-wifi",
  "payload": { "pin": 18, "state": 1 }
}

The firmware filters by the device field and ignores messages intended for other devices on the same topic. The same pin / servo / turnout / effects handlers run regardless of transport โ€” see the Command Reference for all supported actions.


๐Ÿ“š Next Steps