Olá pessoal. Nosso departamento foi encarregado de apresentar a interface digital DALI. Além disso, uma apresentação demonstrando o funcionamento desta interface. Se necessário, então é necessário. O que simplesmente não fizemos. Para esse fim, foram fornecidos dois módulos de controle para luminárias LED. Ambos foram conduzidos. E o mestre? Começamos a escolher um controlador para controlar essa interface. Como resultado, o preço é altíssimo ou o tempo de entrega é o mesmo. E as férias estão se aproximando, e eu não quero mais adiar. Mais uma vez, analisamos as características e chamamos a atenção para os recursos deste protocolo digital:
- DALI é um protocolo aberto;
- O DALI é um barramento descentralizado, ou seja, não possui um controlador central e permite qualquer topologia.
Tudo isso parecia muito atraente e a tarefa parecia completamente não difícil. À primeira vista. Decidimos fazer mestres DALI no Arduino.
Muito obrigado a Timur Nabiev por sua
publicação em Habré . Por favor leia. Não vou me repetir, ele prescreveu uma boa teoria. Layout da interface - isso não acontece mais fácil. Mas com a biblioteca que ele publicou, algo não funcionou muito bem para nós.
Por isso, decidimos fazer nossos esboços. Eles fizeram dois. O primeiro é atribuir endereços curtos a todos os "membros" da rede.
Ver#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; void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); pinMode(DALI_TX_PIN, OUTPUT); digitalWrite(DALI_TX_PIN, HIGH); Serial.begin(115200); DaliInit(); } //----------------------------------------------------- void loop() { } //----------------------------------------------------- void DaliInit() { 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"); } //------------------------------------------------- bool SearchAndCompare(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; } //------------------------------------------------- void DaliTransmitCMD(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); }
Ou faça o downloadE isso é um teste. Nós controlamos dois módulos conectados ao DALI.
Ver #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}; void setup() { 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); } } void loop() { 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; } else if (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); } } } //------------------------------------------------- void DaliTransmitCMD(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); }
Ou faça o downloadMuito trabalho foi feito e, portanto, quero compartilhá-lo com todos. Talvez isso facilite o desenvolvimento para alguém.
Nenhuma biblioteca completa foi encontrada na rede. Por favor, use, tudo realmente funciona. Faça perguntas, tentarei responder a tudo com meus colegas. Talvez não imediatamente, nós realmente saímos de férias por duas semanas.
Na reportagem em vídeo sobre o trabalho realizado.
Módulos DAP-04 e LCM-60DA testados da Mean Well. Mas funcionará com outros.
E este é o esquema do kit de carroceria do Arduino, que o transfere para o modo mestre DALI e a fonte de alimentação ao mesmo tempo.

Esta é a conexão dos botões para o esboço de teste.

E aqui está uma pequena rede DALI
