Am facing serious problem need some help

Hello hi everyone, Sorry i need some help to isolate my problem, everything in the code work well but only one part not working properly, i need when the condition is true in any if statement in a loop function to be executed per time and not continuously repeating again and again until when the condition become true again then the code inside that if statement should be executed again. now what it happen when the condition is true it execute fine only once the code inside that if statement but when the condition become true again the code inside that statement won't be executed again i don't know why it happen like that. i put comment on the part of the code that am facing the problem, please help me to solve my issue

#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "MapFloat.h"
#include <DS3231.h>
#include <TinyGPS++.h>
#include <JQ6500_Serial.h>
#include <ArduinoJson.h>
#include <SoftwareSerial.h>

DS3231  rtc(SDA, SCL);
JQ6500_Serial mp3(Serial2);
TinyGPSPlus gps;
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27

int sensorPin = 0; // select the analog input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor
const int relayPin = 2;
const int relayOnButton = 29;
const int relayOffButton = 28;
const int manualModeButton = 30;
const int autoModeButton = 31;

StaticJsonBuffer<200> jsonBuffer;
char deviceID[12] = "Mivumoni";


int relayState = LOW;
int mode = 0;
unsigned long lastRelayPressTime = 0;
unsigned long debounceDelay = 200;

unsigned long start;
double lat_val, lng_val, alt_m_val;
//float lat_val = -6.098756;
//float lng_val = 39.653409;
uint8_t hr_val, min_val, sec_val;
bool loc_valid, alt_valid, time_valid;

int waterLevel;

float percentage; // variable for height of liquid
float volume; // variable for volume in cu. in.
float water_height;
float distance;
float tank_height = 3.50;

unsigned long startTime_gprs = 0;
unsigned long interval_gprs = 300000;

unsigned long startTime_Voice = 0;
unsigned long interval_Voice = 1000;

unsigned long startTime_rtc = 0;
unsigned long interval_rtc = 1000;

unsigned long startTime_delay = 0;
unsigned long interval_delay = 1000;

unsigned long startTime_gps = 0;
unsigned long interval_gps = 800;

static unsigned long DelayRequired = 0;
static int CurrentStep = 0;
static unsigned long PrevMillis = 0;

unsigned long currentTime = millis();
String sendtoserver;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
int flag5 = 0;
int flag6 = 0;

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  rtc.begin();
  lcd.init();                      // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();

  mp3.reset();
  mp3.setVolume(40);
  mp3.setLoopMode(MP3_LOOP_NONE);
  mp3.setEqualizer(MP3_EQ_ROCK);

  mp3.playFileByIndexNumber(7);



  pinMode(relayPin, OUTPUT);
  pinMode(relayOnButton, INPUT);
  pinMode(relayOffButton, INPUT);
  pinMode(manualModeButton, INPUT);
  pinMode(autoModeButton, INPUT);
  DynamicJsonBuffer jsonBuffer;

  delay(4000);
  lcd.clear();


}

