While loops

I’m having a bit of trouble understanding while loops which I want to use in a function to reset an RTC.
I have copied a bit of my code and the pertinent functions are checkReset() and resetTime()
I’m afraid it is in a ‘developmental’ state and there is lots of ‘commenting out’.

I have three button switches. The first simply calls CheckReset() which is meant to screen out inadvertent button presses. From there I either return to loop() or enter resetTime().

That works fine and the first part of the reset function also does what I want,
in that it resets the ‘year’ variable but adding code to reset the month variable produces no effect. (so I have commented out this part - as I have commented out the code sending the reset variables to the RTC - which works fine).

I imagined that once the ‘year’ while loop ended the following ‘month’ loop would start and so on until the end of the resetTime() function so what am I missing apart from brains?

Initially I intended using a global variable ‘wait’ (unsigned long) to control the loops but I can see that might confuse the system so I tried using different local variables with no result.

One other thing, I first used ‘break’ to get out of the while loop when the variable ‘year’ was correct but it did not close the loop.

#include <Wire.h>
#include<LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#include <BH1750.h>
#include <RealTimeClockDS1307.h>

BH1750 lightMeter;
#define DS1307_ADDRESS 0x68
#define BACKLIGHT_PIN 3
#define DHTPIN 4
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

//The position of the following is critical!
byte decToBcd(byte val) {
  return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val) {
  return ((val / 16 * 10) + (val % 16));
}


OneWire ds(10);  // on pin 10
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7); // 0x3F is the LCD address
byte amend;
byte atd ;// difference between inside air temp and OAT. ATMOSPHERE
byte breeze;  //ATMOSPHERE

byte count1 = 0; //atmosphere
byte date = 0; //checktime, settime, readtime
byte day = 0;
byte edit = 0;
byte heaterState = 0;
byte heatStart = 0;

byte hour = 0;
byte hrst = 0;


byte lastInput = 0;
byte lightLevel;

byte minute = 0;
byte month = 3;

byte No = 7;
//byte no;
byte orbit;

byte resetRTC = 0;
byte second = 0;
byte startup = 1; //heating
byte intSwitch = 6;
byte year = 16;
byte Yes = 8;
//byte yes;
byte zero = 0x00; //Workround for issue #527










unsigned long wait;
float adjustment;  //heating
float air;  //atmosphere
float baseTemp;  //heating
float basic[] = {0, 12.5, 12.5, 12.5, 14.00, 15.95, 18, 18, 18, 18, 16, 14, 12.5};
float controlTemp;
float dayEnvelope;
float dvt = 0.01875;
float hTime;
float hysteresis = 0.25;

float temperature;
float minNow = (hour * 60) + minute + (second / 60);
float variation[] = {0, 0, 0, 0.05, 0.065, 0.065, 0, 0, 0, 0.065, 0.065, 0.05, 0};

//SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
void setup() {
  Wire.begin();
  lcd.begin(20, 4);
  Serial.begin(9600);
  dht.begin();
  lightMeter.begin();
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);



  pinMode(2, OUTPUT); //Heat
  pinMode(6, INPUT); //reset
  pinMode(7, INPUT); //the no switch
  pinMode(8, INPUT); //the yes switch
  pinMode(5, OUTPUT); //Rain
  pinMode(9, OUTPUT); //Humidity
}  //End Setup

//==================================================================
void loop() {


  displayTime();

  heating();

  humidity();

  //displayTime();

  light();

  atmosphere();

  if (digitalRead(intSwitch) == HIGH)checkReset();

}




//==================================================================
void checkReset() {

  /*while (digitalRead(Yes) == HIGH || digitalRead(No) == HIGH) {
    //Do nothing to make sure Yes/No button isn't pressed inadvertantly
    }
  */
  lcd.clear();
  lcd.setCursor(0, 2);
  lcd.print(" Change Date/Time?");
  lcd.setCursor(0, 3);
  lcd.print("No               Yes");

  wait = (millis() + 10000); // Response time = 10 seconds

  while (wait > millis()) { //this is the quit timer

    if (digitalRead(No) == HIGH) {

      wait = millis(); //to get out of loop
    }
    if (digitalRead(Yes) == HIGH) {
      delay(500);
      resetTime();
      lcd.clear();
    }
  }
  // if no input return after (ten) seconds
  lcd.clear();
}

// End of 'checkReset'

//----------------------------------------------------------
void resetTime() {

  wait = (millis() + 10000);
  lcd.clear();
  while (wait > millis()) {
    lcd.print("The year is 20");
    lcd.print(year);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
    if (digitalRead(No) == 1) {
      ++year;
      if (year > 21)year = 16;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      wait = millis();
    }

  } // End year loop

  //------------------------------------
/*
  wait = (millis() + 10000);
  lcd.clear();
  while (wait> millis()) {
    lcd.print("The month is ");
    if (month < 10)lcd.print(" ");
    lcd.print(month);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
    if (digitalRead(No) == 1) {
      ++month;
      if (month > 12)month = 1;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      wait = millis();
    }
  } // End month loop

*/
  //------------------------------------------------------------------
  /* Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(zero);
    Wire.write (decToBcd(second));
    Wire.write (decToBcd(minute));
    Wire.write (decToBcd(hour));
    Wire.write (decToBcd(day));
    Wire.write (decToBcd(date));
    Wire.write (decToBcd(month));
    Wire.write (decToBcd(year));
    Wire.write(zero);
    Wire.endTransmission();
    lcd.clear();
  */
}  //end of resetTime
byte correct=0
while !correct {
    lcd.print("The year is 20");
    lcd.print(year);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
while (wait > millis()) {
    if (digitalRead(No) == 1) {
      ++year;
      if (year > 21)year = 16;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      correct=1;
      wait = millis();
    }
}}

