Skip to content

The DMX512 receiver that actually works with Arduino Core 3.0+ and ESP32-S3! Full 512 channels, automatic break detection, zero packet loss. No more compatibility headaches - just reliable DMX for your lighting projects.

License

Notifications You must be signed in to change notification settings

TimRosener/ESP32S3DMX

Repository files navigation

ESP32S3DMX Library

Arduino License: LGPL v2.1 ESP32

Professional DMX512 receiver library for ESP32 microcontrollers with Arduino Core 3.0+ support.

Table of Contents

Features

Feature Status
Full 512 channel support
Arduino Core 3.0+ compatible
Automatic break detection
Packet statistics
Zero-copy channel reading
Thread-safe operation
Multi-core support (ESP32)
Partial universe support
Multiple UART support
DMX transmission
RDM support

Performance Specifications

  • Packet Rate: 44-50 Hz (standard DMX)
  • Latency: < 1ms from packet reception to data availability
  • Memory Usage: ~1.5KB RAM
  • CPU Usage: < 1% at 50Hz packet rate

Requirements

Software

  • Arduino IDE 1.8.13+ or PlatformIO
  • ESP32 Arduino Core 3.0.0 or later
  • No additional library dependencies

Hardware

  • ESP32, ESP32-S2, or ESP32-S3 development board
  • RS485 transceiver module (MAX485, SN75176B, or equivalent)
  • DMX512 signal source

Tested Configurations

Board Core Version Status
ESP32 DevKitC 3.0.0 ✅ Tested
ESP32-S2 3.0.0 ✅ Tested
ESP32-S3 3.3.0 ✅ Tested

Installation

Method 1: Arduino Library Manager (Recommended)

  1. Open Arduino IDE
  2. Go to ToolsManage Libraries...
  3. Search for "ESP32S3DMX"
  4. Click Install

Method 2: Manual Installation

cd ~/Documents/Arduino/libraries
git clone https://github.com/yourusername/ESP32S3DMX.git

Method 3: PlatformIO

Add to platformio.ini:

lib_deps = 
    https://github.com/yourusername/ESP32S3DMX.git

Quick Start

#include <ESP32S3DMX.h>

ESP32S3DMX dmx;

void setup() {
    Serial.begin(115200);
    dmx.begin();  // Initialize with default pins
}

void loop() {
    if (dmx.isConnected()) {
        uint8_t brightness = dmx.read(1);  // Read channel 1
        Serial.printf("Channel 1: %d\n", brightness);
    }
    delay(100);
}

Hardware Setup

Wiring Diagram

ESP32        RS485 Module     DMX Connector
------       ------------     -------------
GPIO 6  <--- RO               
GPIO 5  ---> DE/RE            
GPIO 4  ---> DI (NC)          
3V3/5V  ---> VCC              
GND     ---> GND -----------> Pin 1 (GND)
              A  -----------> Pin 3 (Data+)
              B  -----------> Pin 2 (Data-)

Important Notes

  • Connect DE and RE pins together for receive-only operation
  • Some RS485 modules require 5V power (check specifications)
  • DMX uses XLR 5-pin or 3-pin connectors
  • 120Ω termination may be required for long cable runs

Pin Configurations by Board

Board Default RX Default TX Default Enable Recommended UART
ESP32 GPIO 16 GPIO 17 GPIO 4 UART2
ESP32-S2 GPIO 6 GPIO 4 GPIO 5 UART1
ESP32-S3 GPIO 6 GPIO 4 GPIO 5 UART2

API Documentation

Class: ESP32S3DMX

Constructor

ESP32S3DMX()

Creates a new DMX receiver instance. Only one instance should be created per UART.

Methods

begin()
void begin(uint8_t uart_num = 2, int rx_pin = 6, int tx_pin = 4, int enable_pin = 5)

Initializes the DMX receiver.

Parameters:

  • uart_num: UART peripheral to use (1 or 2, not 0 on ESP32-S3)
  • rx_pin: GPIO pin connected to RS485 RO (receiver output)
  • tx_pin: GPIO pin connected to RS485 DI (driver input) - unused for receive
  • enable_pin: GPIO pin connected to RS485 DE/RE (direction control)

Example:

dmx.begin();  // Use defaults
dmx.begin(2, 16, 17, 4);  // Custom pins
end()
void end()

Stops the DMX receiver and releases resources.

read()
uint8_t read(uint16_t channel)

Reads a single DMX channel value. Thread-safe.

Parameters:

  • channel: DMX channel number (1-512)

Returns: Channel value (0-255), or 0 if channel is invalid or no signal

Example:

uint8_t dimmer = dmx.read(1);
uint8_t red = dmx.read(2);
readChannels()
uint16_t readChannels(uint8_t* buffer, uint16_t start_channel, uint16_t count)

Reads multiple consecutive channels efficiently. Thread-safe.

Parameters:

  • buffer: Array to store channel values
  • start_channel: First channel to read (1-512)
  • count: Number of channels to read

Returns: Number of channels actually read

Example:

uint8_t rgbw[4];
dmx.readChannels(rgbw, 10, 4);  // Read channels 10-13
isConnected()
bool isConnected()

Checks if receiving valid DMX signal.

Returns: true if DMX received within last second, false otherwise

getPacketRate()
float getPacketRate()

Gets the current packet reception rate.

Returns: Packets per second (0.0 if no signal)

