Stránka 1 z 1

Žaluzie, Motor 12V DC, L293D, ESP8266, MQTT, Node-RED

Napsal: 17 úno 2018, 21:05
od sivlecrash
Dobrý den,
ovládám žaluzie pomocí vizualizace Node-RED Dashboard, tak že přes MQTT server zašlu informaci 0 - 100% pro nastavení žaluzie nebo lamely.
V projektu nemám dořešený koncový spínač v horní části žaluzie, o spodním kontaktu neuvažuji, kvůli vzhledu.
Dále v projektu postrádám stav žaluzie po výpadku.
Snažil jsem se pročítat různé fóra, ale bez kloudného výsledku.
Zasekl jsem se nad koncovým spínačem. Prosím o nakopnutí, jak zastavit motor koncovým spínačem, když právě probíhá zpoždění mezi zapnutím a vypnutím motoru? funkce - "delay(timedown);"

Kód: Vybrat vše

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

//L293D
//L293D VIN, GND - 12V DC
//L293D A-, A+ - Motor 12V DC
//Pin D1mini 3.3V - L293D VCC
//Pin D1mini GND - L293D GND
//Motor A
const int motorA1  = D5;  // Pin D1mini 5 - L293D IN1
const int motorA2  = D6;  // Pin D1mini 6 - L293D IN2
//Motor B
const int motorB3  = D7; // Pin D1mini 7 - L293D IN3
const int motorB4  = D8;  // Pin D1mini 8 - L293D IN4