void loop() {
  unsigned long currentTime = millis();

  //if (currentTime - startTime_gps >= interval_gps)
  //{
  startTime_gps = currentTime;
  smartDelay(200); /* Generate precise delay of 1ms */
  lat_val = gps.location.lat(); /* Get latitude data */
  loc_valid = gps.location.isValid(); /* Check if valid location data is available */
  lng_val = gps.location.lng(); /* Get longtitude data */
  time_valid = gps.time.isValid();  /* Check if valid time data is available */
  //}

  int relayOnButtonState = digitalRead(relayOnButton);
  int relayOffButtonState = digitalRead(relayOffButton);
  int manualModeButtonState = digitalRead(manualModeButton);
  int autoModeButtonState = digitalRead(autoModeButton);


  if ( manualModeButtonState == HIGH) {
    mode = 1;
  } if ( autoModeButtonState == HIGH) {
    mode = 0;
  }

  if (mode == 1) {

    sensorValue = analogRead(sensorPin);
    distance = mapFloat(sensorValue, 540, 261, 5.0, 0.45);
    volume = mapFloat(percentage, 0, 100, 0, 5000000);
    water_height = (tank_height - distance) + 1.110;
    percentage = mapFloat(water_height, 0.45, 3.50, 0, 100);



    lcd.clear();
    lcd.setCursor(10, 2);
    lcd.print("MANUAL");

    if (volume < 0.00)
    {
      volume = 0.00;
    }

    if (volume > 5000000.00)
    {
      volume = 5000000.00;
    }

    if (percentage < 0.00)
    {
      percentage = 0.00;
    }

    if (percentage > 100.00)
    {
      percentage = 100.00;
    }

    if (water_height < 0.30)
    {
      water_height = 0.00;
    }

    if (water_height > 3.5)
    {
      water_height = 3.5;
    }


    if (currentTime - startTime_rtc >= interval_rtc)
    {
      startTime_rtc = currentTime;
      lcd.setCursor(0, 0);
      lcd.print(rtc.getDateStr());
      lcd.print(" ");
      lcd.print(rtc.getTimeStr());
    }

    lcd.setCursor(0, 1);
    lcd.print(volume, 2);
    lcd.setCursor(11, 1);
    lcd.print("|");
    lcd.setCursor(13, 1);
    lcd.print(percentage, 2);
    lcd.print("%");


    lcd.setCursor(0, 2);
    lcd.print(water_height, 2);
    lcd.print("M");
    lcd.setCursor(7, 2);
    lcd.print("|");

    lcd.setCursor(0, 3);
    lcd.print(lat_val, 4);
    lcd.print(" ");
    lcd.print(lng_val, 4);


    if (relayOnButtonState == HIGH && millis() - lastRelayPressTime >= debounceDelay) {
      relayState = HIGH;
      digitalWrite(relayPin, relayState);
      lastRelayPressTime = millis();

    }

    if (relayOffButtonState == HIGH && millis() - lastRelayPressTime >= debounceDelay) {
      relayState = LOW;
      digitalWrite(relayPin, relayState);
      lastRelayPressTime = millis();
    }

    if (relayState == HIGH)
    {

      lcd.setCursor(17, 3);
      lcd.print("ON");
    }

    else if (relayState == LOW)
    {

      lcd.setCursor(17, 3);
      lcd.print("OFF");
    }


      
  } else if (mode == 0) {

    sensorValue = analogRead(sensorPin);
    distance = mapFloat(sensorValue, 540, 261, 5.0, 0.45);
    volume = mapFloat(percentage, 0, 100, 0, 5000000);
    water_height = (tank_height - distance) + 1.110;
    percentage = mapFloat(water_height, 0.45, 3.50, 0, 100);


    lcd.clear();
    lcd.setCursor(10, 2);
    lcd.print("AUTOMATIC");


    if (volume < 0.00)
    {
      volume = 0.00;
    }

    if (volume > 5000000.00)
    {
      volume = 5000000.00;
    }

    if (percentage < 0.00)
    {
      percentage = 0.00;
    }

    if (percentage > 100.00)
    {
      percentage = 100.00;
    }

    if (water_height < 0.30)
    {
      water_height = 0.00;
    }

    if (water_height > 3.5)
    {
      water_height = 3.5;
    }

    if (currentTime - startTime_rtc >= interval_rtc)
    {
      startTime_rtc = currentTime;
      lcd.setCursor(0, 0);
      lcd.print(rtc.getDateStr());
      lcd.print(" ");
      lcd.print(rtc.getTimeStr());
    }

    lcd.setCursor(0, 1);
    lcd.print(volume, 2);
    lcd.setCursor(11, 1);
    lcd.print("|");
    lcd.setCursor(13, 1);
    lcd.print(percentage, 2);
    lcd.print("%");


    lcd.setCursor(0, 2);
    lcd.print(water_height, 2);
    lcd.print("M");
    lcd.setCursor(7, 2);
    lcd.print("|");

    lcd.setCursor(0, 3);
    lcd.print(lat_val, 4);
    lcd.print(" ");
    lcd.print(lng_val, 4);


    if (water_height >= 3.50) {
      relayState = LOW;

      lcd.setCursor(17, 3);
      lcd.print("OFF");
    }

    else if (waterLevel <= 1.00) {
      relayState = HIGH;

      lcd.setCursor(17, 3);
      lcd.print("ON");

    }



    digitalWrite(relayPin, relayState);
 
  }

// starting part that I'm facing the problem
      
if (mode == 1 && flag1 == 0) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(2);
        flag1 = 1;  // Set Flag 1 to true
      }

      
      if (mode == 1 && relayState == HIGH && flag2 == 0)
      {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(6);
        flag2 = 1;  // Set Flag 1 to true
      }
    
    
      if (mode == 1 && relayState == LOW && flag3 == 0)
      {

        mp3.setVolume(40);
        mp3.playFileByIndexNumber(4);
        flag3 = 1;  // Set Flag 1 to true
      }


      if (mode == 0 && flag4 == 0) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(1);
        flag4 = 1;  // Set Flag 1 to true
      }
     
      if (mode == 0 && relayState == LOW && flag5 == 0 ) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(8);
        delay(1000);
        mp3.playFileByIndexNumber(3);
        flag5 = 1;  // Set Flag 1 to true
      }
    

    if (mode == 0 && relayState == HIGH && flag6 == 0) {

      mp3.setVolume(40);
      mp3.playFileByIndexNumber(9);
      delay(1000);
      mp3.playFileByIndexNumber(5);
      flag6 = 1;  // Set Flag 1 to true
    }
    
// ending part that I'm facing the problem
   
  delay(1000);
}



