• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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;
}
 
Сверху Снизу