О протоколе DALI
DALI (Digital Addressable Lighting Interface) – протокол, предназначенный для управления осветительными приборами. Протокол был разработан австрийской компанией Tridonic и основан на манчестерском кодировании: каждый бит данных кодируется перепадом от низкого сигнала к высокому или наоборот.
DALI сеть состоит из контроллера и подключенных к нему осветительных приборов. Передача данных идет на скорости 1200бит/с. Напряжение для логической единицы составляет 16±6,5В, а для логического нуля 0±4,5В. Шина DALI всегда находится под напряжением 16В, в противном случае все осветительные приборы, подключенные к шине, переходят в аварийный режим и включаются. Питание шины обеспечивает контроллер. К одной шине подключается до 64 светильников. Устройства можно объединять в 16 групп и задавать до 16 сцен освещения. Яркость каждого осветительного прибора регулируется от 0 до 254.
Сообщение от контроллера к осветительному прибору состоит из 16 бит и одного стартового бита. Сообщение может быть адресовано отдельному светильнику, группе светильников либо быть широковещательным. Некоторые команды должны передаваться дважды с интервалом не более 100мс. На определенные команды, например запрос текущей яркости или запрос типа устройства, осветительный прибор отправляет ответное сообщение.
Сообщение от осветительного прибора контроллеру состоит из 8 бит и одного стартового бита.
Список команд можно посмотреть здесь.
Инициализация новых светильников
До начала работы каждому светильнику должен быть присвоен адрес от 1 до 63 (short address). У новых светильников короткий адрес как правило не задан, поэтому управлять конкретным светильником не получится. Такие светильники реагируют только на широковещательные команды.
Для того чтобы назначить короткий адрес светильнику нужно его инициализировать. У каждого светильника есть случайный адрес, состоящий из 24 бит (3 раза по 8 бит). 24 битный адрес может принимать значения от 1 до 16777216. Вероятность подключения светильников с одинаковыми адресами минимален и составляет один случай из 1 из 266144.
Процесс инициализации заключается в следующем:
- от контроллера дважды передается широковещательная команда INITIALISE (0b1010010100000000) с интервалом не более 100мс, которая переводит все светильники в режим инициализации;
- от контроллера дважды передается широковещательная команда RANDOMISE (0b1010011100000000) с интервалом не более 100мс, после которой все светильники присваивают себе новый случайный адрес;
- от контроллера передается значение случайного адреса (24бит) тремя сообщениями по 8 бит (0b10110001HHHHHHHH, 0b10110011MMMMMMMM, 0b10110101LLLLLLLL);
- от контроллера передается широковещательная команда COMPARE (0b1010100100000000);
- если контроллер фиксирует ответное сообщение, значит есть светильники с меньшими адресами; таким образом запрашиваемый адрес снижается до тех пор, пока светильники перестанут отвечать;
- если ответ от светильника не был получен, адрес увеличивается на одну единицу и таким образом определяется светильник с наименьшим случайным адресом;
- после определения адреса светильника контроллер задает светильнику короткий адрес (0b10110111AAAAAAAA) и посылает команду WITHRAW (0b1010101100000000), которая исключает светильник из процесса поиска;
- далее контроллер переходит к поиску следующего светильника с большим случайным адресом;
- после завершения процесса инициализации контроллер посылает команду TERMINATE (0b1010000100000000), и светильники выходят из режима инициализации.
DALI и ARDUINO
Для управления светильником я использовал ARDUINO NANO, блок питания 12В, резисторы, светодиоды, транзистор и светильник ERCO Grasshopper. Схема довольно простая.
Светильник ERCO Grasshopper предназначен для освещения фасадов зданий и архитектурных памятников. У меня оказался RGB светильник с DALI драйвером TRIDONIC. У данного светильника 3 адреса (RED, GREEN, BLUE).
Библиотекy DALI можно скачать здесь.
Настройка
void setup() {
Serial.begin(74880);
/*
Задаем цифровой выход.
*/
dali.setupTransmit(3);
/*
Задаем аналоговый вход.
Применяется блок питания большой мощности (12В 2,1А)
и светильники не могут просадить напряжение до 0В.
В моем случае логическая единица соответствует напряжению 4,5В,
а логический нуль соответствует напряжению 3,8В.
*/
dali.setupAnalogReceive(0);
/*
Тестирование шины:
- светильники должны выключиться и включиться;
- определяется среднее значение между логическим нулем и единицей.
*/
dali.busTest();
/*
Режим сообщений, передаваемых по-COM порту
false - передаются только ответы от светильников;
true - предается вся информации с комментариями.
*/
dali.msgMode = true;
}
Основные команды
/*
Передача информации от DALI контроллера, где:
cmd1 - адресный байт;
cmd2 - байт команды.
*/
dali.transmit(cmd1, cmd2)
/*
Получить ответ от светильника
*/
uint8_t response = dali.receive()
/*
Проверка получения ответа
*/
bool response = dali.getResponse()
/*
Сканировать короткие адреса.
*/
dali.scanShortAdd()
/*
Запустить инициализацию.
*/
dali.initialisation();
Пример использования
Ниже приводится пример использования библиотеки. Комбинируя яркости различных каналов светильника, мы получаем разные цвета.
#include <Dali.h>
const int DALI_TX = 3;
const int DALI_RX_A = 0;
#define BROADCAST_C 0b11111111
#define ON_C 0b00000101
void setup() {
Serial.begin(74880);
//устанавливаем цифровой выход для передачи сообщений
dali.setupTransmit(DALI_TX);
//устанавливаем аналоговый вход для приема сообщений
dali.setupAnalogReceive(DALI_RX_A);
//тестируем шину
dali.busTest();
//режим сообщений
dali.msgMode = true;
}
void sinus () {
// задаем адреса светильников
uint8_t lf_1_add = 0;
uint8_t lf_2_add = 1;
uint8_t lf_3_add = 2;
// переменные для значений яркости каждого светильника
uint8_t lf_1;
uint8_t lf_2;
uint8_t lf_3;
// счетчик
uint8_t i;
while (Serial.available() == 0) {
for (i = 0; i < 360; i ++) {
//выход из цикла
if (Serial.available() != 0) {
dali.transmit(BROADCAST_C, ON_C);
break;
}
//определяем значение яркости
lf_1 = (int) abs(254 * sin(i * 3.14 / 180));
lf_2 = (int) abs(254 * sin(i * 3.14 / 180 + 2 * 3.14 / 3));
lf_3 = (int) abs(254 * sin(i * 3.14 / 180 + 1 * 3.14 / 3));
//задаем яркость
dali.transmit(lf_1_add << 1, lf_1);
delay(5);
dali.transmit(lf_2_add << 1, lf_2);
delay(5);
dali.transmit(lf_3_add << 1, lf_3);
delay(5);
delay(20);
}
}
}
void loop() {
sinus();
};
Литература
- DALI commands
- DALI address setting explained
- USB — DALI master using the LPC2141 Application note
- DALI slave using the LPC1112 Application note
- Manchester Library for Arduino
- Digital Addressable Lighting Interface (DALI) Application Note
- DALI gateway
Автор: Nabiyev