Interface DALI and Arduino. Real surrealism
Hello. Our department was tasked to present the DALI digital interface. And a presentation with a demonstration of the work of this interface. If necessary, then it is necessary. What we just did. For this purpose, two LED lighting control modules were provided. Both were led. And the master? Began to choose a controller to control this interface. In the end, or the price of some transcendental or delivery times are the same. A vacation is coming, and I don’t want to postpone it. Once again, we looked at the characteristics and paid attention to the features of this digital protocol:
All this seemed very attractive and the task seemed completely uncomplicated. At first sight. We decided to make the master DALI on Arduino.
Many thanks to Timur Nabiyev for his publication on Habré . Please read. I will not repeat, the theory he prescribed well. The interface circuit - is never easier. But with the library published by him, something was not very good for us.
Therefore, we decided to make our own sketches. Made two. The first is to assign short addresses to all “members” of the network.
Or download
And this is a test. We manage two modules connected to DALI.
Or download
A lot of work has been done and therefore I want to share with everyone. Maybe it will facilitate the development of someone.
No full library found in the network. Please use, everything really works. Ask questions, I and my colleagues will try to answer everything. Maybe not immediately, because we are really going on vacation for two weeks.
In the video report on the work.
We tested the DAP-04 and LCM-60DA modules from Mean Well. But it will work with any others.
And this is the Arduino body kit that translates it into DALI master mode and a power supply at the same time.
This is a button connection for a test sketch.
And here is a small network DALI
- DALI is an open protocol;
- DALI is a decentralized bus, that is, it does not have a central controller and allows any topology.
All this seemed very attractive and the task seemed completely uncomplicated. At first sight. We decided to make the master DALI on Arduino.
Many thanks to Timur Nabiyev for his publication on Habré . Please read. I will not repeat, the theory he prescribed well. The interface circuit - is never easier. But with the library published by him, something was not very good for us.
Therefore, we decided to make our own sketches. Made two. The first is to assign short addresses to all “members” of the network.
Look
#define DALI_TX_PIN 3#define DALI_RX_PIN A0#define LED_PIN 13#define RESET 0b00100000#define INITIALISE 0xA5#define RANDOMISE 0xA7#define SEARCHADDRH 0xB1#define SEARCHADDRM 0xB3#define SEARCHADDRL 0xB5#define PRG_SHORT_ADDR 0xB7#define COMPARE 0xA9#define WITHDRAW 0xAB#define TERMINATE 0xA1#define START_SHORT_ADDR 2#define DALI_ANALOG_LEVEL 650#define DALI_HALF_BIT_TIME 416 //microseconds#define DALI_TWO_PACKET_DELAY 10 //miliseconds#define DALI_RESPONSE_DELAY_COUNT 15 //максимальное число полубитов//до ответаuint8_t ShortAddr = START_SHORT_ADDR;
voidsetup(){
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
pinMode(DALI_TX_PIN, OUTPUT);
digitalWrite(DALI_TX_PIN, HIGH);
Serial.begin(115200);
DaliInit();
}
//-----------------------------------------------------voidloop(){
}
//-----------------------------------------------------voidDaliInit(){
Serial.println("Initialization...");
DaliTransmitCMD(RESET, 0x00);
delay(2*DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(RESET, 0x00);
delay(2*DALI_TWO_PACKET_DELAY);
delay(100);
DaliTransmitCMD(INITIALISE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(INITIALISE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(INITIALISE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
delay(100);
DaliTransmitCMD(RANDOMISE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(RANDOMISE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
delay(100);
while(ShortAddr < 64)
{
long SearchAddr = 0xFFFFFF;
bool Response = 0;
long LowLimit = 0;
long HighLimit = 0x1000000;
Response = SearchAndCompare(SearchAddr);
delay(DALI_TWO_PACKET_DELAY);
if(Response)
{
digitalWrite(LED_PIN, LOW);
Serial.println("Device detected, address searching...");
if(!SearchAndCompare(SearchAddr - 1))
{
delay(DALI_TWO_PACKET_DELAY);
SearchAndCompare(SearchAddr);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(PRG_SHORT_ADDR, ((ShortAddr << 1) | 1));
delay(3*DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(WITHDRAW, 0x00);
Serial.print("24-bit address found: 0x");
Serial.println(SearchAddr, HEX);
Serial.print("Assigning short address ");
Serial.println(ShortAddr);
break;
}
}
else
{
Serial.println("No devices detected");
break;
}
while(1)
{
SearchAddr = (long)((LowLimit + HighLimit) / 2);
Response = SearchAndCompare(SearchAddr);
delay(DALI_TWO_PACKET_DELAY);
if (Response)
{
digitalWrite(LED_PIN, LOW);
if ((SearchAddr == 0) || (!SearchAndCompare(SearchAddr - 1)))
break;
HighLimit = SearchAddr;
}
else
LowLimit = SearchAddr;
}
delay(DALI_TWO_PACKET_DELAY);
SearchAndCompare(SearchAddr);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(PRG_SHORT_ADDR, ((ShortAddr << 1) | 1));
delay(5*DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(WITHDRAW, 0x00);
delay(DALI_TWO_PACKET_DELAY);
Serial.print("24-bit address found: 0x");
Serial.println(SearchAddr, HEX);
Serial.print("Assigning short address ");
Serial.println(ShortAddr);
ShortAddr++;
// break; //только для одного модуля
}
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(TERMINATE, 0x00);
delay(DALI_TWO_PACKET_DELAY);
Serial.println("Init complete");
}
//-------------------------------------------------boolSearchAndCompare(long SearchAddr){
bool Response = 0;
uint8_t HighByte = SearchAddr >> 16;
uint8_t MiddleByte = SearchAddr >> 8;
uint8_t LowByte = SearchAddr;
for(uint8_t i = 0; i < 3; i++)
{
DaliTransmitCMD(SEARCHADDRH, HighByte);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(SEARCHADDRM, MiddleByte);
delay(DALI_TWO_PACKET_DELAY);
DaliTransmitCMD(SEARCHADDRL, LowByte);
delay(DALI_TWO_PACKET_DELAY);
}
DaliTransmitCMD(COMPARE, 0x00);
delayMicroseconds(7 * DALI_HALF_BIT_TIME);
for(uint8_t i = 0; i < DALI_RESPONSE_DELAY_COUNT; i++)
{
if (analogRead(DALI_RX_PIN) < DALI_ANALOG_LEVEL)
{
Response = 1;
digitalWrite(LED_PIN, HIGH);
break;
}
delayMicroseconds(DALI_HALF_BIT_TIME);
}
return Response;
}
//-------------------------------------------------voidDaliTransmitCMD(uint8_t Part1, uint8_t Part2){
uint8_t DALI_CMD[] = { Part1, Part2 };
//Старт бит
digitalWrite(DALI_TX_PIN, LOW);
delayMicroseconds(DALI_HALF_BIT_TIME);
digitalWrite(DALI_TX_PIN, HIGH);
delayMicroseconds(DALI_HALF_BIT_TIME);
//командаfor (uint8_t CmdPart = 0; CmdPart < 2; CmdPart++)
{
for(int i = 7; i >= 0; i--)
{
bool BitToSend = false;
if ((DALI_CMD[CmdPart] >> i) & 1)
BitToSend = true;
if (BitToSend)
digitalWrite(DALI_TX_PIN, LOW);
else
digitalWrite(DALI_TX_PIN, HIGH);
delayMicroseconds(DALI_HALF_BIT_TIME);
if (BitToSend)
digitalWrite(DALI_TX_PIN, HIGH);
else
digitalWrite(DALI_TX_PIN, LOW);
delayMicroseconds(DALI_HALF_BIT_TIME);
}
}
digitalWrite(DALI_TX_PIN, HIGH);
}
Or download
And this is a test. We manage two modules connected to DALI.
Look
#define DALI_TX_PIN 3#define DALI_RX_PIN A0#define BROADCAST_CMD 0b11111111#define DOWN 0b00000010#define UP 0b00000001#define DALI_CHNL_COUNT 4#define LAMP_OFF_VALUE 0#define DALI_HALF_BIT_TIME 416 //microseconds#define DALI_TWO_PACKET_DELAY 10 //miliseconds//аналоговые входыuint8_t AnalogPins[DALI_CHNL_COUNT] = {A1, A2, A3, A4, };
//кнопкиuint8_t KeyPins[DALI_CHNL_COUNT] = {4, 5, 6, 7, };
uint8_t DALIPrevVals[DALI_CHNL_COUNT] = {0, 0, 0, 0};
uint8_t LampState[DALI_CHNL_COUNT] = {0, 0, 0, 0};
voidsetup(){
pinMode(DALI_TX_PIN, OUTPUT);
digitalWrite(DALI_TX_PIN, HIGH);
for(uint8_t i = 0; i < DALI_CHNL_COUNT; i++)
{
pinMode(KeyPins[i], INPUT);
digitalWrite(KeyPins[i], HIGH);
}
}
voidloop(){
for(uint8_t PWM = 2; PWM < DALI_CHNL_COUNT; PWM++)
{
if (LampState[PWM] == 1)
{
uint16_t ADCValue = analogRead(AnalogPins[PWM]);
if (ADCValue > 1016)
ADCValue = 1016;
ADCValue /= 4;
uint8_t PWMVal = ADCValue;
if (abs(DALIPrevVals[PWM] - PWMVal) >= 1)
{
DALIPrevVals[PWM] = PWMVal;
DaliTransmitCMD(PWM << 1, PWMVal);
if (LampState[PWM] == 0)
LampState[PWM] = 1;
delay(DALI_TWO_PACKET_DELAY);
}
}
}
for(uint8_t KEY = 0; KEY < DALI_CHNL_COUNT; KEY++)
{
if (digitalRead(KeyPins[KEY]) == LOW)
{
delay(70);
if (KEY == 0)
{
DaliTransmitCMD(BROADCAST_CMD, UP);
delay(DALI_TWO_PACKET_DELAY);
break;
}
elseif (KEY == 1)
{
DaliTransmitCMD(BROADCAST_CMD, DOWN);
delay(DALI_TWO_PACKET_DELAY);
break;
}
if (digitalRead(KeyPins[KEY]) == LOW)
{
if (LampState[KEY] == 0)
{
LampState[KEY] = 1;
uint16_t ADCValue = analogRead(AnalogPins[KEY]);
if (ADCValue > 1016)
ADCValue = 1016;
ADCValue /= 4;
uint8_t PWMVal = ADCValue;
DaliTransmitCMD(KEY << 1, PWMVal);
}
else
{
LampState[KEY] = 0;
DaliTransmitCMD(KEY << 1, LAMP_OFF_VALUE);
}
delay(DALI_TWO_PACKET_DELAY);
}
delay(500);
}
}
}
//-------------------------------------------------voidDaliTransmitCMD(uint8_t Part1, uint8_t Part2){
uint8_t DALI_CMD[] = { Part1, Part2 };
//Старт бит
digitalWrite(DALI_TX_PIN, LOW);
delayMicroseconds(DALI_HALF_BIT_TIME);
digitalWrite(DALI_TX_PIN, HIGH);
delayMicroseconds(DALI_HALF_BIT_TIME);
//командаfor (uint8_t CmdPart = 0; CmdPart < 2; CmdPart++)
{
for(int i = 7; i >= 0; i--)
{
bool BitToSend = false;
if ((DALI_CMD[CmdPart] >> i) & 1)
BitToSend = true;
if (BitToSend)
digitalWrite(DALI_TX_PIN, LOW);
else
digitalWrite(DALI_TX_PIN, HIGH);
delayMicroseconds(DALI_HALF_BIT_TIME);
if (BitToSend)
digitalWrite(DALI_TX_PIN, HIGH);
else
digitalWrite(DALI_TX_PIN, LOW);
delayMicroseconds(DALI_HALF_BIT_TIME);
}
}
digitalWrite(DALI_TX_PIN, HIGH);
}
Or download
A lot of work has been done and therefore I want to share with everyone. Maybe it will facilitate the development of someone.
No full library found in the network. Please use, everything really works. Ask questions, I and my colleagues will try to answer everything. Maybe not immediately, because we are really going on vacation for two weeks.
In the video report on the work.
We tested the DAP-04 and LCM-60DA modules from Mean Well. But it will work with any others.
And this is the Arduino body kit that translates it into DALI master mode and a power supply at the same time.
This is a button connection for a test sketch.
And here is a small network DALI