My first thoughts (untested/unproofread). You need two loops - the outer one to redraw the prompt with the new value, and the inner one to handle the waiting for buttons.

You've lost me already DrAzzy!

byte No = 7;

That certainly needs some explanation. If that is supposed to be the name for a pin, it would certainly help if Pin was somewhere in the name.

  pinMode(2, OUTPUT); //Heat
  pinMode(6, INPUT); //reset
  pinMode(7, INPUT); //the no switch
  pinMode(8, INPUT); //the yes switch
  pinMode(5, OUTPUT); //Rain
  pinMode(9, OUTPUT); //Humidity

You gave the pins (meaningless) names. Use them!

  wait = (millis() + 10000); // Response time = 10 seconds

Adding times is not guaranteed to work. Subtracting is.

start = millis();
while(millis() - start > interval)
{
}

How are the switches wired? You are not using the internal pullup resistors, so external ones are required.

    if (digitalRead(No) == 1) {
      ++year;
      if (year > 21)year = 16;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      wait = millis();
    }

Don't you need to wait for one of the switches to become pressed? (That is what DrAzzy was suggesting).

Instead of setting wait equal to millis(), which is always growing, to break the loop how about adding a boolean that can be set to signal it's time to move on?

void resetTime() {

  boolean done = false;      // true => ready for next step
  wait = (millis() + 10000);
  lcd.clear();
  while( (wait > millis()) && (!done)) {
    lcd.print("The year is 20");
    lcd.print(year);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
    if (digitalRead(No) == 1) {
      ++year;
      if (year > 21)year = 16;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      //wait = millis();
      done = true;
    }

  } // End year loop
  
  done = false;

Adrifran39:
I’m having a bit of trouble understanding …

In that case the first thing to do is write a short program that has nothing in it but the stuff that you are having trouble with. Then it will be easier for you to understand, debug and learn. And it will be much easier for us to help you.

In general I would avoid WHILE loops unless they can complete their buisness in a few milliseconds or less.

You may get some ideas from Planning and Implementing a Program

…R

So many responses!

First, PaulS. Yes. that could be byte NoPin=7. I couldn’t identify it in isolation at first!
I have a pull-down resistor on each switch pin, the switch wired to V+
I have decided to do away with the timing for now but there has to be some limit or having interrupted the Program it could be that a distraction or forgetfulness might leave a heater on permanently or maybe athe watering system … !
The intial switch press is detected in void loop() (at the end). The reason for the while loops is just that. I’m open to suggestions but they have to be easily understood because I’m a moron and coming back to the code after a while it all seems like gobbledy-gook!

Now then Blue Eyes, I don’t understand Boolean. Can you explain that to me?

Robin2, I have saved your work and I will study it once I’ve printed it for I cannot assimilate much from a screen! I have put the resetTime function on a ‘clean sheet’ which made me decide to ditch the timing for the time being. I also thought I’d try using a switch case arrangement and it gets over the problem but as it is now, I find that the procedure is unstable. sometimes it runs through well, other times it jumps about.

One other thing, The variables year, month, date, hour and minute are global and used in the procedure to reprogram the RTC. It seems that something like ++hour doesn’t actually change that variable, am I wrong?

// Function names used: checkReset,setTime,displayTime,heat,rain,
//Digital pins used:2 heat. 3 LED?. 4 DHT. 5 Rain. 6 Time sw. 7 No sw. 8 Yes sw. 9 Humidity.
//                 10 OneWire. 11 PWM. 12 . 13 .
//Analogue pins used:0 Random. 1 . 2 . 3 . 4 I2C. 5 I2C. 6 . 7 .
//Notes:Timer setting available on reset: hardware reset switch needed
//Modules used:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <Wire.h>
#include<LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#include <BH1750.h>
#include <RealTimeClockDS1307.h>

BH1750 lightMeter;
#define DS1307_ADDRESS 0x68
#define BACKLIGHT_PIN 3
#define DHTPIN 4
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

//The position of the following is critical!
byte decToBcd(byte val) {
  return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val) {
  return ((val / 16 * 10) + (val % 16));
}


OneWire ds(10);  // on pin 10
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7); // 0x3F is the LCD address
byte amend;
byte atd ;// difference between inside air temp and OAT. ATMOSPHERE
byte breeze;  //ATMOSPHERE

byte count1 = 0; //atmosphere
byte date = 0; //checktime, settime, readtime
byte day = 0;
byte edit = 0;
byte heaterState = 0;
byte heatStart = 0;

