Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions wled00/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(DMXGap,dmx[F("gap")]);
CJSON(DMXStart, dmx["start"]);
CJSON(DMXStartLED,dmx[F("start-led")]);
CJSON(DMXNumFixtures, dmx[F("num-fixtures")]);

JsonArray dmx_fixmap = dmx[F("fixmap")];
for (int i = 0; i < dmx_fixmap.size(); i++) {
Expand Down Expand Up @@ -1235,6 +1236,7 @@ void serializeConfig(JsonObject root) {
dmx[F("gap")] = DMXGap;
dmx["start"] = DMXStart;
dmx[F("start-led")] = DMXStartLED;
dmx[F("num-fixtures")] = DMXNumFixtures;

JsonArray dmx_fixmap = dmx.createNestedArray(F("fixmap"));
for (unsigned i = 0; i < 15; i++) {
Expand Down
4 changes: 2 additions & 2 deletions wled00/data/settings_dmx.htm
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ <h2>Imma firin ma lazer (if it has DMX support)</h2><!-- TODO: Change to somethi

Proxy Universe <input name=PU type=number min=0 max=63999 required> from E1.31 to DMX (0=disabled)<br>
<i>This will disable the LED data output to DMX configurable below</i><br><br>
<i>Number of fixtures is taken from LED config page</i><br>

Channels per fixture (15 max): <input type="number" min="1" max="15" name="CN" maxlength="2" onchange="mMap();"><br />
Start channel: <input type="number" min="1" max="512" name="CS" maxlength="2"><br />
Spacing between start channels: <input type="number" min="1" max="512" name="CG" maxlength="2" onchange="mMap();"> [ <a href="javascript:alert('if set to 10, first fixture will start at 10,\nsecond will start at 20 etc.\nRegardless of the channel count.\nMakes memorizing channel numbers easier.');">info</a> ]<br>
<div id="gapwarning" style="color: orange; display: none;">WARNING: Channel gap is lower than channels per fixture.<br />This will cause overlap.</div>
<button type="button" onclick="location.href='/dmxmap';">DMX Map</button><br>
DMX fixtures start LED: <input type="number" min="0" max="1500" name="SL">
DMX fixtures start LED: <input type="number" min="0" max="1500" name="SL"><br>
Number of fixtures: <input type="number" min="1" max="512" name="NF">
<h3>Channel functions</h3>
<div id="dmxchannels"></div>
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
Expand Down
38 changes: 35 additions & 3 deletions wled00/dmx_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,37 @@

#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 = 1000 / MAX_DMX_RATE;
if (millis() - last_dmx_time < dmxFrameTime) return;
Comment thread
Stijn-Jacobs marked this conversation as resolved.

uint8_t brightness = strip.getBrightness();

// Track last brightness sent to DMX, allow one final update when brightness becomes 0
static uint8_t lastSentBrightness = 255;

// Skip DMX entirely if strip is off
if (brightness == 0 && lastSentBrightness == 0) return;

// Change detection: only update if strip data has changed since last update
static unsigned long lastStripShow = 0;
unsigned long currentShow = strip.getLastShow();
if (currentShow == lastStripShow && brightness == strip.getBrightness() && brightness != 0) {
return;
}
lastStripShow = currentShow;
last_dmx_time = millis();

bool calc_brightness = true;

Expand All @@ -28,9 +53,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);
Expand Down Expand Up @@ -66,6 +97,7 @@ void handleDMXOutput()
}

dmx.update(); // update the DMX bus
lastSentBrightness = brightness;
}

void initDMXOutput() {
Expand Down
4 changes: 4 additions & 0 deletions wled00/set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (t>=0 && t < MAX_LEDS) {
DMXStartLED = t;
}
t = request->arg(F("NF")).toInt();
if (t>0 && t<=512) {
DMXNumFixtures = t;
}
for (int i=0; i<15; i++) {
String argname = "CH" + String((i+1));
t = request->arg(argname).toInt();
Expand Down
19 changes: 9 additions & 10 deletions wled00/src/dependencies/dmx/SparkFunDMX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,18 @@ void SparkFunDMX::write(int Channel, uint8_t value) {
void SparkFunDMX::update() {
if (_READWRITE == _WRITE)
{
//Send DMX break
// Manually create DMX break signal, is more efficient than using Serial settings
// Break is just a high signal for minimum 88us, then low (mark) for 8us
pinMode(txPin, OUTPUT);
digitalWrite(txPin, HIGH);
DMXSerial.begin(BREAKSPEED, BREAKFORMAT, rxPin, txPin);//Begin the Serial port
DMXSerial.write(0);
DMXSerial.flush();
delay(1);
DMXSerial.end();
delayMicroseconds(176); // Break duration (176us is standard, 88us minimum)
digitalWrite(txPin, LOW);
delayMicroseconds(8);

//Send DMX data
DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);//Begin the Serial port
// Re-enable serial and send data
DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);
DMXSerial.write(dmxData, chanSize);
DMXSerial.flush();
DMXSerial.end();//clear our DMX array, end the Hardware Serial port
DMXSerial.end();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
#if !defined(DMX_SEND_ONLY)
else if (_READWRITE == _READ)//In a perfect world, this function ends serial communication upon packet completion and attaches RX to a CHANGE interrupt so the start code can be read again
Expand Down
1 change: 1 addition & 0 deletions wled00/xml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
printSetFormValue(settingsScript,PSTR("CG"),DMXGap);
printSetFormValue(settingsScript,PSTR("CS"),DMXStart);
printSetFormValue(settingsScript,PSTR("SL"),DMXStartLED);
printSetFormValue(settingsScript,PSTR("NF"),DMXNumFixtures);

printSetFormIndex(settingsScript,PSTR("CH1"),DMXFixtureMap[0]);
printSetFormIndex(settingsScript,PSTR("CH2"),DMXFixtureMap[1]);
Expand Down