• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

Otto17

New member
Есть Скетч на 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. Код написан в среде Arduino IDE.
Помогите пожалуйста, кто знает как это сделать))
Код:
#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();
  }
}
 

Shyster

New member
Делается легко:
1. При нажатии кнопки загружаете в переменную текущее время если флаг = false, продолжаете работать, ставите флаг = true чтоб повторно не перетирать время.
2. Проверяяете, если кнопка отжата и флаг = true, сколько прошло времени, ставите флаг = false. ну и по времени принимаете решение.
 

Otto17

New member
Делается легко:
1. При нажатии кнопки загружаете в переменную текущее время если флаг = false, продолжаете работать, ставите флаг = true чтоб повторно не перетирать время.
2. Проверяяете, если кнопка отжата и флаг = true, сколько прошло времени, ставите флаг = false. ну и по времени принимаете решение.
с программированием трудно у меня, если не сложно, пример покажите реализации пожалуйста.)
 
пример покажите реализации пожалуйста
например так:

Код:
  uint32_t cur_ms = millis();
  bool but0_pressed = !digitalRead( setting_pin); // true - кнопка нажата
  if ( !setting_begin && but0_pressed) // начало отсчета для установок
  {
    setting_begin = true;
    setting_ms = cur_ms;
  }
  else if ( setting_begin && !but0_pressed) // кнопка отпущена
  {
    setting_begin = false;
    uint32_t delta_ms = cur_ms - setting_ms;
    if ( delta_ms > 100 && delta_ms < 1000) // кратковременное нажатие
    {
        //действие на короткое нажатие
    }
  }
  else if ( setting_begin && but0_pressed && (cur_ms - setting_ms) > 2000) // держим больше 2 сек
  {
        //действие на зажатие кнопки
  }
 

Otto17

New member
Неблина что-то не получается, путаница с функциями, что не так:

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

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

boolean flag = false;
int setting_ms = 0;

***

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 > 1) {              // если действующий режим > второго, то...
      regim1 = 0;                  // возвращаемся на нулевой режим
    }
  }

  uint32_t cur_ms = millis();
  bool but0_pressed = !digitalRead(BUTTON_1); // true - кнопка нажата
  if (!flag && but0_pressed) // начало отсчета для установок
  {
    flag = true;
    setting_ms = cur_ms;
  }
  else if ( flag && !but0_pressed) // кнопка отпущена
  {
    flag = false;
    uint32_t delta_ms = cur_ms - setting_ms;
    if ( delta_ms > 100 && delta_ms < 1000) // кратковременное нажатие
    {
      //действие на короткое нажатие
      if (regim1 == 0) {
        Status1 = true;
        digitalWrite(RELAY_1, Status1);
      }
      if (regim1 == 1) {
        Status1 = false;
        digitalWrite(RELAY_1, Status1);
      }
    }
  }
  else if ( flag && but0_pressed && (cur_ms - setting_ms) > 2000) // держим больше 2 сек
  {
    //действие на зажатие кнопки
    pir();
    regim1 == 2;
  }


  lastbtnStat1 = btnPress1;
}
 
Сверху Снизу