• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP-01S + MQTT + проходной выключатель

skaf

New member
Всем доброго времени суток. Хочу организовать в комнате выключение света как через выключатель, так и через mqtt. Компоненты следующие: готовое реле 10 А с оптомуфтой и обвзякой (с Китая), esp-01s (тоже из поднебесной), блок питания 3.3 В, проходной переключатель. Соответственно на реле и на esp-01s подаю 3.3 В, реле подключаю к пину 0, через проходной переключатель на пин 2 подаю/прерываю +3.3 В (т.е. одна клемма переключателя остается пустой). Скетч залил вот этот:
C:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "ssid";
const char* password = "pass";
const char* mqtt_server = "192.168.1.10";

#define mqtt_login "login"                       
#define mqtt_password "pass"
#define RELAY_1 0                               // Реле №1
#define BUTTON_1 2                              // Кнопочный выключатель №1
#define relays_topic "Switch"                  // Топик реле №1

WiFiClient espClient;
PubSubClient client(espClient);
//long lastMsg = 0;
//long last_mls = millis();
char msg[50];
//int value = 0;
//int diff = 1;
boolean rState1 = false;
boolean btnPress = false;
boolean lastbtnStat = false;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
 
  if ((char)payload[0] == '1') {
      rState1 = true;
      digitalWrite(RELAY_1, rState1);
  }
  else {
      rState1 = false;
      digitalWrite(RELAY_1, rState1);
  }
}

void buttonF() {
  btnPress = digitalRead(BUTTON_1);
 
  if (btnPress != lastbtnStat){
    delay(30); // защита от дребезга
    btnPress = digitalRead(BUTTON_1);
    
    if(btnPress != lastbtnStat){
      rState1 = !rState1;
      digitalWrite(RELAY_1, rState1);
      
      // публикуем изменение состояния реле на брокер
      client.publish(relays_topic, String(rState1).c_str(), true);
      
      lastbtnStat = btnPress;
    }   
  } 
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_login, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(relays_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(RELAY_1, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  pinMode(BUTTON_1, INPUT);
  digitalWrite(RELAY_1, rState1);
  Serial.begin(9600);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  lastbtnStat = digitalRead(BUTTON_1);
}

void loop() {
  client.loop();
 
  if (!client.connected()) {
    reconnect();
  }
 
  buttonF();
}
Т.е. смысл какой: вносятся изменения в топик либо через клиент, либо сама ESP, когда изменяется состояние пина 2. Соответственно когда в топике происходят изменения esp щелкает релюшкой.
Проблема следующая: через клиент работает все четко, а вот через переключатель - очень странно. Логики нет. Может сработать несколько раз, может вообще не откликаться. В итоге у esp срабатывает WDT и она перезагружается. Менял местами пины (реле и переключатель) - эффекта ноль. Менял, также, скорость порта со 115200 на 9600 - аналогично...Подскажите, пожалуйста, куда еще копать? Спасибо.
 

ravend

Member
Всем доброго времени суток. Хочу организовать в комнате выключение света как через выключатель, так и через mqtt. Компоненты следующие: готовое реле 10 А с оптомуфтой и обвзякой (с Китая), esp-01s (тоже из поднебесной), блок питания 3.3 В, проходной переключатель. Соответственно на реле и на esp-01s подаю 3.3 В, реле подключаю к пину 0, через проходной переключатель на пин 2 подаю/прерываю +3.3 В (т.е. одна клемма переключателя остается пустой). Скетч залил вот этот:
C:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "ssid";
const char* password = "pass";
const char* mqtt_server = "192.168.1.10";

#define mqtt_login "login"                     
#define mqtt_password "pass"
#define RELAY_1 0                               // Реле №1
#define BUTTON_1 2                              // Кнопочный выключатель №1
#define relays_topic "Switch"                  // Топик реле №1

WiFiClient espClient;
PubSubClient client(espClient);
//long lastMsg = 0;
//long last_mls = millis();
char msg[50];
//int value = 0;
//int diff = 1;
boolean rState1 = false;
boolean btnPress = false;
boolean lastbtnStat = false;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
      rState1 = true;
      digitalWrite(RELAY_1, rState1);
  }
  else {
      rState1 = false;
      digitalWrite(RELAY_1, rState1);
  }
}

