-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
DMX improvements and configuration option. #5216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
8690657
b1664af
3e3d6d6
78a8631
d2d37e8
6d60695
e9ec9fa
4625481
4587a7c
4f903c0
dbf6788
6747fb5
193b8e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,21 +3,36 @@ | |
| /* | ||
| * Support for DMX output via serial (e.g. MAX485). | ||
| * Change the output pin in src/dependencies/ESPDMX.cpp, if needed (ESP8266) | ||
| * Change the output pin in src/dependencies/SparkFunDMX.cpp, if needed (ESP32) | ||
| * Change the output pin in src/dependencies/dmx/EspDmxOutput.cpp, if needed (ESP32/S3) | ||
| * ESP8266 Library from: | ||
| * https://github.com/Rickgg/ESP-Dmx | ||
| * ESP32 Library from: | ||
| * https://github.com/sparkfun/SparkFunDMX | ||
| * https://github.com/someweisguy/esp_dmx | ||
| */ | ||
|
|
||
| #ifdef WLED_ENABLE_DMX | ||
|
|
||
| #define MAX_DMX_RATE 44 // max DMX update rate in Hz | ||
|
|
||
| void handleDMXOutput() | ||
| { | ||
| // don't act, when in DMX Proxy mode | ||
| if (e131ProxyUniverse != 0) return; | ||
|
|
||
| // Ensure segments exist before accessing strip data | ||
| if (strip.getSegmentsNum() == 0) return; | ||
|
|
||
| // Rate limiting | ||
| static unsigned long last_dmx_time = 0; | ||
| const unsigned long dmxFrameTime = (1000UL + MAX_DMX_RATE - 1) / MAX_DMX_RATE; // Subtract 1 to round up | ||
| if (millis() - last_dmx_time < dmxFrameTime) return; | ||
|
Stijn-Jacobs marked this conversation as resolved.
|
||
|
|
||
| uint8_t brightness = strip.getBrightness(); | ||
|
|
||
| // Skip DMX entirely if strip is off | ||
| if (brightness == 0) return; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some fixtures have a manual mode in case they don't receive a DMX signal. For example they could jump to a static color, where they should be off. This line should be removed IMO.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm this is an interesting one, I agree with you. If you have DMX on in the build, we can assume you intend to use it with DMX and we can always output zero values to the bus, even if this means impacting performance negatively.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good spot @Mdbelen I totally agree |
||
|
|
||
| last_dmx_time = millis(); | ||
|
|
||
| bool calc_brightness = true; | ||
|
|
||
|
|
@@ -28,9 +43,15 @@ void handleDMXOutput() | |
| } | ||
|
|
||
| uint16_t len = strip.getLengthTotal(); | ||
| for (int i = DMXStartLED; i < len; i++) { // uses the amount of LEDs as fixture count | ||
|
|
||
| uint32_t in = strip.getPixelColor(i); // get the colors for the individual fixtures as suggested by Aircoookie in issue #462 | ||
| if (len == 0) return; | ||
|
|
||
| // OPTIMIZATION: Only process the LEDs that actually need DMX output | ||
| // Limit to configured number of fixtures instead of processing all LEDs | ||
| uint16_t dmxEndLED = DMXStartLED + DMXNumFixtures; | ||
| if (dmxEndLED > len) dmxEndLED = len; | ||
|
|
||
| for (int i = DMXStartLED; i < dmxEndLED; i++) { | ||
| uint32_t in = strip.getPixelColor(i); | ||
| byte w = W(in); | ||
| byte r = R(in); | ||
| byte g = G(in); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /****************************************************************************** | ||
| * EspDmxOutput.cpp | ||
| * | ||
| * DMX output via `esp_dmx` on ESP32. | ||
| * Keeps the minimal API WLED uses: initWrite(), write(), update(). | ||
| ******************************************************************************/ | ||
|
|
||
| /* ----- LIBRARIES ----- */ | ||
| #if defined(ARDUINO_ARCH_ESP32) | ||
|
|
||
| #include <Arduino.h> | ||
| #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) | ||
|
|
||
| #include "EspDmxOutput.h" | ||
| #include <esp_dmx.h> | ||
|
|
||
| #define dmxMaxChannel 512 | ||
| #define defaultMax 32 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a dead define, as DMXOutput::init calls EspDmxOutput::initWrite always with 512. Should be removed.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well 44hz is the actual hard limit of what the spec can handle. The limiting was there in place to increase performance dramatically before using the old driver, and thus was ported from there. It should have less impact right now, but will still have some negative impact on the actual framerate you will achieve on a microcontroller. I think at the moment fixtures with different channel numbers are not really properly supported globally (while you ofcourse can set it to the value of the fixture with the highest fixture count, and setup your channels properly on the fixtures). I think its a good point you mention, I'll also do some more testing with 512 channels and see if it impacts the framerate as it did before. |
||
|
|
||
| // Some new MCUs (-S2, -C3) don't have HardwareSerial(2) | ||
| #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) | ||
| #if SOC_UART_NUM < 3 | ||
| #error DMX output is not possible on your MCU, as it does not have HardwareSerial(2) | ||
| #endif | ||
| #endif | ||
|
|
||
| static constexpr dmx_port_t dmxPort = DMX_NUM_2; | ||
|
Comment on lines
+23
to
+30
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use either HardwareSerial1 or HardwareSerial2 - we just can't use the same one for both DMX input and DMX output (or any other conflicting usage) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously, I got the impression that SparkFunDMX was only used with HardwareSerial2, i.e. all ESPs with < 3 UARTs like the S2 would fallback to ESPDMX bitbanging, right? Do you know why that was, was serial1 reserved for something like IR, NPB, etc and is this not needed anymore? Just asking out of interest I guess. |
||
|
|
||
| // Pin defaults. Change these if needed for your hardware. | ||
| static const int txPin = 2; // transmit DMX data over this pin (default is GPIO2) | ||
| static const int rxPin = DMX_PIN_NO_CHANGE; // RX unused for DMX output | ||
| static const int rtsPin = DMX_PIN_NO_CHANGE; // RS485 DE/RE pin (UART RTS). Set to a GPIO to control transceiver direction. | ||
|
|
||
| // DMX value array and size. Entry 0 holds start code, so we need 512+1 elements. | ||
| static uint8_t dmxData[DMX_PACKET_SIZE] = {0}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this? This is not read ever, is it?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, reminiscence of the old driver. I'll remove it. |
||
| // Maximum slot count configured by initWrite() (includes start code slot 0). | ||
| static size_t maxSize = 0; | ||
| // Current transmit size (includes start code slot 0). This grows as channels are written. | ||
| static size_t txSize = 1; | ||
| static bool dmxInstalled = false; | ||
|
|
||
| void EspDmxOutput::initWrite(int chanQuant) { | ||
| if (chanQuant > dmxMaxChannel || chanQuant <= 0) chanQuant = defaultMax; | ||
| maxSize = static_cast<size_t>(chanQuant) + 1; // +1 for start code | ||
| txSize = 1; // start with just start code | ||
|
|
||
| // Configure the driver if needed. | ||
| if (!dmx_driver_is_installed(dmxPort)) { | ||
| dmx_config_t config = DMX_CONFIG_DEFAULT; | ||
| dmxInstalled = dmx_driver_install(dmxPort, &config, DMX_INTR_FLAGS_DEFAULT); | ||
| } else { | ||
| dmxInstalled = true; | ||
| } | ||
|
|
||
| if (dmxInstalled) { | ||
| dmx_set_pin(dmxPort, txPin, rxPin, rtsPin); | ||
|
|
||
| // Ensure NULL start code (slot 0). | ||
| dmxData[0] = DMX_SC; | ||
| dmx_write_slot(dmxPort, 0, DMX_SC); | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| void EspDmxOutput::write(int Channel, uint8_t value) { | ||
| if (!dmxInstalled) return; | ||
|
|
||
| // Allow slot 0 writes, but start code is enforced in update(). | ||
| if (Channel < 0) Channel = 0; | ||
| if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; | ||
|
|
||
| const size_t neededSize = static_cast<size_t>(Channel) + 1; | ||
| if (neededSize > txSize) txSize = neededSize; | ||
| if (maxSize > 0 && txSize > maxSize) txSize = maxSize; | ||
| if (txSize > DMX_PACKET_SIZE) txSize = DMX_PACKET_SIZE; | ||
|
|
||
| dmxData[Channel] = value; | ||
| dmx_write_slot(dmxPort, static_cast<size_t>(Channel), value); | ||
| } | ||
|
|
||
| void EspDmxOutput::update() { | ||
| if (!dmxInstalled) return; | ||
|
|
||
| // Always send the break signal first | ||
| dmx_write_slot(dmxPort, 0, DMX_SC); | ||
|
|
||
| // Send the frame currently staged in the driver buffer. | ||
| dmx_send(dmxPort, txSize); | ||
| } | ||
|
|
||
| #endif | ||
| #endif | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /* | ||
| * EspDmxOutput.h | ||
| * | ||
| * WLED DMX output implementation for ESP32 using the `esp_dmx` library. | ||
| */ | ||
| #pragma once | ||
|
|
||
| #include <inttypes.h> | ||
|
|
||
| class EspDmxOutput { | ||
| public: | ||
| void initWrite(int maxChan); | ||
| void write(int channel, uint8_t value); | ||
| void update(); | ||
| }; | ||
|
|
||
|
|
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.