// WIFI connection details, NETWORK static IP...
const char* ssid     = "Pokus";
const char* password = "Pokus456Password";
IPAddress ip(192, 168, 100, 182);
IPAddress gateway(192, 168, 100, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns1(0, 0, 0, 0);
IPAddress dns2(0, 0, 0, 0);

// IP address = Raspberry Pi - MQTT mosquitto
const char* mqtt_server = "192.168.100.6";

// Name D1mini = D1mini001
WiFiClient D1mini001;
PubSubClient client(D1mini001);

long timeheight = 10000; // čas žaluzie dolů (ms) změnit dle žaluzie
long timeslat = 2000; // čas přejezdu lamely (ms) změnit dle žaluzie
long timestatus = 0; // poslední nastavená (ms)
long heightstatus; // poslední nastavená (%)
long slatstatus; // poslední nastavená (%)
boolean drivingdirection = false; // true=down  false=up
long messagevaluelong; // přijatá hodnota 0-100% převedená na long
long timeset; // vypočítaný čas motoru

#include <WEMOS_SHT3X.h>
SHT3X sht30(0x45);
int Temp;
int Hum;

// Timers auxiliar variables
long wait;

// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
  delay(10);

  //WIFI
  Serial.println("-");
  Serial.print("Connecting to ");
  Serial.println(ssid);
  // Static IP Setup Info Here...
  WiFi.config(ip, gateway, subnet, dns1, dns2);
  // Start Server
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected, D1mini IP address: ");
  Serial.println(WiFi.localIP());
}
// Tato část se provádí, když někdo publikuje zprávu
void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageValue;
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageValue += (char)message[i];
  }
  Serial.println();
  messagevaluelong = (messageValue.toInt()); //převede string hodnotu na číselnou long // 0-100%
  if (topic == "room/blind01/height_set") {
    timeset = (timeheight / 100) * messagevaluelong;
    Serial.print("timeset:");
    Serial.println(timeset);

    if (timeset > timestatus) {
      long timedown = timeset - timestatus;
      Serial.print("start motor dolu, cas: ");
      Serial.println(timedown);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, HIGH);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, HIGH);
      delay(timedown);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      timestatus = timeset;
      heightstatus = messagevaluelong;
      if (timedown > timeslat) {
        slatstatus = 100;
      }
      if ((timeslat > timedown) && (drivingdirection = false)) {
        float calculation = (100 / (float)timeslat) * timedown;
        slatstatus = calculation;
      }
      else {
        slatstatus = 100;
      }
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      drivingdirection = true;

      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
    else if (timeset < timestatus) {
      long timeup = timestatus - timeset;
      Serial.print("start motor nahoru cas: ");
      Serial.println(timeup);
      digitalWrite(motorA1, HIGH);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, HIGH);   digitalWrite(motorB4, LOW);
      delay(timeup);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      timestatus = timeset;
      heightstatus = messagevaluelong;
      if (timeup > timeslat) {
        slatstatus = 0;
      }
      if ((timeslat > timeup) && (drivingdirection = true)) {
        float calculation = (100 / (float)timeslat) * (timeslat - timeup);
        slatstatus = calculation;
      }
      else {
        slatstatus = 0;
      }
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      drivingdirection = false;
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
    else {
      Serial.println("Motor A&B STOP");
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
  }
  if (topic == "room/blind01/slat_set") {
    //timeset2 = (timeheight / 100) * messagevaluelong;
    //Serial.print("timeset:");
    //Serial.println(timeset);

    if (messagevaluelong > slatstatus) {
      long timedownslat = (timeslat / 100) * (messagevaluelong - slatstatus);
      Serial.print("start motor dolu, cas: ");
      Serial.println(timedownslat);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, HIGH);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, HIGH);
      delay(timedownslat);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      timestatus = timestatus + timedownslat;
      slatstatus = messagevaluelong;
      float calculation = (100 / (float)timeheight) * timestatus;
      heightstatus = calculation;
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
    else if ((messagevaluelong < slatstatus) && (timestatus >= timeslat)) {
      long timeupslat = (timeslat / 100) * (slatstatus - messagevaluelong);
      Serial.print("start motor nahoru cas: ");
      Serial.println(timeupslat);
      digitalWrite(motorA1, HIGH);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, HIGH);   digitalWrite(motorB4, LOW);
      delay(timeupslat);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      timestatus = timestatus - timeupslat;
      slatstatus = messagevaluelong;
      float calculation = (100 / (float)timeheight) * timestatus;
      heightstatus = calculation;
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
    else if ((messagevaluelong < slatstatus) && (timestatus < timeslat)) {
      long timeupslat2 = timestatus;
      Serial.print("start motor nahoru cas: ");
      Serial.println(timeupslat2);
      digitalWrite(motorA1, HIGH);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, HIGH);   digitalWrite(motorB4, LOW);
      delay(timeupslat2);
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      timestatus = 0;
      slatstatus = 0;
      heightstatus = 0;
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
    else {
      Serial.println("Motor A&B STOP");
      digitalWrite(motorA1, LOW);   digitalWrite(motorA2, LOW);   digitalWrite(motorB3, LOW);   digitalWrite(motorB4, LOW);
      Serial.print("height status: ");
      Serial.print(heightstatus);
      Serial.print(" % = ");
      Serial.print(timestatus);
      Serial.println(" ms");
      Serial.print("slat status: ");
      Serial.print(slatstatus);
      Serial.println(" %");
      float value3 = heightstatus;
      static char heightstatusprint[7];
      dtostrf(value3, 6, 2, heightstatusprint);
      client.publish("room/blind01/heightstatus", heightstatusprint);
      float value4 = slatstatus;
      static char slatstatusprint[7];
      dtostrf(value4, 6, 2, slatstatusprint);
      client.publish("room/blind01/slatstatus", slatstatusprint);
    }
  }
}
// Tato část znovu připojí D1mini k MQTT serveru
// Případně přidat nové "topic"
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("MQTT connection...");
    // Pokus o připojeník MQTT serveru
    if (client.connect("D1miniMQTTclient001")) {
      Serial.println("connected");
      client.subscribe("room/blind01/height_set");
      client.subscribe("room/blind01/slat_set");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
// Nastaví zprostředkovatele mqtt a nastaví funkci zpětného volání
// The callback function is what receives messages and actually controls the LEDs
void setup() {

  pinMode(motorA1, OUTPUT);
  pinMode(motorA2, OUTPUT);
  pinMode(motorB3, OUTPUT);
  pinMode(motorB4, OUTPUT);
  digitalWrite(motorA1, LOW);
  digitalWrite(motorA2, LOW);
  digitalWrite(motorB3, LOW);
  digitalWrite(motorB4, LOW);

  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(100);
}
Děkuji

Re: Žaluzie, Motor 12V DC, L293D, ESP8266, MQTT, Node-RED

Napsal: 17 úno 2018, 22:22
od martinius96
Odpoveď: Nepoužívať delay. Keď to dáš na 100% otvoriť žalúzie, tak máš koncový spínač, ktorý sa v loope overuje.. if(digitalread(Tvojspinac)==HIGH){
//zastav pohyb a odosli info o vykonani akcie
}
Riešil by som to na takýto štýl. S MQTT som nikdy nerobil, ale takto sa to štandardne robí.
Ak je pohyb na menej ako 100%, tak tam si použi delay. Ale ak je 100%, overuj iba stav tlačidla. Koncový spínač funguje totožne ako obyčajné tlačidlo.

Re: Žaluzie, Motor 12V DC, L293D, ESP8266, MQTT, Node-RED

Napsal: 17 úno 2018, 22:22
od jankop
Odměřovat kritické děje pomocí delay má opravdu k optimálnosti daleko. Protože funkce delay() zastavuje většinu procesů, nemáš při jejím použití podle mě jinou možnost, než koncovým kontaktem vyvolat přerušení a motory vypnout. Přerušení by mělo fungovat i při delay().
Jinou alternativou je prostě zapnout motor a ve smyčce číst stav koncového spínače. Prostě se tomu delay vyhnout. Stav žaluzií po výpadku nelze v tvém případě řešit rozumně jinak, než najet na koncový spínač a zjistit tak výchozí polohu.

Re: Žaluzie, Motor 12V DC, L293D, ESP8266, MQTT, Node-RED

Napsal: 18 úno 2018, 00:01
od BlindP
Ahoj, jak bylo řečeno nepoužívej delay použij millis. Nějakou inspiraci najdeš zde - https://gist.github.com/blindp/77805e4a ... 0d86e55e51
Blokování koncovým spínačem si budeš muset dopsat. ;)

Re: Žaluzie, Motor 12V DC, L293D, ESP8266, MQTT, Node-RED

Napsal: 18 úno 2018, 08:41
od sivlecrash
Děkuji za nakopnutí :)
Přerušení jsem zkoušel při použití D1mini-Motor-Shield, na serialu se vytiskla hláška že motor má zastavit, ale nezatavil. Teď mi došlo, že to bylo nejspíše způsobeno komunikací I2C. Tento modul jsem přestal používat, byli s tím jen problémy, nyní to zkusím s L293D. ;)
Pokud nevyjde přerušení, tak u pravím kód pro 0% a koncový spínač. Děkuji