King-Art TuYa Curtain - настенный Wifi выключатель с сенсорным управлением. Основан на микросхеме ESP8266 и может управлять двумя реле.
Для управления выключателем  в локальной сети по протоколу MQTT необходим  MQTT брокер 
mosquitto, предустановленный на компьютер или роутер с прошивкой OpenWRT. Также необходим MQTT клиент такой как 
MQTT Dash для Андроид или же что-то более масштабное такое как умный дом 
MajorDoMo.
Подготовка к прошивке выключателя.
Снимаем крышку, для этого отвёрткой снизу поддеваем Touch панель.
Снимаем плату. 
Все контакты, в том числе и GPIO0 для перевода чипа в режим записи прошивки, выведены на плате.
Подпаиваемся к контактам.
Для прошивки чипа нужен  USB-TTL конвертер, к примеру CP2104 CNT-003A работающий с напряжением 3.3В.
Соединяем конвертер и выключатель 4 проводами следующим образом:
GND выключатель     - GND конвертер
RX выключатель        - TX конвертер
TX выключатель        - RX конвертер
3.3В выключатель      - 3.3В конвертер (VCC)
GPIO0 выключатель  - GND конвертер
Осторожно напряжение должно быть не более 3.3В.
 
В Arduino IDE устанавливаем настройки чипа в меню Инструменты ->
Если конвертер используете впервые, то в разделе "Порт"  запоминаем всё что там есть.
После подключения конвертера и установки драйверов, появится ещё один порт, его и нужно будет выбрать для прошивки выключателя. В моём случае это 12 порт.
Простейший скетч для выключателя.
Остаётся только присвоить значения переменным
- ssid                - название Wi-Fi сети
- password       - пароль от Wifi
- mqtt_server   - IP адрес MQTT брокера в локальной сети к примеру 192.168.178.2
- NAME          - Имя выключателя к примеру kitchenSwitch значит команды на вкл/выкл будут ходить по пути kitchenSwitch/status, а подтверждения по пути kitchenSwitch/alive.
Если MQTT брокер защищён логином и паролем необходимо так же присвоить переменным mqtt_user и mqtt_password правильные значения. И не забыть убрать слеш // перед ними.
Вот теперь можно заливать скетч.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
//--------------WIFI---------------------//
const char* ssid = "................";  // SSID Имя Wifi
const char* password = "............";  // Введи пароль от Wifi
const char* mqtt_server = ".........";  // IP адрес MQTT брокера
#define NAME  "..........."           // Имя выключателя
//const char* mqtt_user = "majordomo";
//const char* mqtt_password = "123456";
/*/--------------MQTT и топики----------------/*/
const char *COMAND = NAME "/comand";
const char *TOPIC_IP = NAME "/IP";           // отправляет IP
const char *TOPIC_INFO = NAME "/Info";
const char *STATUS_TOPIC =  NAME "/status";
const char *ALIVE_TOPIC =  NAME "/alive";
// #define NeuStart    "Vremja/timeNow"      // Время нового старта
/*/--------------Пины-----------------/*/
#define BUTTON_PIN1 5
#define RELAY_PIN1 15
#define LED_PIN 0
#define BUTTON_PIN2 14
#define BUTTON_PIN3 12
#define RELAY_PIN3 13
/*/--------------Переменные-----------------/*/
int releStatus1 = 0;
int releAlive1 = 0;
int releStatus3 = 0;
int releAlive3 = 0;
boolean Button1 = false;
boolean Button3 = false;
boolean sperButton1 = false;
boolean sperButton3 = false;
int tajmer = 0;
unsigned long lastMQTTCheck = -5000; //This will force an immediate check on init
boolean infoCom = false;
/*/--------------Инициализация----------------/*/
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  randomSeed(micros());
}
void reconnect() {
  while (!client.connected()) {
    digitalWrite(LED_PIN, HIGH); //LED off.
    if (client.connect(NAME)) {
      client.subscribe(COMAND);
      client.subscribe(STATUS_TOPIC);
      //client.subscribe(NeuStart);
      digitalWrite(LED_PIN, LOW);
    } else {
      delay(5000);
    }
  }
}
void callback(char* topic, byte* payload, unsigned int length) {
  // Преобразование входящего массива байтов в строку
  payload[length] = '\0'; // Null terminator используется для завершения массива char
  String message = (char*)payload;
  String top = topic;
  /*-------------Info ESP-----------------*/
  if (top == COMAND) {
    if (message == "Info") {
      String esp = "KingArt Tuya_3, BUTTON: 5.14.12, Relay: 15.X.13, и т.д.";
      client.publish(TOPIC_INFO, esp.c_str(), true);
    } else if (message == "IP") {
      infoCom = false;
    }
  }
  /*-------------Новый старт-----------------
  if (top == NeuStart) {
    if (message == "03:06") {
      ESP.reset();
    }
  }*/
  if (top == STATUS_TOPIC) {
    if (message == "1" || message == "ON") {
      digitalWrite(RELAY_PIN3, LOW);
      releStatus1 = 1;
    }
    else if (message == "3" || message == "STOP") {
      releStatus3 = 0;
      releStatus1 = 0;
      client.publish(ALIVE_TOPIC, String("3").c_str(), true);
    }
    else if (message == "0" || message == "OFF") {
      digitalWrite(RELAY_PIN1, LOW);
      releStatus3 = 1;
    }
  }
}
void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN1, OUTPUT);
  digitalWrite(RELAY_PIN1, LOW);
  pinMode(BUTTON_PIN1, INPUT_PULLUP);
  pinMode(BUTTON_PIN2, INPUT_PULLUP);
  pinMode(RELAY_PIN3, OUTPUT);
  digitalWrite(RELAY_PIN3, LOW);
  pinMode(BUTTON_PIN3, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH); //LED off.
  setup_wifi();
  ArduinoOTA.setHostname(NAME);               // Задаем имя сетевого порта
  ArduinoOTA.begin();                             // Инициализируем OTA
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}
void loop() {
  ArduinoOTA.handle();   // Всегда готовы к прошивке
  if (millis() - lastMQTTCheck >= 5000) {
    reconnect();
    lastMQTTCheck = millis();
  }
  client.loop();
  delay(100);
  /*---- Отправляем IP при старте МК и по запросу ----*/
  if (!infoCom && WiFi.status() == WL_CONNECTED) {
    String ipInfo = WiFi.localIP().toString();
    client.publish(TOPIC_IP, ipInfo.c_str(), true);
    infoCom = true;
  }
  
  /*---- Опрос кнопок ----*/
  if (digitalRead(BUTTON_PIN1) == 0) {
    digitalWrite(RELAY_PIN3, LOW);
    delay(100);
    releStatus1 = !releStatus1;
  }
  if (digitalRead(BUTTON_PIN2) == 0) {
    releStatus1 = 0;
    releStatus3 = 0;
    client.publish(ALIVE_TOPIC, String("3").c_str(), true);
  }
  if (digitalRead(BUTTON_PIN3) == 0) {
    digitalWrite(RELAY_PIN1, LOW);
    delay(100);
    releStatus3 = !releStatus3;
  }
  /*---- Управление реле ----*/
  if (releAlive1 != releStatus1) {
    if (releStatus1 == 1) {
      digitalWrite(RELAY_PIN3, LOW);
      delay(100);
      digitalWrite(RELAY_PIN1, HIGH);
      releAlive1 = releStatus1;
      client.publish(ALIVE_TOPIC, String("1").c_str(), true);
      tajmer = 1;
    } else {
      digitalWrite(RELAY_PIN1, LOW);
      releAlive1 = releStatus1;
      client.publish(ALIVE_TOPIC, String("3").c_str(), true);
    }
  }
  if (releAlive3 != releStatus3) {
    if (releStatus3 == 1) {
      digitalWrite(RELAY_PIN1, LOW);
      delay(100);
      digitalWrite(RELAY_PIN3, HIGH);
      releAlive3 = releStatus3;
      client.publish(ALIVE_TOPIC, String("0").c_str(), true);
      tajmer = 1;
    } else {
      digitalWrite(RELAY_PIN3, LOW);
      releAlive3 = releStatus3;
      client.publish(ALIVE_TOPIC, String("3").c_str(), true);
    }
  }
    /*---- Таймер отключения реле ----*/
  if (tajmer != 0) {
    if (tajmer >= 150) {
      digitalWrite(RELAY_PIN1, LOW);
      digitalWrite(RELAY_PIN3, LOW);
      delay(100);
      releStatus1 = 0;
      releStatus3 = 0;
      delay(100);
      tajmer = 0;
    } else {
      tajmer++;
    }
  }
  delay(100);
}
И прошиваем чип. Вот и всё. Удачи
 
Комментарии
Отправить комментарий