Change DALI send-twice timing from 14 to 10ms fixing MiBoxer DT8

This commit is contained in:
Theo Arends 2025-11-20 17:44:37 +01:00
parent 41d3ffb98f
commit 64491d25d0

View File

@ -65,6 +65,7 @@
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
Version yyyymmdd Action Description Version yyyymmdd Action Description
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
1.3.0.1 20251120 update - Reduce send-twice timing from 14 to 10ms fixing MiBoxer DT8
1.3.0.0 20251119 update - Add DALI DT8 RGBWAF color support using Tasmota light control 1.3.0.0 20251119 update - Add DALI DT8 RGBWAF color support using Tasmota light control
- Add command `DaliChannels` to select Tasmota color type - Add command `DaliChannels` to select Tasmota color type
1.2.0.0 20251116 update - Add persistence for `DaliTarget` if filesystem is present 1.2.0.0 20251116 update - Add persistence for `DaliTarget` if filesystem is present
@ -123,6 +124,7 @@
#endif #endif
//#define DALI_LIGHT_COLOR_SUPPORT //#define DALI_LIGHT_COLOR_SUPPORT
//#define DALI_LIGHT_NO_READ_AFTER_WRITE // Use no DTR read-after-write for smooth color transitions (saves 55ms / channel)
//#define DALI_DEBUG //#define DALI_DEBUG
#ifndef DALI_DEBUG_PIN #ifndef DALI_DEBUG_PIN
@ -159,13 +161,16 @@ struct DALI {
uint8_t web_dimmer[DALI_MAX_STORED]; uint8_t web_dimmer[DALI_MAX_STORED];
uint8_t target_rgbwaf; uint8_t target_rgbwaf;
uint8_t device_type; uint8_t device_type;
uint8_t probe;
#ifdef DALI_DEBUG
uint8_t log_level;
#endif // DALI_DEBUG
bool allow_light; bool allow_light;
bool last_power; bool last_power;
bool power[DALI_MAX_STORED]; bool power[DALI_MAX_STORED];
bool available; bool available;
bool response; bool response;
bool light_sync; bool light_sync;
bool probe;
bool invert_rx; bool invert_rx;
bool invert_tx; bool invert_tx;
} *Dali = nullptr; } *Dali = nullptr;
@ -412,7 +417,7 @@ void DaliReceiveData(void) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("DLI: Rx collision")); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("DLI: Rx collision"));
} }
} }
if (Dali->probe) { if (1 == Dali->probe) {
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Rx %05X %d"), received_dali_data, gap_time); AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Rx %05X %d"), received_dali_data, gap_time);
} else { } else {
if (Dali->response || // Response from last message send if (Dali->response || // Response from last message send
@ -438,7 +443,7 @@ void DaliSendDataOnce(uint16_t send_dali_data) {
Bit number 01234567890123456789012345678901234567 Bit number 01234567890123456789012345678901234567
1 2 3 1 2 3
*/ */
Dali->last_activity += 14; // As suggested by DALI protocol (> 9.17 ms) Dali->last_activity += 10; // As suggested by DALI protocol (> 9.17 ms)
while (!TimeReached(Dali->last_activity)) { while (!TimeReached(Dali->last_activity)) {
delay(1); // Wait for bus to be free if needed delay(1); // Wait for bus to be free if needed
} }
@ -533,7 +538,7 @@ void DaliSendData(uint32_t adr, uint32_t cmd) {
} }
#ifdef DALI_DEBUG #ifdef DALI_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Tx DT%d, Twice %d, Adr 0x%02X, Cmd 0x%02X"), Dali->device_type, send_twice, adr, cmd); AddLog(Dali->log_level, PSTR("DLI: Tx DT%d, Twice %d, Adr 0x%02X, Cmd 0x%02X"), Dali->device_type, send_twice, adr, cmd);
#endif // DALI_DEBUG #endif // DALI_DEBUG
uint16_t send_dali_data = adr << 8 | cmd; uint16_t send_dali_data = adr << 8 | cmd;
@ -568,7 +573,7 @@ int DaliSendWaitResponse(uint32_t adr, uint32_t cmd, uint32_t timeout) {
Dali->response = false; Dali->response = false;
#ifdef DALI_DEBUG #ifdef DALI_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: Rx 0x%05X"), result); AddLog(Dali->log_level, PSTR("DLI: Rx 0x%05X"), result);
#endif // DALI_DEBUG #endif // DALI_DEBUG
return result; return result;
@ -585,9 +590,13 @@ bool DaliSetDTR(uint32_t dtr, uint32_t adr, uint32_t value) {
uint8_t dtr_query[3] = { DALI_102_QUERY_CONTENT_DTR0, DALI_102_QUERY_CONTENT_DTR1, DALI_102_QUERY_CONTENT_DTR2 }; uint8_t dtr_query[3] = { DALI_102_QUERY_CONTENT_DTR0, DALI_102_QUERY_CONTENT_DTR1, DALI_102_QUERY_CONTENT_DTR2 };
if (dtr > 2) { dtr = 0; } if (dtr > 2) { dtr = 0; }
uint32_t retry = 3;
while (retry--) {
DaliSendData(dtr_set[dtr], value); // Store value in DTR DaliSendData(dtr_set[dtr], value); // Store value in DTR
int result = DaliSendWaitResponse(adr | DALI_SELECTOR_BIT, dtr_query[dtr]); // Get DTR value int result = DaliSendWaitResponse(adr | DALI_SELECTOR_BIT, dtr_query[dtr]); // Get DTR value
return (result == value); if (result == value) { return true; }
}
return false;
} }
bool DaliSetValue(uint32_t adr, uint32_t getcmd, uint32_t setcmd, uint32_t v) { bool DaliSetValue(uint32_t adr, uint32_t getcmd, uint32_t setcmd, uint32_t v) {
@ -659,12 +668,14 @@ uint32_t DaliQueryRGBWAF(uint32_t adr) {
} }
} }
if (DALI_209_DEVICE_TYPE == dt) { if (DALI_209_DEVICE_TYPE == dt) {
delay(DALI_TIMEOUT); uint32_t retry = 3;
while (retry--) {
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
delay(DALI_TIMEOUT);
int colour_type = DaliSendWaitResponse(adr, DALI_209_QUERY_COLOUR_TYPE_FEATURES); int colour_type = DaliSendWaitResponse(adr, DALI_209_QUERY_COLOUR_TYPE_FEATURES);
if (colour_type >= 0) { if (colour_type >= 0) {
rgbwaf_channels = (colour_type >> 5) & 0x07; // RGBWAF channels in bits 5..7 rgbwaf_channels = (colour_type >> 5) & 0x07; // RGBWAF channels in bits 5..7
break;
}
} }
} }
return rgbwaf_channels; return rgbwaf_channels;
@ -917,51 +928,50 @@ bool DaliSetChannels(void) {
if (255 == cur_col[i]) { cur_col[i] = 254; } // Max Dali value if (255 == cur_col[i]) { cur_col[i] = 254; } // Max Dali value
} }
uint32_t adr = DaliTarget2Address(Dali->Settings.target); uint32_t adr = DaliTarget2Address(Dali->Settings.target);
#ifdef DALI_LIGHT_COLOR_SUPPORT #ifdef DALI_LIGHT_COLOR_SUPPORT
uint32_t channels = Dali->Settings.light_type -8; uint32_t channels = Dali->Settings.light_type -8;
if ((Dali->target_rgbwaf > 0) && (channels > 1)) { // Colour control if ((Dali->target_rgbwaf > 0) && (channels > 0)) { // Colour control
adr |= DALI_SELECTOR_BIT; // Enable Selector bit adr |= DALI_SELECTOR_BIT; // Enable Selector bit
/* #ifdef DALI_LIGHT_NO_READ_AFTER_WRITE
// This is too slow - 800ms for 5 channels // This takes 310ms for 3 channels but might send bad data as no DTR read-after-write
if (!DaliSetDTR(0, adr, 0x7F)) { return true; } // Linked Channel control
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGBWAF_CONTROL);
uint32_t channels = Dali->Settings.light_type -8;
if (!DaliSetDTR(0, adr, cur_col[0])) { return true; } // DALI Red
if (!DaliSetDTR(1, adr, cur_col[1])) { return true; } // DALI Green
if (!DaliSetDTR(2, adr, cur_col[2])) { return true; } // DALI Blue
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGB_DIMLEVEL);
if (channels > 3) {
if (!DaliSetDTR(0, adr, cur_col[4])) { return true; } // DALI While
if (!DaliSetDTR(1, adr, cur_col[3])) { return true; } // DALI Amber
if (!DaliSetDTR(2, adr, 255)) { return true; } // DALI Freecolour - no change
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_WAF_DIMLEVEL);
}
*/
// This is fastest - 330ms for 3 channels
DaliSendData(DALI_102_SET_DTR0, 0x7F); // Linked Channel control DaliSendData(DALI_102_SET_DTR0, 0x7F); // Linked Channel control
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGBWAF_CONTROL); DaliSendData(adr, DALI_209_SET_TEMPORARY_RGBWAF_CONTROL);
DaliSendData(DALI_102_SET_DTR0, cur_col[0]); // DALI Red DaliSendData(DALI_102_SET_DTR0, cur_col[0]); // DALI Red
DaliSendData(DALI_102_SET_DTR1, cur_col[1]); // DALI Green DaliSendData(DALI_102_SET_DTR1, (channels > 1) ? cur_col[1] : 255); // DALI Green
DaliSendData(DALI_102_SET_DTR2, cur_col[2]); // DALI Blue DaliSendData(DALI_102_SET_DTR2, (channels > 2) ? cur_col[2] : 255); // DALI Blue
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGB_DIMLEVEL); DaliSendData(adr, DALI_209_SET_TEMPORARY_RGB_DIMLEVEL);
if (channels > 3) { if (channels > 3) {
DaliSendData(DALI_102_SET_DTR0, cur_col[4]); // DALI White DaliSendData(DALI_102_SET_DTR0, cur_col[4]); // DALI White
DaliSendData(DALI_102_SET_DTR1, cur_col[3]); // DALI Amber DaliSendData(DALI_102_SET_DTR1, (channels > 4) ? cur_col[3] : 255); // DALI Amber
DaliSendData(DALI_102_SET_DTR2, 255); // DALI Freecolour - no change DaliSendData(DALI_102_SET_DTR2, 255); // DALI Freecolour - no change
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_WAF_DIMLEVEL); DaliSendData(adr, DALI_209_SET_TEMPORARY_WAF_DIMLEVEL);
} }
#else
// This takes 480ms for 3 channels but might send nothing if DTR read-after-write fails
if (!DaliSetDTR(0, adr, 0x7F)) { return true; } // Linked Channel control
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGBWAF_CONTROL);
if (!DaliSetDTR(0, adr, cur_col[0])) { return true; } // DALI Red
if (!DaliSetDTR(1, adr, (channels > 1) ? cur_col[1] : 255)) { return true; } // DALI Green
if (!DaliSetDTR(2, adr, (channels > 2) ? cur_col[2] : 255)) { return true; } // DALI Blue
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_RGB_DIMLEVEL);
if (channels > 3) {
if (!DaliSetDTR(0, adr, cur_col[4])) { return true; } // DALI While
if (!DaliSetDTR(1, adr, (channels > 4) ? cur_col[3] : 255)) { return true; } // DALI Amber
if (!DaliSetDTR(2, adr, 255)) { return true; } // DALI Freecolour - no change
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_SET_TEMPORARY_WAF_DIMLEVEL);
}
#endif // DALI_LIGHT_NO_READ_AFTER_WRITE
DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command DaliSendData(DALI_102_ENABLE_DEVICE_TYPE_X, DALI_209_DEVICE_TYPE); // Enable Extended command
DaliSendData(adr, DALI_209_ACTIVATE); DaliSendData(adr, DALI_209_ACTIVATE);
return true; return true;
@ -1016,6 +1026,7 @@ bool DaliInit(uint32_t function) {
digitalWrite(Dali->pin_tx, (Dali->invert_tx) ? LOW : HIGH); // Idle digitalWrite(Dali->pin_tx, (Dali->invert_tx) ? LOW : HIGH); // Idle
pinMode(Dali->pin_rx, INPUT); pinMode(Dali->pin_rx, INPUT);
#ifdef DALI_DEBUG #ifdef DALI_DEBUG
Dali->log_level = LOG_LEVEL_DEBUG;
pinMode(DALI_DEBUG_PIN, OUTPUT); pinMode(DALI_DEBUG_PIN, OUTPUT);
digitalWrite(DALI_DEBUG_PIN, HIGH); digitalWrite(DALI_DEBUG_PIN, HIGH);
#endif // DALI_DEBUG #endif // DALI_DEBUG
@ -1126,9 +1137,18 @@ bool DaliJsonParse(void) {
void CmndDali(void) { void CmndDali(void) {
// Dali {"addr":254,"cmd":100} - Any address and/or command // Dali {"addr":254,"cmd":100} - Any address and/or command
// Dali 0|1 - Enable DALI receive probe // Dali 0|1 - Enable DALI receive probe
// Dali 2 - Disable debug log output
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Dali->probe = XdrvMailbox.payload; Dali->probe = XdrvMailbox.payload;
#ifdef DALI_DEBUG
if (0 == Dali->probe) {
Dali->log_level = LOG_LEVEL_DEBUG;
}
else if (2 == Dali->probe) {
Dali->log_level = LOG_LEVEL_DEBUG_MORE +1;
}
#endif // DALI_DEBUG
ResponseCmndNumber(Dali->probe); ResponseCmndNumber(Dali->probe);
return; return;
} }
@ -1290,7 +1310,7 @@ void CmndDaliSend(void) {
uint32_t params = ParseParameters(5, values); uint32_t params = ParseParameters(5, values);
#ifdef DALI_DEBUG #ifdef DALI_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("DLI: index %d, params %d, values %d,%d,%d,%d,%d"), XdrvMailbox.index, params, values[0], values[1], values[2], values[3], values[4]); AddLog(Dali->log_level, PSTR("DLI: index %d, params %d, values %d,%d,%d,%d,%d"), XdrvMailbox.index, params, values[0], values[1], values[2], values[3], values[4]);
#endif // DALI_DEBUG #endif // DALI_DEBUG
if (DALI_207_DEVICE_TYPE == XdrvMailbox.index) { // DaliSend6 - DT6 = 207 = Extended LED commands 224...236 if (DALI_207_DEVICE_TYPE == XdrvMailbox.index) { // DaliSend6 - DT6 = 207 = Extended LED commands 224...236