๐ง 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 type | Board | Transport | Sketch source |
|---|---|---|---|
๐ข deja-arduino | Arduino Mega 2560 (or compatible AVR) | USB serial @ 115200 | io/src/deja-arduino/ |
๐ deja-esp32 | ESP32 Dev Module | USB serial @ 115200 | io/src/deja-arduino/ (shared sketch) |
๐ deja-esp32-wifi | ESP32 Dev Module | WiFi + MQTT | io/src/deja-esp32-wifi/ |
๐ค
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
- 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 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, 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.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:
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-wifiby hand: confirmWIFI_SSID,WIFI_PASSWORD,MQTT_BROKER,DEVICE_ID,LAYOUT_ID, andTOPIC_IDare set correctly indeja-esp32-wifi/config.h. The deploy wizard bakes these in automatically; non-interactivepnpm build:firmwareruns leave them empty.
๐ Connecting to the Server
๐ข๐ USB-serial variants (deja-arduino / deja-esp32)
- Plug the board into the server machine via USB
- In the Cloud app, 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 the Monitor app to verify the device appears and responds to 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 the Cloud app, register a device with type
deja-esp32-wifiand the matchingDEVICE_ID - 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
- ๐ 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