🔧 Arduino & ESP32 Setup
DEJA ships three Arduino-family firmware variants that all share the same C++ command handlers and the same DEJA Cloud configuration pipeline. Pick the variant that matches your hardware:
| Device type | Board | Transport |
|---|---|---|
🟢 deja-arduino |
Arduino Mega 2560 (or compatible AVR) | USB serial @ 115200 |
🟠 deja-esp32 |
ESP32 Dev Module | USB serial @ 115200 |
🛜 deja-esp32-wifi |
ESP32 Dev Module | WiFi + MQTT |
🤝
deja-esp32reuses thedeja-arduinosketch — same JSON-over-serial protocol, just compiled for ESP32 hardware with a different FQBN and a faster upload speed (460800 baud).🛜
deja-esp32-wifiis 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
- DEJA Server running on the same network — it provides the MQTT broker (port 1883)
- 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 Pin | Arduino Mega | ESP32 (default) |
|---|---|---|
| VCC | 5V | 3V3 |
| GND | GND | GND |
| SDA | 20 | GPIO 21 |
| SCL | 21 | GPIO 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 automatically — you shouldn't normally need to hand-edit it. The shape differs slightly between the USB-serial variants and the WiFi variant; this reference is here for when you want to understand (or tweak) what got generated.
🟢🟠 deja-arduino / deja-esp32 — 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 — config.h
The WiFi variant adds WiFi/MQTT credentials that get baked in at build time. The deja deploy wizard prompts for these and writes them into the generated file:
// 📶 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.tomlat runtime), the ESP32 WiFi firmware bakes credentials intoconfig.hat 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:
deja deploy
The wizard auto-detects connected boards, fetches your device config from DEJA Cloud, generates config.h, and uses arduino-cli to compile and upload. For deja-esp32-wifi it also prompts for WiFi/MQTT credentials.
The first run asks before downloading the Arduino tools into ~/.deja/tools (see What deja deploy installs). On Linux, if the upload says permission denied, add yourself to the dialout group (sudo usermod -aG dialout $USER) and log out and back in.
If you'd rather flash the board yourself, deja deploy also drops a self-contained bundle you can open in PlatformIO, Arduino CLI, or the Arduino IDE. The exact commands for your board are shown on the device's page in Throttle (Devices → the device) and in the bundle's own DEPLOYMENT.md — copy them from there rather than guessing, since they're generated per device type.
🛜 Before flashing
deja-esp32-wifiby hand: confirmWIFI_SSID,WIFI_PASSWORD,MQTT_BROKER,DEVICE_ID,LAYOUT_ID, andTOPIC_IDare set correctly in the generatedconfig.h. The deploy wizard bakes these in automatically when it runs interactively.
🔌 Connecting to the Server
🟢🟠 USB-serial variants (deja-arduino / deja-esp32)
- Plug the board into the server machine via USB
- In Throttle, open Devices and register a device with the matching type (
deja-arduinoordeja-esp32) and yourDEVICE_ID - The DEJA Server auto-detects the serial port and connects at 115200 baud
- Open Throttle → Devices and tap the device — its serial log shows it answering commands
🛜 deja-esp32-wifi
- Make sure your MQTT broker is running and reachable on the IP you set in
config.h - Make sure the DEJA Server has
ENABLE_MQTT=truein its.env - Power on the ESP32 — it connects to WiFi, subscribes to
DEJA/{layoutId}/{deviceId}, and publishes a status message to…/messages - In Throttle, open Devices and register a device with type
deja-esp32-wifiand the matchingDEVICE_ID - Open Throttle → Devices 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, "profile": "medium" } },
{ "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
- 🚀 Deploy to Devices — full walkthrough of the
deja deploywizard - 📋 Configuration Reference — every
config.h/settings.tomlfield per variant - 📡 Protocol Details — serial + MQTT wire formats
- 🍓 Pico W Setup — the CircuitPython MQTT alternative to
deja-esp32-wifi - 🔧 Building Custom Devices — bring your own MQTT hardware