Additional Methods
Method Returns Description
getPacketCount() uint32_t Total valid packets received
getErrorCount() uint32_t Total reception errors
timeSinceLastPacket() uint32_t Milliseconds since last packet
getLastPacketSize() uint16_t Size of last packet (bytes)
getBuffer() const uint8_t* Direct access to DMX buffer

Examples

BasicReceive

Simple DMX channel display - perfect for getting started.

// Displays first 8 channels continuously

ChannelMonitor

Monitor specific channels and trigger actions on changes.

// Detect changes, thresholds, and mode switches

ChannelViewer

Interactive channel viewer with Serial Monitor commands.

// View any range of channels interactively

Technical Details

DMX512 Protocol Implementation

  • Baud Rate: 250,000 bps
  • Format: 8 data bits, no parity, 2 stop bits (8N2)
  • Break: Minimum 88μs (detected via UART error)
  • MAB: Minimum 8μs (tolerates down to 2μs)
  • Start Code: 0x00 (null start code only)

ESP32-S3 UART Behavior

The ESP32-S3 UART hardware captures an extra byte at the beginning of the break signal. This library automatically compensates for this behavior, ensuring correct channel mapping.

Memory Layout

dmxData[0]   = Start code (0x00)
dmxData[1]   = Channel 1
dmxData[2]   = Channel 2
...
dmxData[512] = Channel 512

Thread Safety and Multi-Core Support

Thread Safety: ✅ Fully Thread-Safe

The ESP32S3DMX library is designed to be thread-safe and can be safely used in multi-threaded environments:

Safe Operations

  • Reading channels from multiple threads/tasks simultaneously
  • Calling begin() from any core (0 or 1)
  • Accessing data while reception is ongoing
  • Using from FreeRTOS tasks without additional synchronization

Implementation Details

  • Atomic Operations: Critical sections protected with noInterrupts()/interrupts()
  • Volatile Buffers: Ensures memory coherency between cores
  • Double Buffering: Separate receive and read buffers prevent corruption
  • No Dynamic Memory: All buffers are statically allocated

Multi-Core Support: ✅ Works on Either Core

// Example: Running DMX on Core 1
void dmxTask(void* param) {
    dmx.begin();  // Initialize on Core 1
    
    while(1) {
        if (dmx.isConnected()) {
            uint8_t value = dmx.read(1);
            // Process DMX data...
        }
        vTaskDelay(1);
    }
}

void setup() {
    xTaskCreatePinnedToCore(dmxTask, "DMX", 4096, NULL, 1, NULL, 1);
}

Usage Examples

Multi-Task Example

// Task 1: Read lighting channels
void lightingTask(void* param) {
    while(1) {
        uint8_t brightness = dmx.read(1);
        uint8_t color = dmx.read(2);
        // Update lights...
        vTaskDelay(20);
    }
}

// Task 2: Read effects channels
void effectsTask(void* param) {
    while(1) {
        uint8_t effect = dmx.read(10);
        uint8_t speed = dmx.read(11);
        // Update effects...
        vTaskDelay(50);
    }
}

Core Assignment

  • UART interrupts run on the core that calls begin()
  • DMX data can be read from any core
  • No core affinity requirements
  • Default scheduler assignment works perfectly

Performance Considerations

  • Interrupt disable time: < 100μs (minimal impact)
  • Safe for real-time applications
  • No mutex overhead for read operations
  • Zero-copy design for efficiency

Troubleshooting

Common Issues and Solutions

Problem Possible Causes Solutions
No signal detected Wiring issue Check connections, verify power
Wrong polarity Swap A/B connections
No DMX source Verify console is outputting
Wrong channel values Universe size Check console universe settings
Channel offset Verify channel numbering
Intermittent signal Termination Add 120Ω terminator
Cable quality Use DMX-rated cable
Compilation error Core version Update to Core 3.0+

Debug Checklist

  1. ✓ RS485 module powered (LED indicator?)
  2. ✓ DE/RE pins connected together and to GPIO
  3. ✓ A/B polarity correct (try swapping)
  4. ✓ DMX source actively transmitting
  5. ✓ Using UART1 or UART2 (not UART0)

Contributing

We welcome contributions! Please see our Contributing Guidelines.

Development Setup

git clone https://github.com/yourusername/ESP32S3DMX.git
cd ESP32S3DMX
# Create feature branch
git checkout -b feature/your-feature

Code Style

  • Use 4 spaces for indentation
  • Follow Arduino style guide
  • Document all public methods
  • Include examples for new features

License

Dual License Notice

This library is available under a dual license model:

Option 1: Open Source License (LGPL v2.1)

For open source projects and non-commercial use, this library is licensed under the GNU Lesser General Public License v2.1.

Option 2: Commercial License

For use in commercial products or closed-source applications, a commercial license is required.

Commercial licenses include:

  • Rights to use in commercial products
  • Ability to create closed-source derivatives
  • Priority support
  • Custom feature development options

To obtain a commercial license, contact: [your.email@example.com]

Note: If you're unsure which license applies to your use case, please reach out for clarification.

Acknowledgments

  • ESP32 Arduino Core team for Core 3.0
  • DMX512 specification by ESTA
  • RS485 transceiver manufacturers
  • All contributors and testers

Need Help? Open an issue on GitHub.

About

The DMX512 receiver that actually works with Arduino Core 3.0+ and ESP32-S3! Full 512 channels, automatic break detection, zero packet loss. No more compatibility headaches - just reliable DMX for your lighting projects.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published