How to run this in loop only once while others continuesly

I want to run the float sensors in loop but send telegram bot message only once. i tried with bool and still could not make it work.
i tried this for hours and cant fix.. please hope someone could help me here

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>


const char* ssid = "xxxx";
const char* password = "xxxxxxxxx";

const int  FloatSensor = 5;
const int Relay = 4;
int FloatState =0;  


#define BOTtoken "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define CHAT_ID "xxxxxx"


X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

void setup() {
  Serial.begin(115200);

  pinMode(FloatSensor, INPUT_PULLUP);
  pinMode (Relay, OUTPUT);
 
    
  configTime(0, 0, "pool.ntp.org");      // get UTC time via NTP
  client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org

  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  int a = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
    a++;
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  delay(500);

  bot.sendMessage(CHAT_ID, "System started", "");
  delay(1000);

 
}

void loop() {
 
  bool  FloatState = digitalRead(FloatSensor);

 if (FloatState == LOW){
    Serial.println("Water level HIGH & Pressure pump ON");
    digitalWrite(Relay, HIGH);

     bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
}
  else  if (FloatState == HIGH){
    Serial.println("Water level LOW & Pressure pump OFF");
    digitalWrite(Relay, LOW);

    bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
   }
   }
  
}

  
  

this is the only part where i want to run only once

bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); 
 bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF");

hi

you have to verify a "staus change" not a status itself...I mean...you have to read the status of the sensor then save this in a variable with a global scope...called something like "oldState"... then verify if the new read has a different value of the "oldState" variable...so...if the new valie is HIGH do something otherwise do semthing else....

I hope that is clear enough

You need to use StateChangeDetection

Here is a solution:

void loop() {
  static bool prevFloatState = digitalRead(FloatSensor);
  bool  FloatState = digitalRead(FloatSensor);

  if (FloatState != prevFloatState) {
    prevFloatState = FloatState;
    if (FloatState == LOW) {
      Serial.println("Water level HIGH & Pressure pump ON");
      digitalWrite(Relay, HIGH);
      bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
    }
    else {
      Serial.println("Water level LOW & Pressure pump OFF");
      digitalWrite(Relay, LOW);
      bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
    }
  }
}

thanks for replying . i even tried statechangedetection before and their is a issue with this too.
while float switch is high and when their is a power outage , when power gets back and float is high
it does nothing because it only works with change of state.
this happens same when float is LOW. after power outage it never reads the float sensor .unless their is change in state.
could yu help me on this.?

tried but look like i have other issue on reading the FLoat sensor after poweroutage.
please check
post #5

do you need that at the start up of the arduino the message is sent about all possible status of th efloat then just if this will change?...or do you want that the message is sent always for te status chagement also after a power off of the arduino?...for this last I mean...before the power off the float was low...at the start up it rise to high...so this is a status change...so arduino has to send a message...what of the two options?

So now that's your new question. How to write code that can "recover" from an unplanned reset.

I say "recover" in quotes as it really has no idea of any past when it reboots.

You could… save the state of affairs in EEPROM and read them at boot time.

Better would be to handle all the initially observed inputs and set outputs appropriately, then get on with the state change monitorization.

a7

thanks for replying, what i need is even after power outage or after boot i want to check for float sensor change first and the telegram bot should send msg only once.

Simply read and report the state in setup(). After that the state only gets reported when it changes. Like this:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>


const char* ssid = "xxxx";
const char* password = "xxxxxxxxx";

const int  FloatSensor = 5;
const int Relay = 4;
bool prevFloatState = digitalRead(FloatSensor);

#define BOTtoken "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define CHAT_ID "xxxxxx"


X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

void setup() {
  Serial.begin(115200);

  pinMode(FloatSensor, INPUT_PULLUP);
  pinMode (Relay, OUTPUT);
 
    
  configTime(0, 0, "pool.ntp.org");      // get UTC time via NTP
  client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org

  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  int a = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
    a++;
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  delay(500);

  bot.sendMessage(CHAT_ID, "System started", "");
  delay(1000);
  
  if (prevFloatState == LOW) {
    Serial.println("Water level HIGH & Pressure pump ON");
    digitalWrite(Relay, HIGH);
    bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
  }
  else {
    Serial.println("Water level LOW & Pressure pump OFF");
    digitalWrite(Relay, LOW);
    bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
  }
}

void loop() {
  bool  FloatState = digitalRead(FloatSensor);

  if (FloatState != prevFloatState) {
    prevFloatState = FloatState;
    if (FloatState == LOW) {
      Serial.println("Water level HIGH & Pressure pump ON");
      digitalWrite(Relay, HIGH);
      bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
    }
    else {
      Serial.println("Water level LOW & Pressure pump OFF");
      digitalWrite(Relay, LOW);
      bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
    }
  }
}

eeprom is something limited with esp8266 and i dont want to run that in flash memory .
better what im asking is...not to recover the last state rather let it start checking for sensor states (if float is HIGH or LOW) from start and send telegram bot msg once

@ToddL1962 and I have said basically the same thing.

I mentioned the EEPROM as a straw man.

And better woukd be exactly what I said, or perhaps more fully by @ToddL1962.

a7

this works but not completely, have tried the same in past. but what happens is when float is LOW and once esp boots and its connected to wifi and when bot sends system started.
then it send float to HIGH for a sec . after that it reads and gets back to LOW.
*relay dosnt turn on while boot.( for LTR does happen)
Im using ssr
beacuse of this relay turns on for a sec and turns off also telegram bot sends its high .only after a sec it sends low