byte hour = 0;
byte hrst = 0;


byte lastInput = 0;
byte lightLevel;

byte minute = 0;
byte month = 3;

byte No = 7;
//byte no;
byte orbit;

byte resetRTC = 0;
byte second = 0;
byte startup = 1; //heating
byte intSwitch = 6;
byte year = 16;
byte Yes = 8;
//byte yes;
byte zero = 0x00; //Workround for issue #527










unsigned long wait;
float adjustment;  //heating
float air;  //atmosphere
float baseTemp;  //heating
float basic[] = {0, 12.5, 12.5, 12.5, 14.00, 15.95, 18, 18, 18, 18, 16, 14, 12.5};
float controlTemp;
float dayEnvelope;
float dvt = 0.01875;
float hTime;
float hysteresis = 0.25;

float temperature;
float minNow = (hour * 60) + minute + (second / 60);
float variation[] = {0, 0, 0, 0.05, 0.065, 0.065, 0, 0, 0, 0.065, 0.065, 0.05, 0};

//SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
void setup() {
  Wire.begin();
  lcd.begin(20, 4);
  Serial.begin(9600);
  dht.begin();
  lightMeter.begin();
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);



  pinMode(2, OUTPUT); //Heat
  pinMode(6, INPUT); //reset
  pinMode(7, INPUT); //the no switch
  pinMode(8, INPUT); //the yes switch
  pinMode(5, OUTPUT); //Rain
  pinMode(9, OUTPUT); //Humidity
}  //End Setup

//==================================================================
void loop() {


  displayTime();

  heating();

  humidity();

  //displayTime();

  light();

  atmosphere();

  if (digitalRead(intSwitch) == HIGH)checkReset();

}




//==================================================================
void checkReset() {

  /*while (digitalRead(Yes) == HIGH || digitalRead(No) == HIGH) {
    //Do nothing to make sure Yes/No button isn't pressed inadvertantly
    }
  */
  lcd.clear();
  lcd.setCursor(0, 2);
  lcd.print(" Change Date/Time?");
  lcd.setCursor(0, 3);
  lcd.print("No               Yes");

  wait = (millis() + 10000); // Response time = 10 seconds

  while (wait > millis()) { //this is the quit timer

    if (digitalRead(No) == HIGH) {

      wait = millis(); //to get out of loop
    }
    if (digitalRead(Yes) == HIGH) {
      delay(500);
      resetTime();
      lcd.clear();
    }
  }
  // if no input return after (ten) seconds
  lcd.clear();
}

// End of 'checkReset'

//----------------------------------------------------------
void resetTime() {

  wait = (millis() + 10000);
  lcd.clear();
  while (wait > millis()) {
    lcd.print("The year is 20");
    lcd.print(year);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
    if (digitalRead(No) == 1) {
      ++year;
      if (year > 21)year = 16;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      wait = millis();
    }

  } // End year loop

  //------------------------------------

  wait = (millis() + 10000);
  lcd.clear();
  while (wait> millis()) {
    lcd.print("The month is ");
    if (month < 10)lcd.print(" ");
    lcd.print(month);
    lcd.setCursor(6, 2);
    lcd.print("Correct?");
    lcd.setCursor(0, 3);
    lcd.print("No               Yes");
    if (digitalRead(No) == 1) {
      ++month;
      if (month > 12)month = 1;
      delay(500);
      wait = (millis() + 10000);
      lcd.clear();
    }
    if (digitalRead(Yes) == 1) {
      lcd.clear();
      wait = millis();
    }
  } // End month loop


  //------------------------------------------------------------------
  /* Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(zero);
    Wire.write (decToBcd(second));
    Wire.write (decToBcd(minute));
    Wire.write (decToBcd(hour));
    Wire.write (decToBcd(day));
    Wire.write (decToBcd(date));
    Wire.write (decToBcd(month));
    Wire.write (decToBcd(year));
    Wire.write(zero);
    Wire.endTransmission();
    lcd.clear();
  */
}  //end of resetTime

Adrifran39:
Now then Blue Eyes, I don't understand Boolean. Can you explain that to me?

I'm not trying to be mean, but really... there are so many places on the internet that can explain that. This question just screams, "Google!".

because I'm a moron

I'm not near as bad as one of my former co-workers, but all my programs are heavily commented. I can follow the code, easily enough, but WHY did I do that, that way? That's what I don't remember two weeks (or days or sometimes minutes later), so I use lots of comments. They take no space in the file loaded to the Arduino, but anyone reading my code later can see what I was thinking when I wrote the code.

I also usually write the comments first, creating an outline for the program. The program then pretty much writes itself, with only the random() function causing the occasional syntax error.

Beats actually working.

Adrifran39:
I cannot assimilate much from a screen!

I do understand that, but I strongly recommend that you develop the ability to do so because so much info is now available on the web rather than on paper.

With a printed version you can't easily follow links to other material.

And if you can assimilate stuff on the screen you can easily identify the irrelevant stuff at great saving to your stock of paper.

...R