Керування світильниками по протоколу DALI з допомогою Arduino

протоколі 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 Коник. Схема досить проста.

Світильник ERCO Grasshopper призначений для освітлення фасадів будівель і архітектурних пам'яток. У мене виявився RGB світильник з DALI драйвером TRIDONIC. У даного світильника 3 адреси (RED, GREEN, BLUE).

Бібліотеки 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();
};


Література
  1. DALI commands
  2. DALI address setting explained
  3. USB — DALI master using the LPC2141 Application note
  4. DALI slave using the LPC1112 Application note
  5. Manchester Library for Arduino
  6. Digital Addressable Lighting Interface (DALI) Application Note
  7. DALI gateway
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.