Ожидание выключения реле после смс запроса

Тема в разделе "Arduino & Shields", создана пользователем overdast, 11 янв 2023.

Метки:
  1. overdast

    overdast Нуб

    Не могу добиться задержки выключения реле после получения СМС. После получения СМС Rele2 переходит в режим LOW, но обратно в режим HIGH не выходит вообще и СМС не отправляет.
    Что я делаю не так?

    Код (C++):

    #include "TM1637.h"
    #include "DHT.h"
    #include <Wire.h>
    #include <SoftwareSerial.h>

    #define Rele 10  // Пин на реле
    #define Rele2 11
    #define CLK 12
    #define DIO 13
    #define pinPower A0   // Пин датчика напряжения
    #define DHTPin A1     // Пин датчика DHT22
    #define pinSensor A5  // Пин датчика влажности почвы HM-390

    #define pinSensor_MIN 230
    #define pinSensor_MAX 600
    #define INTERVAL 10000 * 3
    #define INTERVAL2 20000 * 8
    #define DHTTYPE DHT22

    int analogInput = A0;
    float vout = 0.0;
    float vin = 0.0;
    float R1 = 28200.0;
    float R2 = 7500.0;
    int value = 0;

    unsigned int humidity = 0;
    unsigned long waitTime = 0;

    char incomingByte;
    String inputString;

    float t;  // Температура
    float h;  // Влажность воздуха
    float p;  // Влажность почвы
    float v;

    SoftwareSerial mySerial(7, 8);  // пины RX:TX
    TM1637 tm1637(CLK, DIO);        // Дисплей HW-069
    DHT dht(DHTPin, DHTTYPE);

    void setup() {
      pinMode(Rele2, OUTPUT);
      digitalWrite(Rele2, HIGH);
      pinMode(Rele, OUTPUT);
      digitalWrite(Rele, HIGH);
      delay(100);
      pinMode(pinPower, INPUT);
      delay(1000);
      pinMode(9, OUTPUT);  // Атозапуск SIM900 при первом всключении
      digitalWrite(9, LOW);
      delay(1000);
      digitalWrite(9, HIGH);
      delay(2000);
      digitalWrite(9, LOW);
      delay(3000);

      Serial.begin(9600);
      delay(1000);
      mySerial.begin(9600);

      while (!mySerial.available()) {     // Зацикливаем и ждем инициализацию SIM900
        mySerial.println("AT");           // Отправка команды AT
        delay(1000);                      // Пауза
        Serial.println("Connecting...");  // Печатаем текст
      }
      Serial.println("Connected!");           // Печатаем текст
      mySerial.println("AT+CMGF=1");          // Отправка команды AT+CMGF=1
      delay(1000);                            // Пауза
      mySerial.println("AT+CNMI=1,2,0,0,0");  // Отправка команды AT+CNMI=1,2,0,0,0
      delay(1000);                            // Пауза
      mySerial.println("AT+CMGL=\"REC UNREAD\"");

      delay(1000);

      tm1637.init();

      dht.begin();  // запускаем датчик DHT22
      tm1637.set(BRIGHTEST);
    }

    void loop() {
      int Temperature = dht.readTemperature();
      int Humidity = dht.readHumidity();
      int valueSensor = analogRead(pinSensor);
      int powSensor = analogRead(pinPower);


      if (mySerial.available()) {  // Проверяем, если есть доступные данные
        delay(100);                // Пауза

        while (mySerial.available()) {     // Проверяем, есть ли еще данные.
          incomingByte = mySerial.read();  // Считываем байт и записываем в переменную incomingByte
          inputString += incomingByte;     // Записываем считанный байт в массив inputString
        }

        delay(10);                    // Пауза
        Serial.println(inputString);  // Отправка в "Мониторинг порта" считанные данные
        inputString.toUpperCase();    // Меняем все буквы на заглавные

        if (inputString.indexOf("DATA") > -1) {
          p = analogRead(pinSensor);
          t = dht.readTemperature();
          h = dht.readHumidity();
          value = analogRead(pinPower);
          vout = (value * 5.0) / 1024.0;
          vin = vout / (R2 / (R1 + R2));
          v = (vin);

          sms(String("Temper: " + String(t) + " C " + " Humid: " + String(h) + " Pochva: " + String(p) + " Volt: " + String(v)), String("+7xxxxxxxxxx"));
        }

        delay(10);

        if (inputString.indexOf("POLIV1") > -1) { // Смс с запросом на полив
        digitalWrite(Rele2, LOW);     // Включаем реле
        if (waitTime == 0 || millis() - waitTime > INTERVAL2){    // Ожидание автоматического выключения
        digitalWrite(Rele2, HIGH); // Вылючаем реле
        }
        waitTime = millis();
          sms(String("Rele2 - PolifConch"), String("+7xxxxxxxxx")); // Смс полив окончен
        }

       

        delay(50);

        if (inputString.indexOf("OK") == -1) {
          mySerial.println("AT+CMGDA=\"DEL ALL\"");
          delay(1000);
        }

        inputString = "";
      }

      Serial.println(valueSensor);
      value = analogRead(pinPower);
      vout = (value * 5.0) / 1024.0;
      vin = vout / (R2 / (R1 + R2));
      if (isnan(Humidity) || isnan(Temperature)) {
        Serial.println(F("Oshibka"));
        return;
      }

      int digitoneT = Temperature / 10;
      int digittwoT = Temperature % 10;

      int digitoneH = Humidity / 10;
      int digittwoH = Humidity % 10;

      tm1637.display(1, digitoneT);
      tm1637.display(2, digittwoT);
      tm1637.display(3, 12);

      delay(5000);

      tm1637.display(1, digitoneH);
      tm1637.display(2, digittwoH);
      tm1637.display(3, 15);

      delay(5000);

      Serial.print(F("INPUT V = "));
      Serial.println(vin, 2);
      Serial.print(F("Vlaga: "));
      Serial.print(Humidity);
      Serial.print(F(" %\t"));
      Serial.print(F("Tempera: "));
      Serial.print(Temperature);
      Serial.println(F(" °C "));

      delay(500);

      int humidityNow = analogRead(pinSensor);

      if (humidityNow != humidity) {
        humidity = humidityNow;
      }
      if ((waitTime == 0 || millis() - waitTime > INTERVAL) && humidity < pinSensor_MIN) {
        digitalWrite(Rele, LOW);
        delay(8000 * 2);
        digitalWrite(Rele, HIGH);
        waitTime = millis();
      }
    }

    void sms(String text, String phone)  // Процедура Отправка SMS
    {
      Serial.println("SMS send started");
      mySerial.println("AT+CMGS=\"" + phone + "\"");
      delay(500);
      mySerial.print(text);
      delay(500);
      mySerial.print((char)26);
      delay(500);
      Serial.println("SMS send complete");
      delay(2000);
    }
    Да код кривой, но мне он для личного пользования и до того как он выглядит мне интереса нету
     
  2. parovoZZ

    parovoZZ Гуру

    делаешь дебаг вставки в виде отладочной информации в UART порт и по нему смотришь, что вытворяет код.
     
  3. User248

    User248 Гик

    У вас так:
    Код (C++):

        if (waitTime == 0 || millis() - waitTime > INTERVAL2){    // Ожидание автоматического выключения
        digitalWrite(Rele2, HIGH); // Вылючаем реле
        }
        waitTime = millis();
     
    А надо так:
    Код (C++):

        if (waitTime == 0 || millis() - waitTime > INTERVAL2){    // Ожидание автоматического выключения
        digitalWrite(Rele2, HIGH); // Вылючаем реле
        waitTime = millis();
        }
     
    И ещё, у вас один таймер waitTime в двух местах используется. Нужно сделать отдельные.
    Код (C++):

        if (waitTime == 0 || millis() - waitTime > INTERVAL2){    // Ожидание автоматического выключения
        digitalWrite(Rele2, HIGH); // Вылючаем реле
        waitTime = millis();
        }
    ...
        if((waitTime2 ==0|| millis()- waitTime2 > INTERVAL)&& humidity < pinSensor_MIN){
        digitalWrite(Rele, LOW);
        delay(8000*2);
        digitalWrite(Rele, HIGH);
        waitTime2 = millis();
    }
     
     
    Последнее редактирование: 15 янв 2023
  4. User248

    User248 Гик

    А подобные макросы надо брать в скобки, чтобы не нарушился порядок математических операций.
    Код (C++):

    #define INTERVAL (10000 * 3)
     
     
    Ariadna-on-Line нравится это.
  5. overdast

    overdast Нуб

    Код (C++):
    if (inputString.indexOf("POLIV1") > -1) {
          digitalWrite(Rele2, LOW);
        } else if (waitTime2 == 0 || millis() - waitTime2 > INTERVAL) {
          digitalWrite(Rele2, HIGH);
          waitTime2 = millis();
          delay(1000);
          sms(String("Rele2 - PolifConch"), phoneNumber);
        }
    Так? Скорее всего действительно проблема была waitTime их должно быть две штуки.
    Как проверю сообщу какие будут успехи.
     
  6. overdast

    overdast Нуб

    К сожалению код не работает. Теперь он без отправки команды шлет смс с текстом PolifConch.
     
  7. User248

    User248 Гик

    Всё согласно условию. Не найдя в inputString нужного текста, срабатывает "else if" с заданным интервалом. Нужно добавить какую-то метку, что сообщение отправлено, чтобы условие больше не срабатывало.

    Например:
    Код (C++):

      static bool PolifConch = true;
      if (inputString.indexOf("POLIV1") > -1) {
        digitalWrite(Rele2, LOW);
        PolifConch = false;
      }
      else if ((waitTime2 == 0 || millis() - waitTime2 > INTERVAL) && !PolifConch) {
        digitalWrite(Rele2, HIGH);
        waitTime2 = millis();
        delay(1000);
        sms(String("Rele2 - PolifConch"), phoneNumber);
        PolifConch = true;
      }
     
     
    Последнее редактирование: 19 янв 2023
  8. overdast

    overdast Нуб

    Да действительно перестал слать смс, но INTERVAL не работает реле переключается через 30сек.
     
  9. User248

    User248 Гик

    10000 * 3 это и есть 30 секунд. Что не так?
     
  10. overdast

    overdast Нуб

    Там же два интервала. Использовал интервал2.
     
  11. User248

    User248 Гик

    Реле там тоже два. Уточните, какое из них имеете в виду.
     
  12. overdast

    overdast Нуб

    Rele2 должно работать с интервалом2.
     
  13. User248

    User248 Гик

    А если так:
    Код (C++):

      static bool PolifConch = true;
      if (inputString.indexOf("POLIV1") > -1) {
        digitalWrite(Rele2, LOW);
        PolifConch = false;
        waitTime2 = millis();
      }
      else if (millis() - waitTime2 > INTERVAL2 && !PolifConch) {
        digitalWrite(Rele2, HIGH);
        delay(1000);
        sms(String("Rele2 - PolifConch"), phoneNumber);
        PolifConch = true;
      }
     
     
  14. User248

    User248 Гик

    А это лучше заменить:
    Код (C++):

      if (mySerial.available()) {  // Проверяем, если есть доступные данные
        delay(100);                // Пауза

        while (mySerial.available()) {     // Проверяем, есть ли еще данные.
          incomingByte = mySerial.read();  // Считываем байт и записываем в переменную incomingByte
          inputString += incomingByte;     // Записываем считанный байт в массив inputString
        }
     
    На это:
    Код (C++):

      if (mySerial.available()) {  // Проверяем, если есть доступные данные
        inputString = mySerial.readString(); // Записываем считанную строку в массив inputString
     
     
  15. User248

    User248 Гик

    Ваш вариант тоже годится, но нужно добавить delay в цикле. Иначе может проскочить, и получится обрезанная строка.
    Код (C++):

      if (mySerial.available()) {  // Проверяем, если есть доступные данные
        while (mySerial.available()) {     // Проверяем, есть ли еще данные.
          incomingByte = mySerial.read();  // Считываем байт и записываем в переменную incomingByte
          inputString += incomingByte;     // Записываем считанный байт в массив inputString
          delay(5);                // Пауза, защита от пропусков
        }
     
     
  16. overdast

    overdast Нуб

    Нет теперь не выключает вообще.
    Код (C++):
    #include "TM1637.h"
    #include "DHT.h"
    #include <Wire.h>
    #include <SoftwareSerial.h>

    #define Rele 10  // Пин на реле
    #define Rele2 11
    #define CLK 12
    #define DIO 13
    #define pinPower A0   // Пин датчика напряжения
    #define DHTPin A1     // Пин датчика DHT22
    #define pinSensor A5  // Пин датчика влажности почвы HM-390

    #define pinSensor_MIN 230
    #define pinSensor_MAX 600
    #define INTERVAL (10000 * 3)
    #define INTERVAL2 (70000 * 8)
    #define DHTTYPE DHT22

    String phoneNumber = ("+7ххххххххххх");

    int analogInput = A0;
    float vout = 0.0;
    float vin = 0.0;
    float R1 = 30000.0;
    float R2 = 7500.0;
    int value = 0;

    unsigned int humidity = 0;

    float waitTime = 0;  // отсчёт времени
    float waitTime2 = 0;
    float lcdTime = 0;  // отсчёт времени
    static bool PolifConch = true;

    char incomingByte;
    String inputString;

    float t;  // Температура
    float h;  // Влажность воздуха
    float p;  // Влажность почвы
    float v;

    int Temperature = 0;
    int Humidity = 0;
    int valueSensor = 0;
    int powSensor = 0;

    bool tempVlaj = false;   // флаг вывода на экран т/в
    bool poliv = false;      // флаг полива
    bool smsOtchet = false;  // флаг для отправки смс по окончанию ролива

    SoftwareSerial mySerial(7, 8);  // пины RX:TX
    TM1637 tm1637(CLK, DIO);        // Дисплей HW-069
    DHT dht(DHTPin, DHTTYPE);

    void setup() {
      pinMode(Rele2, OUTPUT);
      digitalWrite(Rele2, HIGH);
      pinMode(Rele, OUTPUT);
      digitalWrite(Rele, HIGH);
      delay(100);
      pinMode(pinPower, INPUT);
      delay(500);
      pinMode(9, OUTPUT);  // Атозапуск SIM900 при первом всключении
      digitalWrite(9, LOW);
      delay(1000);
      digitalWrite(9, HIGH);
      delay(2000);
      digitalWrite(9, LOW);
      delay(3000);

      Serial.begin(9600);
      //delay(1000);
      mySerial.begin(9600);

      while (!mySerial.available()) {     // Зацикливаем и ждем инициализацию SIM900
        mySerial.println("AT");           // Отправка команды AT
        delay(500);                       // Пауза
        Serial.println("Connecting...");  // Печатаем текст
      }
      Serial.println("Connected!");           // Печатаем текст
      mySerial.println("AT+CMGF=1");          // Отправка команды AT+CMGF=1
      delay(500);                             // Пауза
      mySerial.println("AT+CNMI=1,2,0,0,0");  // Отправка команды AT+CNMI=1,2,0,0,0
      delay(500);                             // Пауза
      mySerial.println("AT+CMGL=\"REC UNREAD\"");

      delay(1000);

      tm1637.init();

      dht.begin();  // запускаем датчик DHT22
      tm1637.set(BRIGHTEST);
    }

    void loop() {
      int Temperature = dht.readTemperature();
      int Humidity = dht.readHumidity();
      int valueSensor = analogRead(pinSensor);
      int powSensor = analogRead(pinPower);


      if (isnan(Humidity) || isnan(Temperature)) {
        Serial.println(F("Oshibka DHT22"));
        // return;  //весь остальной код не будет исполняться после этого. либо в конец функции эту проверку, либо не использовать
      }

      if (mySerial.available()) {  // Проверяем, если есть доступные данные
        while (mySerial.available()) {     // Проверяем, есть ли еще данные.
          incomingByte = mySerial.read();  // Считываем байт и записываем в переменную incomingByte
          inputString += incomingByte;     // Записываем считанный байт в массив inputString
          delay(5);                // Пауза, защита от пропусков
        }

        //delay(10);                    // Пауза тут вообще не нужна
        Serial.println(inputString);  // Отправка в "Мониторинг порта" считанные данные
        inputString.toUpperCase();    // Меняем все буквы на заглавные

        if (inputString.indexOf("DATA") > -1) {
          p = analogRead(pinSensor);
          t = dht.readTemperature();
          h = dht.readHumidity();
          value = analogRead(pinPower);
          vout = (value * 5.0) / 1024.0;
          vin = vout / (R2 / (R1 + R2));
          v = (vin);

          sms(String("Temper: " + String(t) + " C " + " Humid: " + String(h) + " Pochva: " + String(p) + " Volt: " + String(v)), phoneNumber);
        }

        delay(10);

        if (inputString.indexOf("POLIV1") > -1) {
        digitalWrite(Rele2, LOW);
        PolifConch = false;
        waitTime2 = millis();
      }
      else if (millis() - waitTime2 > INTERVAL2 && !PolifConch) {
        digitalWrite(Rele2, HIGH);
        delay(1000);
        sms(String("Rele2 - PolifConch"), phoneNumber);
        PolifConch = true;
      }

        delay(10);

        if (inputString.indexOf("POLIVON") > -1) {
          digitalWrite(Rele2, LOW);
          delay(1000);
          sms(String("Rele2 - PolifON"), phoneNumber);
        }

        delay(10);

        if (inputString.indexOf("POLIVOFF") > -1) {

          digitalWrite(Rele2, HIGH);
          delay(1000);
          sms(String("Rele2 - PolifOff"), phoneNumber);
        }

        delay(10);

        if (inputString.indexOf("GOLYON") > -1) {

          digitalWrite(Rele, LOW);
          delay(1000);
          sms(String("Rele1 - PolifOn1"), phoneNumber);
        }

        delay(10);

        if (inputString.indexOf("GOLYOFF") > -1) {

          digitalWrite(Rele, HIGH);
          delay(1000);
          sms(String("Rele1 - PolifOff2"), phoneNumber);
        }

        delay(50);

        if (inputString.indexOf("OK") == -1) {
          mySerial.println("AT+CMGDA=\"DEL ALL\"");
          delay(1000);
        }

        inputString = "";
      }

      Serial.println(valueSensor);
      value = analogRead(pinPower);
      vout = (value * 5.0) / 1024.0;
      vin = vout / (R2 / (R1 + R2));
      if (isnan(Humidity) || isnan(Temperature)) {
        Serial.println(F("Oshibka"));
        return;
      }

      int digitoneT = Temperature / 10;
      int digittwoT = Temperature % 10;

      int digitoneH = Humidity / 10;
      int digittwoH = Humidity % 10;

      tm1637.display(1, digitoneT);
      tm1637.display(2, digittwoT);
      tm1637.display(3, 12);

      delay(5000);

      tm1637.display(1, digitoneH);
      tm1637.display(2, digittwoH);
      tm1637.display(3, 15);

      delay(5000);

      Serial.print(F("INPUT V = "));
      Serial.println(vin, 2);
      Serial.print(F("Vlaga: "));
      Serial.print(Humidity);
      Serial.print(F(" %\t"));
      Serial.print(F("Tempera: "));
      Serial.print(Temperature);
      Serial.println(F(" °C "));

      delay(500);

      int humidityNow = analogRead(pinSensor);

      if (humidityNow != humidity) {
        humidity = humidityNow;
      }
      if ((waitTime == 0 || millis() - waitTime > INTERVAL) && humidity < pinSensor_MIN) {
        digitalWrite(Rele, LOW);
        delay(5000 * 2);
        digitalWrite(Rele, HIGH);
        waitTime = millis();
      }
    }

    void sms(String text, String phone)  // Процедура Отправка SMS
    {
      Serial.println("SMS send started");
      mySerial.println("AT+CMGS=\"" + phone + "\"");
      delay(500);
      mySerial.print(text);
      delay(500);
      mySerial.print((char)26);
      delay(500);
      Serial.println("SMS send complete");
      delay(2000);
    }
     
     
  17. User248

    User248 Гик

    Вот эта часть кода находится внутри условия "if (mySerial.available())", поэтому таймер не работает:
    Код (C++):

      if (mySerial.available()) {
        ...
        if (inputString.indexOf("POLIV1") > -1) {
          digitalWrite(Rele2, LOW);
          PolifConch = false;
          waitTime2 = millis();
        }
        else if (millis() - waitTime2 > INTERVAL2 && !PolifConch) {
          digitalWrite(Rele2, HIGH);
          delay(1000);
          sms(String("Rele2 - PolifConch"), phoneNumber);
          PolifConch = true;
        }
        ...
      }
     
    Нужно вынести наружу:
    Код (C++):

        if (mySerial.available()) {
        ...
        }

        if (inputString.indexOf("POLIV1") > -1) {
          digitalWrite(Rele2, LOW);
          PolifConch = false;
          waitTime2 = millis();
        }
        else if (millis() - waitTime2 > INTERVAL2 && !PolifConch) {
          digitalWrite(Rele2, HIGH);
          delay(1000);
          sms(String("Rele2 - PolifConch"), phoneNumber);
          PolifConch = true;
        }
     
     
  18. User248

    User248 Гик

    Я вообще не понимаю, зачем здесь нужен таймер? Если полив окончен, то сразу выключить реле и отправить сообщение.
     
  19. overdast

    overdast Нуб

    Таймер нужен чтобы сделать несколько вариантов с разным временем работы.
    Чтобы не слать каждый раз смс на отключение, а оно само выключало реле через некоторое время.
    Но тут проблема в том что он не отключает реле.
     
  20. User248

    User248 Гик