Переключение режима на ESP8266 при зажатии кнопки

Тема в разделе "Проводная и беспроводная связь", создана пользователем Otto, 31 июл 2016.

  1. Otto

    Otto Нерд

    Есть Скетч на ESP8266 "Witty Cloud", долго с ним возился, что бы заработал как мне нужно.... Вот только не могу понять как решить проблему и немного переделать его....
    Что делает скетч: Скетч позволяет включать/выключать 2 реле по MQTT и с выключателей-кнопок. Имеет 3 режима: Off - выключено реле (отправл. 0 по MQTT), On - включено реле (отправл. 1 по MQTT), auto - в этом режиме идёт проверка датчика освещённости и реакция датчика движения, если в обоих случаях true - то включается реле (отправл. 2 по MQTT).
    Работает это так: Есть 2 кнопка, при коротком нажатии любой из них происходит переключение режима на конкретное реле. Тем самым это не удобно, т.к. при нажатии на кнопку включается реле, и что бы выключить нужно ещё дважды нажать на эту кнопку.
    Что хочу от скетча: Переделать так, что бы при обычных коротких нажатиях любой из кнопки просто включалось/выключалось реле, а при зажатии кнопки 1 (к примеру) более 2-х секунд включался режим auto(режим 3), а отключался простым коротким нажатием в режим Off(режим 0).
    Кнопки подключены к GPIO12/14, Релюшки к GPIO4/5.
    Помогите пожалуйста, кто знает как это сделать))
    Код (C++):
    #include <ESP8266WiFi.h>                     // Библиотека ESP8266
    #include <PubSubClient.h>                    // Библиотека MQTT

    const char* ssid = "ROUTER_SSID";             // Название сети роутера
    const char* password = "Password";            // Пароль от роутера
    const char* mqtt_server = "192.168.1.70";    // ip брокера mqtt

    #define RELAY_1 5                                  // Реле №1
    #define BUTTON_1 12                                // Кнопка №1
    #define relays_topic1 "home/data/ESP01/Relay1"     // Публикуемый топик

    #define RELAY_2 4                                  // Реле №2
    #define BUTTON_2 14                                // Кнопка №2
    #define relays_topic2 "home/data/ESP01/Relay2"     // Публикуемый топик

    WiFiClient espClient;                              // Инициализация WiFi клиента
    PubSubClient client(espClient);                    // Инициализация MQTT клиента

    long last_mls = millis();              // функция времени в милисекундах
    long last_mls2 = millis();             // функция времени для датчика движения PIR
    long last_mls3 = millis();             // функция времени для отправки топиков
    long last_mls4 = millis();             // функция времени для датчика света

    boolean Status1 = true;                // объявляем Status1 реле в 0, инверсия...
    boolean btnPress1 = false;             // объявляем что кнопка №1 не нажата "0"
    boolean lastbtnStat1 = false;          // временная переменная для хранения статуса1

    boolean Status2 = true;                // объявляем Status2 реле в 0, инверсия...
    boolean btnPress2 = false;             // объявляем что кнопка №2 не нажата "0"
    boolean lastbtnStat2 = false;          // временная переменная для хранения статуса2

    int regim1 = 0;               // Режимы по умолчанию при включении
    int regim2 = 0;

    int ligtsvet = 0;             // Переменная для фоторезистора, светло или темно | 1 или 0
    int pirPin = 13;              // 13 - pin для подключения датчика движения
    int val = 0;                  // Переменная для хранения состояния датчика движения
    int ligt;                     // Переменная освещенности для фоторезистора

    void setup() {
      pinMode(pirPin, INPUT);                    // PIR датчик как ВХОД
      pinMode(RELAY_1, OUTPUT);                  // Реле №1 как ВЫХОД
      pinMode(BUTTON_1, INPUT);                  // Кнопка №1 как ВХОД
      digitalWrite(RELAY_1, Status1);            // устанавливаем на выходе статус1 реле

      pinMode(RELAY_2, OUTPUT);                  // Реле №2 как ВЫХОД
      pinMode(BUTTON_2, INPUT);                  // Кнопка №2 как ВХОД
      digitalWrite(RELAY_2, Status2);            // устанавливаем на выходе статус2 реле

      Serial.begin(115200);                      // инициализация монитора порта
      client.setServer(mqtt_server, 1883);       // подключаемся к MQTT
      client.setCallback(callback);              // функция получения топиков с брокера
      delay(100);                                // ждем 100 милисекунд

      WiFi.begin(ssid, password);                // подключаемся к WiFi
      delay(15000);                              // ждем 15 секунд

      client.connect("ESP01RelayClient");        // конектимся с брокером как клиент
      client.subscribe("home/data/ESP01/#");     // подписываемся на все топики
    }

    void pir() {                                 // Функция для датчика движения
      val = digitalRead(pirPin);                 // считываем состояние датчика
      if (val == HIGH) {
        if (millis() - last_mls2 > 500 && ligtsvet == 0) {   // Если значен. датчика движения и фоторезистор...
          last_mls2 = millis();
          if (regim1 == 2) {
            Status1 = false;
            digitalWrite(RELAY_1, Status1);
            Serial.println("Motion1");
          }
          if (regim2 == 2) {
            Status2 = false;
            digitalWrite(RELAY_2, Status2);
            Serial.println("Motion2");
          }
        }
      } else {
        if (millis() - last_mls2 > 15000) {
          last_mls2 = millis();
          if (regim1 == 2) {
            Status1 = true;
            digitalWrite(RELAY_1, Status1);
            Serial.println("no Motion1");
          }
          if (regim2 == 2) {
            Status2 = true;
            digitalWrite(RELAY_2, Status2);
            Serial.println("no Motion2");
          }
        }
      }
    }


    void svet() {                                // функция чтения с датчика света
      ligt = analogRead(A0);
      Serial.print("Svet: ");
      Serial.println(ligt);

      if (ligt < 100)                            // Если свет меньше указанного значения...
      { //то ligtsvet равен 0
        ligtsvet = 0;
      } else                                     //если нет то 1
      {
        ligtsvet = 1;
      }
    }

    void callback(char* topic, byte* payload, unsigned int length)      //читаем топики
    {
      Serial.print(topic);
      Serial.print("  ");
      String strTopic = String(topic);
      String strPayload = String((char*)payload);
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      Serial.println();
      if (strTopic == "home/data/ESP01/Relay1") {
        if ((char)payload[0] == '0') {
          Status1 = true;
          regim1 = 0;
        }
        else if ((char)payload[0] == '1') {
          Status1 = false;
          regim1 = 1;
        } else {
          regim1 = 2;
        }
      }
      if (strTopic == "home/data/ESP01/Relay2") {
        if ((char)payload[0] == '0') {
          Status2 = true;
          regim2 = 0;
        }
        else if ((char)payload[0] == '1') {
          Status2 = false;
          regim2 = 1;
        } else {
          regim2 = 2;
        }
      }
    }



    void button1() {                            // Функция для кнопки №1
      btnPress1 = digitalRead(BUTTON_1);
      Status1 = digitalRead(RELAY_1);
      if (btnPress1 && !lastbtnStat1) {
        delay(30); // защита от дребезга
        btnPress1 = digitalRead(BUTTON_1);

        if (btnPress1) {                 // Если кнопка нажата, то...
          regim1++;                      // переключаем на слежующий режим
          if (regim1 > 2) {              // если действующий режим > второго, то...
            regim1 = 0;                  // возвращаемся на нулевой режим
          }
        }
      }
      if (regim1 == 0) {
        Status1 = true;
        digitalWrite(RELAY_1, Status1);
      }
      if (regim1 == 1) {
        Status1 = false;
        digitalWrite(RELAY_1, Status1);
      }
      if (regim1 == 2) {
        pir();
      }

      lastbtnStat1 = btnPress1;
    }


    void button2() {                            // Функция для кнопки №2
      btnPress2 = digitalRead(BUTTON_2);
      Status2 = digitalRead(RELAY_2);
      if (btnPress2 && !lastbtnStat2) {
        delay(30); // защита от дребезга
        btnPress2 = digitalRead(BUTTON_2);

        if (btnPress2) {                 // Если кнопка нажата, то...
          regim2++;                      // переключаем на слежующий режим
          if (regim2 > 2) {              // если действующий режим > второго, то...
            regim2 = 0;                  // возвращаемся на нулевой режим
          }
        }
      }
      if (regim2 == 0) {
        Status2 = true;
        digitalWrite(RELAY_2, Status2);
      }
      if (regim2 == 1) {
        Status2 = false;
        digitalWrite(RELAY_2, Status2);
      }
      if (regim2 == 2) {
        pir();
      }

      lastbtnStat2 = btnPress2;
    }


    void reconnect_server()                     // функция проверки подключения
    {
      if (WiFi.status() != WL_CONNECTED)        // если нет подключения с сетью...
      {
        WiFi.begin(ssid, password);
        Serial.println("");
        Serial.println("WiFi connect...");      // выводим в монитор порта что пытаемся подкл.
      } else {
        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
      }
      if (!client.connected() && WiFi.status() == WL_CONNECTED) {     // если к сети подключились но к MQTT нет
        client.connect("ESP01RelayClient");                           // Подключаемся к клиенту
        client.subscribe(relays_topic1);                              // подписываемся на топик
        Serial.println("Mosquitto connect...");                       // выводим в монитор порта что пытаемся подкл.
      }
    }


    void MQTT()                                  // Публикуем топик с состоянием режима
    {
      if (millis() - last_mls3 > 2000)           // Периодичность публикации топика раз в 2 сек.
      {
        last_mls3 = millis();
        client.publish(relays_topic1, String(regim1).c_str());
        client.publish(relays_topic2, String(regim2).c_str());
      }
    }

    void loop() {

      client.loop();
      MQTT();
      button1();
      button2();

      if (millis() - last_mls > 300000) {    // Проверка подключений раз в 300 сек. (5 минут)
        last_mls = millis();
        reconnect_server();
      }

      if (millis() - last_mls4 > 500) {      // Проверка подключений раз в 0,5 сек
        last_mls4 = millis();
        svet();
      }
    }