Как сбросить переменную непосредственно перед вводом функции?

Я сталкиваюсь с проблемой, когда условие if в функции waterNowrun может выполняться один раз после запуска программы, когда переменная v равна 0 в начале, но при повторном запуске if не выполняется как v не <10.

После некоторой отладки я решил, что v должен быть сброшен перед вводом функции, и поэтому я установил v в 0 в цикле, тогда произошло то, что if всегда был удовлетворен и не переходил к другому.

Можно ли это сделать? Может быть, с перерывами или чем-то еще?

Аппаратное обеспечение-ESP8266 на основе NodeMCU

В заключение-

Я хочу сбросить переменную v один раз перед запуском функции waterNowrun, как это сделать?

Мой код ...

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "DHT.h"
#include "LiquidCrystal_PCF8574.h"

#define BLYNK_PRINT Serial
#define DHT_PIN_DATA  12
// LCD definations
#define LCD_ADDRESS 0x27
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 25
#define DHTTYPE DHT22

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "ymri80lFL9_xZhf6WIRHtQ1qadfafdEWOt9zBy";
char ssid[] = "-Hotspot-82DB";
char pass[] = "b35288qqafdd";
int autoSch;
int waterNow;
int morTime;
int afterTime;
int postNoon;
int eveTime;
int schTime;
int minStep;
int interval;
int count;
int flag = 0;
int soilHum = A0;
int v;
unsigned long previousMillis = 0;

DHT dht(DHT_PIN_DATA, DHTTYPE);
LiquidCrystal_PCF8574 lcdI2C;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "in.pool.ntp.org", 19800, 600000);
// This function will be called every time Slider Widget
// in Blynk app writes values to the Virtual Pin 1

BLYNK_CONNECTED() {
  Blynk.syncAll();
}

BLYNK_WRITE(V0)
{
  autoSch = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1)
{
  morTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V2)
{
  afterTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V6)
{
  postNoon = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V3)
{
  eveTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V10)
{
  waterNow = param.asInt(); // assigning incoming value from pin V1 to a variable
Serial.println("Boo BOO is BOO BOO billa");
}

BLYNK_WRITE(V4)
{
  schTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V7)
{
  minStep = param.asInt(); // assigning incoming value from pin V1 to a variable
}

void setup()
{
  dht.begin();
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  Blynk.virtualWrite(V5, 0);
  Blynk.virtualWrite(V8, 0);
  pinMode(0, INPUT_PULLUP);
  Serial.begin(9600);

  //WiFi.begin(ssid, password);
  Blynk.begin(auth, ssid, pass);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  timeClient.begin();
  Blynk.syncAll();
}

void loop()
{
  Blynk.run();
  time_run();
  lcd();
  butPress();

  timeClient.update();
  if (waterNow != 1) {
    Blynk.virtualWrite(V10, 0);
   // digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, minStep * 60);

    Blynk.syncAll();
  }
  if (waterNow == 1) {
    waterNowrun(v = 0);

  } else if (autoSch == 0) {
    auto_run1();
  } else if (autoSch == 1) {
    sch_run2();
  } else {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }
  Blynk.syncAll();
  Serial.println(timeClient.getFormattedTime());
  Serial.println(analogRead(A0));
}
void butPress() {
  if (digitalRead(0) == LOW) {
    if (flag == 0) {


      digitalWrite(14, HIGH);
      delay(3000);
      digitalWrite(14, LOW);

      flag = 1;
    }
    else {
      digitalWrite(14, LOW);
      flag = 0;
    }
  }
}

void test() {
  if (v < 10) {
    digitalWrite(14, HIGH);
    v++;
    delay(500);


  } else {
    digitalWrite(14, LOW);

  }

}


void lcd() {
  //lcdI2C.clear();
  lcdI2C.setCursor(0, 0);
  timeClient.update();
  lcdI2C.print(timeClient.getFormattedTime());

  if (autoSch == 0) {
    lcdI2C.setCursor(9, 0);
    lcdI2C.print("Auto     ");
  } else {
    lcdI2C.print(" Sch   ");
  }


  if (digitalRead(14) == 1) {
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now           ");
  }
  else
  {

    if (int(timeClient.getHours()) < 6 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6a ");
    } else if (int(timeClient.getHours()) < 12 && afterTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 12n ");
    } else if (int(timeClient.getHours()) < 14 && postNoon == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at:14pn ");
    } else if (int(timeClient.getHours()) < 18 && eveTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 18e ");
    } else if (int(timeClient.getHours()) >= 18 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6a ");
    } else {
      lcdI2C.selectLine(2);
      lcdI2C.print("My name is billa");
    }

  }

}

