Интерфейс DALI и Arduino. Реальный сюрреализм

n_-133wjyzxu0jonwcsjuw_ssbk.jpeg
#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