# DALI Bus Controller Driver (`esp_dali`)
[](https://components.espressif.com/components/espressif/esp_dali)
A DALI (Digital Addressable Lighting Interface, IEC 62386) master controller driver for ESP-IDF. The driver uses the on-chip **RMT (Remote Control Transceiver)** peripheral to generate and decode the Manchester-encoded DALI physical layer, requiring no external timing logic.
---
## Features
- **Full IEC 62386 physical layer** — Manchester encoding at Te = 416.67 µs, ±10 % tolerance window.
- **Forward frame TX** — Sends 16-bit DALI forward frames (address byte + command/data byte).
- **Backward frame RX** — Receives and decodes 8-bit DALI backward frames from slave devices.
- **All addressing modes** — Short address (0–63), group address (0–15), broadcast, and special-command addressing.
- **Direct arc-power control (DAPC)** — Set lamp output level directly (0x01–0xFE).
- **Indirect control commands** — OFF, UP, DOWN, STEP_UP, RECALL_MAX, GO_TO_SCENE, etc.
- **Configuration commands** — RESET, STORE_DTR_AS_*, ADD/REMOVE group, scene storage.
- **Query commands** — QUERY_STATUS, QUERY_ACTUAL_LEVEL, QUERY_VERSION, and all IEC 62386-102 queries.
- **Special (commissioning) commands** — INITIALIZE, RANDOMIZE, COMPARE, PROGRAM_SHORT_ADDRESS, etc.
- **Send-twice** — Automatic re-transmission for commands that require two consecutive forward frames within 100 ms.
- **Auto inter-frame gap** — The driver automatically inserts the IEC 62386 minimum inter-frame gap (> 22 Te) after every transaction; no manual delay needed.
- **Handle-based API** — `dali_new_master_rmt()` returns an independent instance handle; multiple instances can run concurrently on different GPIO pairs.
- **ESP-IDF v5.0+** compatible — Uses the new `esp_driver_rmt` component API.
---
## Supported Targets
| ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | ESP32-C6 | ESP32-P4 | ESP32-H2 |
| :---: | :------: | :------: | :------: | :------: | :------: | :------: |
| Yes | Yes | Yes | Yes | Yes | Yes | Yes |
---
## Requirements
- **ESP-IDF** v5.5.0 or later
- **Two GPIO pins** — one for TX (DALI bus drive), one for RX (DALI bus sense)
- **External DALI interface circuit** — The GPIO signals are 3.3 V logic; a DALI-compliant bus transceiver (e.g., based on a current-limited open-drain driver and optocoupler) is required to interface with the 9.5 V–22.5 V DALI bus.
## API Overview
### Include headers
```c
#include "dali.h" /* Driver API and constants */
#include "dali_command.h" /* DALI command code macros */
```
### Initialization
```c
dali_master_handle_t dali;
dali_master_config_t cfg = {
.rx_gpio = GPIO_NUM_4,
.tx_gpio = GPIO_NUM_5,
.invert_tx = false, /* enable if TX hardware path is inverting */
.invert_rx = false, /* enable if RX hardware path is inverting */
};
dali_master_rmt_config_t rmt_cfg = {
.mem_block_symbols = 64,
};
ESP_ERROR_CHECK(dali_new_master_rmt(&cfg, &rmt_cfg, &dali));
```
### Sending a command (no reply expected)
```c
dali_master_do_transaction(dali, DALI_ADDR_BROADCAST, 0, true, DALI_CMD_OFF,
false, DALI_TX_TIMEOUT_MS, NULL);
/* Inter-frame gap is inserted automatically — no explicit delay needed */
```
### Direct arc-power control (DAPC)
```c
dali_master_do_transaction(dali, DALI_ADDR_SHORT, 0, false, 200,
false, DALI_TX_TIMEOUT_MS, NULL);
```
### Querying a device (reply expected)
```c
int reply;
esp_err_t err = dali_master_do_transaction(dali, DALI_ADDR_SHORT, 0, true,
DALI_CMD_QUERY_ACTUAL_LEVEL,
false, DALI_TX_TIMEOUT_MS, &reply);
if (err == ESP_OK && DALI_RESULT_IS_VALID(reply)) {
ESP_LOGI(TAG, "Actual level: 0x%02X", (uint8_t)reply);
}
```
### Send-twice commands
```c
/* RESET must be sent twice within 100 ms. Pass send_twice = true. */
dali_master_do_transaction(dali, DALI_ADDR_SHORT, 0, true, DALI_CMD_RESET,
true, DALI_TX_TIMEOUT_MS, NULL);
```
### Release resources
```
dali_del_master(dali);
```
### Frame timing
The driver automatically inserts the minimum inter-frame gap required by IEC 62386 (> 22 Te ≈ 9.2 ms) after every `dali_master_do_transaction()` call. No explicit delay helper is needed between consecutive transactions.
---
## DALI Frame Timing Reference
```
Te = 416.67 µs (half-period)
Forward frame (FF): start(1Te×2) + 16 bits(1Te×2 each) + stop(2Te×2) = 38 Te ≈ 15.8 ms
Backward frame (BF): start(1Te×2) + 8 bits (1Te×2 each) + stop(2Te×2) = 22 Te ≈ 9.2 ms
No reply: FF → wait > 22 Te → next FF
With reply: FF → [7 Te … 22 Te] → BF → wait > 22 Te → next FF
Send-twice: FF1 → wait < 100 ms → FF2
```
---
## Project Layout
```
components/dali/
├── CMakeLists.txt
├── idf_component.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_cn.md
├── src/
│ └── dali.c # Driver implementation
└── include/
├── dali.h # Public API
└── dali_command.h # Command code definitions
```
---
## License
Apache License 2.0. See [LICENSE](LICENSE) for details.
6a11ddd575777cf5b7722fcd62fd39e18a3372fa
idf.py add-dependency "espressif/dali^1.0.0"