static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (Serial1.available())  /* Encode data read from GPS while data is available on serial port */
      gps.encode(Serial1.read());
    /* Encode basically is used to parse the string received by the GPS and to store it in a buffer so that information can be extracted from it */
  } while (millis() - start < ms);
}




Here is the part of the code that i need to be executed only when condition is true and should executed only once


// starting part that I'm facing the problem
      
if (mode == 1 && flag1 == 0) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(2);
        flag1 = 1;  // Set Flag 1 to true
      }

      
      if (mode == 1 && relayState == HIGH && flag2 == 0)
      {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(6);
        flag2 = 1;  // Set Flag 1 to true
      }
    
    
      if (mode == 1 && relayState == LOW && flag3 == 0)
      {

        mp3.setVolume(40);
        mp3.playFileByIndexNumber(4);
        flag3 = 1;  // Set Flag 1 to true
      }


      if (mode == 0 && flag4 == 0) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(1);
        flag4 = 1;  // Set Flag 1 to true
      }
     
      if (mode == 0 && relayState == LOW && flag5 == 0 ) {
        mp3.setVolume(40);
        mp3.playFileByIndexNumber(8);
        delay(1000);
        mp3.playFileByIndexNumber(3);
        flag5 = 1;  // Set Flag 1 to true
      }
    

    if (mode == 0 && relayState == HIGH && flag6 == 0) {

      mp3.setVolume(40);
      mp3.playFileByIndexNumber(9);
      delay(1000);
      mp3.playFileByIndexNumber(5);
      flag6 = 1;  // Set Flag 1 to true
    }
    
// ending part that I'm facing the problem

Use a logic analyzer to see what happens.

Insert Serial.println()´s at points of interrest and analyze the test results.

Have a nice day and enjoy coding in C++.

how?

Did you make the coding?

If yes, then you know how the program logic should work.

Check this logic with the a.m. logic analyzer.

respect people when they need some helps, i come here to ask for someone who can solve my problem that am facing so if you know where mighty be the problem help me to isolate my problem

Sorry, this forum isn´t a software-repair-service!

1 Like

i know what am doing man, it's not my first time to use this forum man, if you can't help someone who need some helps it more better to keep quiet and leave people who can help me to solve my problem.

1 Like

Hello

if (mode == 1 && flag1 == 0) {
  ...
  flag1 = 1;  // Set Flag 1 to true
}

The condition will be true only once, until you reset flag1 to 0, but you never do that

ok thanks for the feedback, so how i can do that?

sorry, how do i reset the flag to 0?

Have a flag to indicate when the stuff has been done.

Don't do that stuff when that flag is set.

Pseudocode:

bool done_the_stuff ;

setup()
{
   // Initially, the stuff has not been done
   done_the_stuff = false;
}

loop()
{
   if( your_condition )
   {
      if( !done_the_stuff )
      {
         // do the stuff
         :
         :

         // Now the stuff has been done!
         done_the_stuff = true;
      }
   }
   :
   :
}

You'll need to think about where/when you should clear the flag to allow the stuff to be done again, if required...

Start a timer with the same duration than the sound file (or whatever duration you want)

When the timer is elapsed, do flag1 = 0; so the condition can become true again.

flag1 = 0;
1 Like

I once wrote a debounce class to debounce switches. Looks like bounce2.

One thing I added is that you can supply the debouncer with external input. So you are not tied to digitalRead.

It is really usefull, you can use the debouncer to debounce analog input and you can monitor outputs and flags and create a sort of events for when a flag or output changes value.

Debounce flag1Event() ;

...
...

void loop()
{
    flag1Event.debounce( flag1 ) ; // insert flag1 into the debouncer

    if( flag1Event.getState() == FALLING ) // or RISING, HIGH or LOW.
    {
        // do something one time when flag1 goes from HIGH to LOW
    } 
}

sorry bro i don't know how to do that can you please help me to show in my code above?

Why not just set the flag when the sound ends?

(surely, you must know when the sound ends?)

this trick doesn't work

Try something like this

static uint32_t flag1_timestamp = 0;
static uint32_t flag1_duration = 0;

if (mode == 1 && flag1 == 0){
  ...
  flag1 = 1;  // Set Flag 1 to true
  flag1_timestamp = millis();
  flag1_duration = 5000;
}

if ( flag1 != 0 && millis() - flag1_timestamp >= flag1_duration )
{
	flag1 = 0;
}

Hi, I think part of the problem is the expression, try to use IF directly and not ELSE IF in the code.

I can see:

if (mode == 1)

Xxxxx
Xxxxx
Xxxxx
Xxxxx

And

else if (mode == 0) here maybe is the problem, only if would be better.

I think that the program will stay in the air waiting, for example, waiting since basically are you not express do it.

else if, for me is like, maybe waiting to do it....not like, do it!

if (mode == 0), for me is like Do it, not waiting

I'm new, I have no experience, but remember, the simpler is better.
Good luck!