i am not sure to have properly understood your situation...but maybe you can start to read the status of the fload only after that you are sure that the whole system is ready...maybe a "delay" will help...

In this code when esp boots up && float is HIGH. it sends LOW once and sends HIGH . Any suggestions to fix this issue?
On serial monitor

WiFi connected
IP address: 192.168.169.210
Water level LOW & Pressure pump OFF  // float is HIGH but still runs LOW for once
Water level HIGH & Pressure pump ON  // actual state of float

code is as follows

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>


const char* ssid = "xxx";
const char* password = "xxxxxx";

const int  FloatSensor = 5;
const int Relay = 4;
static bool prevFloatState = 1;
//bool prevFloatState = digitalRead(FloatSensor);
#define BOTtoken "xxxxxxxxxx"
#define CHAT_ID "xxx"


X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

void setup() {
  Serial.begin(115200);

  pinMode(FloatSensor, INPUT_PULLUP);
  pinMode (Relay, OUTPUT);
 
    
  configTime(0, 0, "pool.ntp.org");      // get UTC time via NTP
  client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org


  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  int a = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
    a++;
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  delay(500);

  bot.sendMessage(CHAT_ID, "System started", "");
  delay(2000);
  
   if (prevFloatState == LOW) {
    Serial.println("Water level HIGH & Pressure pump ON");
    digitalWrite(Relay, HIGH);
    bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
  }
  else {
    Serial.println("Water level LOW & Pressure pump OFF");
    digitalWrite(Relay, LOW);
    bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
  }
}


void loop() {
  bool  FloatState = digitalRead(FloatSensor);
  if (FloatState != prevFloatState) {
    prevFloatState = FloatState;
    if (FloatState == LOW) {
      Serial.println("Water level HIGH & Pressure pump ON");
      digitalWrite(Relay, HIGH);
      bot.sendMessage(CHAT_ID, "Water level HIGH & Pressure pump ON"); // only once i want to send message to bot
    }
    else {
      Serial.println("Water level LOW & Pressure pump OFF");
      digitalWrite(Relay, LOW);
      bot.sendMessage(CHAT_ID, "Water level LOW & Pressure pump OFF"); // only once i want to send message to bot
    }
  }
}

This looks like a good idea. Why not actually digitalRead() the FloatSensor before the if statement in you setup()?

You could read the sensor and set the FloatState and the prevFloatState would be the logical opposite.

Declare both global variables global, read the sensor and set both values in setup(). Artificial instate state transition when you hit the loop().

Sry typing with my nose here, I'll try to make an examlpe if you can't get that to work, but it also sounds like you have some warming up issues, perhaps as suggested a bit of delay in the setup portion so everything is in a known state settled ready for action.

a7

Thanks for your response @alto777 . I appreciate if you could share some help with example .
I even tried out delay in setup..and read float sensor in setup ...nothings works ...Still the same issue ...The last code I shared in last post I what I use for now . When float is LOW . It runs low and perfect...but when it's Float is HIGH on boot it goes low and then goes high...really not sure what's the issue .

I even set previous state = 1 soo this won't affect when float is LOW .

It would be great if you help to fix the duplicate reading of low when Float is HIGH .

My beach buddy is on her way to pick me up, but I did write this

const int  FloatSensor = 5;
const int Relay = 4;
bool prevFloatState = 1;

void setup() {
  Serial.begin(115200);

  pinMode(FloatSensor, INPUT_PULLUP);
  pinMode(Relay, OUTPUT);

  prevFloatState =  digitalRead(FloatSensor);
 
  Serial.print("System started with... ");

  bool initialFloatState = digitalRead(FloatSensor);

  if (initialFloatState == LOW) {
    Serial.println("Water level HIGH & Pressure pump ON");
    digitalWrite(Relay, HIGH);
  }
  else {
    Serial.println("Water level LOW & Pressure pump OFF");
    digitalWrite(Relay, LOW);
  }
}

void loop() {
  static unsigned long lastTime;
  unsigned long now = millis();

  if (now - lastTime < 20) return;    // run loop at 50 Hz, automatic swtich debouncing.
  lastTime = now;

  bool FloatState = digitalRead(FloatSensor);
  if (FloatState != prevFloatState) {
    prevFloatState = FloatState;
    if (FloatState == LOW) {
      Serial.println("Water level HIGH & Pressure pump ON");
      digitalWrite(Relay, HIGH);
    }
    else {
      Serial.println("Water level LOW & Pressure pump OFF");
      digitalWrite(Relay, LOW);
    }
  }
}

and simulate it here. Take the link and play with it:

It respects the initial setting of the slide switch. Run it and leave the switch on or off for the next test.

This is the suggestion I made and @ToddL1962 also made put into the simplest expression of the logic needed to send a message once, to react to state changes and to boot up into an approriate mode.

This is the logic I believe you need. If is and it doesn't work when you put it into the more complex context which is your sketch, it is something else that is the problem.

Uh oh - off to the beach. Try it.

HTH & L8R

a7

You and @alto777 discovered my bad idea of initializing prevFloatState with digitalRead() as that occurs before setup() is called.

thanks this works i guess and hope yu had a good time in beach..lol

No need to guess. Take the link and run the code.

And yes, beach good thx.

a7