void waterNowrun(int v) {
  /*
    Serial.println (currentMillis);
    Serial.println (previousMillis);
    Serial.println(interval);
  */


  if (v < 10) {

    Serial.println("Boo Boo");

    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now :");
    /*
      lcdI2C.print((minStep * 60) - ((currentMillis - previousMillis) / 1000));
      Blynk.virtualWrite(V8, ((interval / 1000) - ((currentMillis - previousMillis) / 1000)));
    */
    Blynk.syncAll();
    delay(500);
    v++;
  } else {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, 0);

    Blynk.syncAll();


  }
}

void sch_run2() {
  if (schTime == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  } else if (schTime == 0) {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }

}

void time_run() {
  Blynk.virtualWrite(V11, int(timeClient.getHours()));
  Blynk.virtualWrite(V12, int(timeClient.getMinutes()));
  Blynk.virtualWrite(V13, float(dht.readTempC()));
  Blynk.virtualWrite(V14, float(dht.readHumidity()));

}





void auto_run1() {
  if (morTime == 1 && String(timeClient.getFormattedTime()) > "06:00:00" && String(timeClient.getFormattedTime()) < "06:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (afterTime == 1 && String(timeClient.getFormattedTime()) > "12:00:00" && String(timeClient.getFormattedTime()) < "12:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (postNoon == 1 && String(timeClient.getFormattedTime()) > "14:00:00" && String(timeClient.getFormattedTime()) < "14:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (eveTime == 1 && String(timeClient.getFormattedTime()) > "12:59:00" && String(timeClient.getFormattedTime()) < "13:01:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else  {
    //(String(timeClient.getFormattedTime() == "06:20:00" || "12:20:00" || "14:20:00" || "13:48:00"))
    //waterNowrun();
    /*
      Blynk.virtualWrite(V10, 0);
      digitalWrite(14, LOW);
      Blynk.virtualWrite(V5, 0);
      Blynk.virtualWrite(V8, 0);
      Blynk.syncAll();
    */
  }
}

, 👍1

Обсуждение

Логика вашего объяснения мне не совсем ясна, но переменная int v внутри функции waternowRun является локальной переменной, которая действительна только внутри этой функции и *не совпадает* с "глобальной" переменной int v. Это, вероятно, и вызывает путаницу. Если вы хотите сохранить значение локальной переменной между вызовами функций, вы можете объявить ее как "статическую" переменную, но это может быть или не быть тем, что вам нужно. Это также вопрос программирования, а не конкретный вопрос Arduino., @StarCat

И именно поэтому не рекомендуется использовать глобальные переменные... В любом случае, функция test() изменяет глобальную переменную v (отличное имя, если вы хотите зашифровать код). "waterNowrun(int v)" изменяет локальную переменную с удобным именем "v", которая затеняет глобальную " v " ... возьмите то, что портит его, @KIIV

@StarCat Не могли бы вы объяснить, как работают статические переменные?, @Coder9390

Если здесь все объяснено довольно ясно: [https://www.tutorialspoint.com/what-is-the-lifetime-of-a-static-variable-in-a-cplusplus-function](https://www.tutorialspoint.com/what-is-the-lifetime-of-a-static-variable-in-a-cplusplus-function). Если вы объявите переменную static внутри функции (например, static int counter;), она сохранит свое значение при многократном вызове функции, как в примере из ссылки. Обычно локальная переменная перераспределяется (сбрасывается) при выходе из функции и повторном входе в нее., @StarCat

@StarCat Я пробовал, но это не сработало, @Coder9390


2 ответа


Лучший ответ:

3

Цель функции waterNowrun и "v", по-видимому, состоит в том, чтобы включить немного воды и держать ее работающей в течение 10 итераций, прежде чем выключить?

Я бы разделил водный поток на две функции:

void waterOn() {
    Serial.println("Boo Boo");
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now :");
    /*
      lcdI2C.print((minStep * 60) - ((currentMillis - previousMillis) / 1000));
      Blynk.virtualWrite(V8, ((interval / 1000) - ((currentMillis -     previousMillis) / 1000)));
    */
    Blynk.syncAll();
    delay(500);
}

void waterOff() {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, 0);
    Blynk.syncAll();
}

В loop() Я бы так и сделал

...
if (waterNow != 1) {
    waterOff();
}
if (waterNow == 1) {
    if (v < 10) {
        waterOn();
        v++;
    }
    else {
        waterOff();
        v = 0;
    }
} else if (autoSch == 0) {
    auto_run1();
} else if (autoSch == 1) {
    sch_run2();
} else {
    waterOff();
}
...

Но сделайте себе одолжение и переименуйте v в waterPeriod или что-нибудь еще, что легче запомнить.

,

Спасибо за помощь... Просто для пояснения я попытаюсь объяснить, что я понял - Поэтому, если значение waterNow равно 1, а v<10 then waterOn until v> или = 10, перейдите к оператору else и выполните сброс воды, который также преобразует значение waterNow в 0, следовательно, выходим из оператора if и устанавливаем v=0, чтобы сбросить состояние переменной. Это то, что я должен понимать?, @Coder9390

Привет, извини, что не перезвонил тебе раньше. Да, это правильно. Когда вы начинаете, значение waterNow равно false (или 0), а v равно 0. Когда значение waterOn равно true (или 1), мы переходим к ветви waterNow==1. v равно 0, так что < 10, вода включена, и v увеличивается. Для следующих итераций мы делаем то же самое, пока v не достигнет 10. Затем мы переходим в ветку else, выключаем воду и сбрасываем V. Теперь waterNow и v равны 0, как и в начале., @jkp

Если снова и снова проходить через waterOn является проблемой, вы можете попробовать , если (v == 0) { уотерОн(); } если (v++ == 10) { Сток воды(); v = 0; } РЕДАКТИРОВАТЬ: Похоже, комментарии отформатированы. Лайнбрейки после бранкетов и ;, @jkp


0

Непонятно , какого поведения вы ожидаете от v, тем более что у вас их два - глобальный v во главе вашей программы и параметр v функции waterNowrun(int v).

Мое понимание того, что вы хотите, заключается в том, что функция должна поддерживать контроль над v. Если да,то

  • Избавиться от глобального v';
  • В loop ()ничего не передавайте waterNowrun ().
  • Внутри функции waterNowrun() объявите static int v = 0;. Эта инициализация до нуля произойдет только один раз, перед запуском программы (не при каждом входе в функцию, хотя она вроде как читается так). С этого момента только ваша функция waterNowrun() может изменять v.

Возможно, это не единственное логическое изменение, которое вам нужно сделать - я не понимаю, что вы пытаетесь сделать с v, и не могу критиковать это. Но, по крайней мере, теперь v будет полностью управляться изнутри функции, и он не будет меняться между вызовами функции.

Некоторая предыстория: Статическая переменная, объявленная в функции, подобна глобальной в том, что она имеет фиксированный адрес памяти для всего запуска программы; в отличие от локальной (включая параметр функции), которая перераспределяется в памяти каждый раз, когда функция вводится (и поэтому должна быть инициализирована при каждой записи). Но в отличие от глобального, он невидим - не известен - где-либо за пределами этой функции.

,

К сожалению, этот ответ не решает проблему, так как я сталкиваюсь с той же проблемой, что и раньше, когда функция работает один раз, но не второй, @Coder9390

Пожалуйста, объясните, чего вы пытаетесь достичь., @JRobert

Я пытаюсь включить полив на определенное количество итераций, а затем отключить его, проблема в том, что счетчик итераций v остается = или > 10, следовательно, не входит в функцию во второй раз, @Coder9390

Попробуйте добавить строку "v = 0;" после двух других вызовов waterOff ();., @jkp

Вам нужно сбросить счетчик, когда вы выключаете воду, и увеличить его, пока вода включена., @jkp