Управление Реле по MQTT на Arduino

Тема в разделе "Arduino & Shields", создана пользователем Otto, 25 июл 2016.

  1. Otto

    Otto Нерд

    Такая проблема, работаю над скетчем для Arduino UNO + Ethernet Shild W5100, который будет управлять реле по протоколу MQTT программно через систему автоматизации Умного дома MajorDoMo, или вручную с выключателей-кнопок + отображать в системе MajorDoMo состояние реле (Вкл./Выкл., 0 или 1) для каждой релюшки. Только пока не могу понять как сделать управление Вкл./Выкл. с отправкой статуса о реле через топики по MQTT и выключателей.
    Уже долго мучаюсь над кодом, помогите пожалуйста.
    Код (C++):
    /*
      Переделываю скетч для реле
    */

    #include <SPI.h>                 // Библиотека SPI шины
    #include <Ethernet.h>            // Ethernet библиотека
    #include <PubSubClient.h>        // Библиотека MQTT
    #include <EEPROM.h>           // Библиотека EEPROM

    #define Relay1 2              // Реле №1
    #define Relay2 3              // Реле №2
    #define relays_topic1 "home/data/status/Relay/1"     //публикуемый топик

    #define BUTTON_1 6            // Кнопка-выключатель №1
    #define BUTTON_2 7            // Кнопка-выключатель №2
    #define relays_topic2 "home/data/status/Relay/2"     //публикуемый топик

    #define UNUSED(expr) do { (void)(expr); } while (0) /*Безсмысленный цикл для callback
                                                          убирающий предупреждение
                                                          с компилятора*/
    long last_mls3 = millis();   //функция времени для отправки топиков

    bool stateRelay1 = false;      // Состояние Реле №1
    bool wasButtonDown1 = false;   // Состояние 1-й кнопки

    bool stateRelay2 = true;      // Статус Реле №2
    bool wasButtonDown2 = false;        // Объявляем что кнопка №2 не нажата 0

    int Address1 = 0;              // Адреса EEPROM для хранения значений
    int Address2 = 2;


    // Задаём mac и ip адреса в Локальной сети
    byte mac[]    = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
    IPAddress ip{192, 168, 1, 74};      //ip Адрес Ethernet Shild'a Arduino
    IPAddress server{192, 168, 1, 70};  //ip Адрес для MQTT Брокера

    // Шапка Функции Callback для объявления и Инициализации PubSubClient
    void callback(char* topic, byte* payload, unsigned int length);

    EthernetClient ethClient;                                 // Инициализируем Ethernet клиент
    PubSubClient client(server, 1883, callback, ethClient);   // Инициализируем MQTT клиент


    // Функция Callback
    void callback(char* topic, byte* payload, unsigned int length)
    {
      //Используем идентификатор UNUSED для устранения Warning'а при компиляции
      UNUSED(topic);
      client.publish("home/data/status/Relay", payload, length);

    }


    void setup() {
      pinMode(Relay1, OUTPUT);          // Задаём Реле №1 как Выход
      pinMode(BUTTON_1, INPUT);         // Задаём кнопку №1 как Вход
      pinMode(Relay2, OUTPUT);
      pinMode(BUTTON_2, INPUT);

      Serial.begin(9600);                  // Задаём скорость порта в БОД'ах.
      Serial.println(F("Relay test!"));    /* Тестовое сообщ. при откр. Монитора порта.
                                              Так же обёртываем сообщения
                                              в макрос F() для экономии ОЗУ */


      Ethernet.begin(mac, ip);        // Инициализируем mac, ip
      delay(100);                     //ждем 100 милисекунд

      client.connect("RelayClient");           //конектимся с брокером как клиент
      client.subscribe(relays_topic1);            //подписываемся на топик
      client.subscribe(relays_topic2);            //подписываемся на топик

      //цикл считывания значения из EEPROM для реле №1
      if ( EEPROM.read(Address1) ) {
        digitalWrite(Relay1, HIGH);
      } else {
        digitalWrite(Relay1, LOW);
      }

      //цикл считывания значения из EEPROM для реле №2
      if ( EEPROM.read(Address2) ) {
        digitalWrite(Relay2, HIGH);
      } else {
        digitalWrite(Relay2, LOW);
      }
    }

    // Функция для переподключения соединения с Брокером
    void reconnect() {
      // Повторяем, пока не переподключимся...
      while (!client.connected()) {         // Логическое НЕ "!" - Проверяем, если клиент не Законнектен....
        // Попытка подключиться
        if (client.connect("RelayClient")) {  // Если RelayClient клиент подключен...
          Serial.println(F("Connected!"));  // Выводим сообщ., что подключено!
        } else {
          Serial.print(F("failed connected - ")); // Ощибка соединения
          Serial.println(F("Jdem 5 seconds"));    // Ждём 5 секунд
          delay(5000);
        }
      }
    }

    // Функция для кнопки №1 (функция для сенсорной кнопки)
    void Button1() {
      byte sensButtonVal = digitalRead(BUTTON_1);  // Читаем значение с сенсорной кнопки
      bool isButtonDown1 = sensButtonVal;
      if (isButtonDown1 && !wasButtonDown1) {
        stateRelay1 = !stateRelay1;
        //delay(10);    // Для сенсорной кнопки защита от дребезга некчему
      }
      wasButtonDown1 = isButtonDown1;
      digitalWrite(Relay1, stateRelay1);
    }

    // Функция для кнопки №2 (функция для механической кнопки)
    void Button2() {
      bool isButtonDown2 = digitalRead(BUTTON_2);
      if (isButtonDown2 && !wasButtonDown2) {
        stateRelay2 = !stateRelay2;
        delay(10);     // Защита от дребезга
      }
      wasButtonDown2 = isButtonDown2;
      digitalWrite(Relay2, stateRelay2);
    }


    void loop() {

      if (!client.connect("RelayClient")) {   // Если RelayClient клиент НЕ подключен...
        reconnect();                        // Запускаем функцию переподключения
      }
      client.loop();



      Button1();
      Button2();

    }
     
    Последнее редактирование: 26 июл 2016
  2. alex-prog

    alex-prog Гик

    То есть, как передать информацию? У Вас пакеты какие-то получается передавать?