Интерфейс DALI и Arduino. Реальный сюрреализм03.02.2018 00:05
#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);
}
© Geektimes