void buttonF() {
  btnPress = digitalRead(BUTTON_1);

  if (btnPress != lastbtnStat){
    delay(30); // защита от дребезга
    btnPress = digitalRead(BUTTON_1);
  
    if(btnPress != lastbtnStat){
      rState1 = !rState1;
      digitalWrite(RELAY_1, rState1);
    
      // публикуем изменение состояния реле на брокер
      client.publish(relays_topic, String(rState1).c_str(), true);
    
      lastbtnStat = btnPress;
    } 
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_login, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(relays_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(RELAY_1, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  pinMode(BUTTON_1, INPUT);
  digitalWrite(RELAY_1, rState1);
  Serial.begin(9600);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  lastbtnStat = digitalRead(BUTTON_1);
}

void loop() {
  client.loop();

  if (!client.connected()) {
    reconnect();
  }

  buttonF();
}
Т.е. смысл какой: вносятся изменения в топик либо через клиент, либо сама ESP, когда изменяется состояние пина 2. Соответственно когда в топике происходят изменения esp щелкает релюшкой.
Проблема следующая: через клиент работает все четко, а вот через переключатель - очень странно. Логики нет. Может сработать несколько раз, может вообще не откликаться. В итоге у esp срабатывает WDT и она перезагружается. Менял местами пины (реле и переключатель) - эффекта ноль. Менял, также, скорость порта со 115200 на 9600 - аналогично...Подскажите, пожалуйста, куда еще копать? Спасибо.
Подозреваю, что такое поведение из-за некорректно реализованной защиты от дребезга. Фигурирует задержка в 30 миллисекунд, т.е. пока кнопка зажата, состояние переключается циклично, 33 раза в секунду, при отпускании кнопки результат будет 50/50, т.е. случайный (а не одно нажатие, - одно изменение состояния). Откуда wdt? - скорей всего pubsub клиент ставит в очередь publish (33 раза в секунду, пока зажата кнопка), и его очередь переполняет память.
 
  • Like
Реакции: skaf

skaf

New member
Подозреваю, что такое поведение из-за некорректно реализованной защиты от дребезга. Фигурирует задержка в 30 миллисекунд, т.е. пока кнопка зажата, состояние переключается циклично, 33 раза в секунду, при отпускании кнопки результат будет 50/50, т.е. случайный (а не одно нажатие, - одно изменение состояния). Откуда wdt? - скорей всего pubsub клиент ставит в очередь publish (33 раза в секунду, пока зажата кнопка), и его очередь переполняет память.
Ага, логично, спасибо. А каким образом лучше реализовать защиту? Аппаратно или программно? В интернетах рекомендуют ставить сопротивление и емкость в разрыв 3.3 В и пина esp-01 для переключателя - это, если, аппаратно. Правда, боюсь с номиналами прогадать. И сразу в догонку - программную защиту нужно будет убрать, если реализовать аппаратную? Спасибо.
 

nikolz

Well-known member
во-первых, надо задействовать прерывание от пина и тогда WDT не будет срабатывать
--------------------
во-вторых, можно выключатель повесить на RST т е
нажимаете ESP рестартует переключает свет и уходит в ожидание сигнала по wifi
-------------------------------------------
в-третьих,
так как включение выключателем это сравнительно медленный процесс то можно на пин к которому подключен
выключатель повесить на землю от 1 до 100 мкф и на питание резистор от 10 до 100 к.
При нажатии выключателя на кондере к.з. и он разрядится, на пине будет ноль
При этом дребезга не будет так как кратковременное размыкание выключателя недостаточно для заряда емкости через внутренний резистор ESP либо внешний в 10...100 к. Время разряда через выключатель будет в 1000 раз меньше чем время заряда через резистор.
 
  • Like
Реакции: skaf
Сверху Снизу