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

Nedaří se vám s projektem a nenašli jste vhodné místo, kde se zeptat? Napište sem.
Pravidla fóra
Tohle subfórum je určeno pro konzultaci ucelených nápadů, popřípadě řešení komplexnějších projektů, které opravdu není možné rozdělit na menší části.
Většinu problémů jde rozdělit na menší a ptát se na ně v konkrétních subfórech.
Odpovědět
sivlecrash
Příspěvky: 2
Registrován: 17 úno 2018, 19:40

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

Příspěvek od sivlecrash » 17 úno 2018, 21:05

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

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Bydliště: Poprad
Kontaktovat uživatele:

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

Příspěvek od martinius96 » 17 úno 2018, 22:22

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.
Naposledy upravil(a) martinius96 dne 17 úno 2018, 22:22, celkem upraveno 1 x.

jankop
Příspěvky: 1034
Registrován: 06 zář 2017, 20:04
Bydliště: Brno
Kontaktovat uživatele:

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

Příspěvek od jankop » 17 úno 2018, 22:22

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.

Uživatelský avatar
BlindP
Příspěvky: 39
Registrován: 23 črc 2017, 00:46

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

Příspěvek od BlindP » 18 úno 2018, 00:01

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. ;)

sivlecrash
Příspěvky: 2
Registrován: 17 úno 2018, 19:40

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

Příspěvek od sivlecrash » 18 úno 2018, 08:41

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

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host