When button is pushed it takes to long to read, misses normal button push

Here is the code for a Mung Bean grower that controls temperature, the watering cycle, and watering on time. I have a lot of notes, just to help me learn, as my son wrote 90% of the code.
I have one problem! The button hold down time is to long to get a read, It misses the read with a normal push time of the button.
I have removed operation of all delay(), however, millis() is used and the internal clock is used.
Can you see what is causing the hold up is in the button pushing?

// This sketch is for a Bean Sprout Grower. It controls temperature (using a DS18B20),
//how many hours between pump cycles, and how long the pump is on during each 
// watering cycle. The "Set Temperature", "Set Water Cycle", and 'Set Shower Time" are 
//sequenced through using the Select button, The UP/DOWN buttons are used to set the 
// temperature', how long the 'Water Cycle' is (in Hours) , and the length of the 
//'water shower' (in 5 second increments).
//
// Libraries used

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
                        //Sets digital pins for LCD 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int relayHeat = 12;
int relayPump = 11;
                       //x= analog read of pin A (buttons)
int x;   
                     // Sets S at 0 for button sequencing
int S = 0; 
               // millis count
unsigned long currentTime;
              //millis before adding
unsigned long previousTime;   

int temperature;
int tempC;
const int oneWireBus = 3;
OneWire oneWire(oneWireBus);
DallasTemperature sensors (&oneWire);
           // Sets intitial thermostat temperature
int setPoint = 80;
int H2OcycleVis = 0;
unsigned long H2OcycleReal = 0; //Change this back to 0 for prime time.
int H2OtimeVis= 0;
int H2OtimeReal= 0;
                // gets the temerature from Index in *F
int getTempFByIndex;
                 //this is the cycle time in ms. Change it to whatever time interval you want to test. 
                   //3,600,000 = sequencing in 1HR intervals
const unsigned long H2Oc =20000;
              //  this is the 'Watering Time' ON in ms. In 5 Second Increments
const unsigned long H2Ot = 5000; 
const int tempM = 0;

void setup() {
  lcd.begin(16, 2);
  pinMode(relayHeat, OUTPUT);
  pinMode(relayPump, OUTPUT);
  pinMode (3, INPUT);
  Serial.begin(9600);
  sensors.begin();
}

void loop() {

sensors.requestTemperatures();

temperature = sensors.getTempFByIndex(0);

currentTime = millis();

x = analogRead (0);


  //Serial.print("F: ");
  //.print(sensors.getTempFByIndex(0)); //change back to 0
  //Serial.print("\t Temperature: ");
  //Serial.print(temperature);
  //Serial.print("\t C: ");
  //Serial.println(sensors.getTempCByIndex(0)); //change back to 0
  //Serial.print("\t H2O Cycle Real: ");
  //Serial.print(H2OcycleReal);
  //Serial.print("\t H2O Time Real: ");
  //Serial.print(H2OtimeReal);
  //Serial.print("\t currentTime: ");
  //Serial.print(currentTime);
  //Serial.print("\t previousTime:");
  //Serial.println(previousTime);
  //Serial.print("\t TempH:");
  //Serial.print(tempH);
  //Serial.print("\t Heat On:");
  //Serial.println(12);


              // This steps through the select button choices
if (S > 3){
  S = 0; }
  if (x > 600 && x < 800)
  { S++; 
                               //delay(100);
}
// This lcd prints the temp when S=0
if (S == 0) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature ");
  lcd.setCursor(6,1);
  lcd.print(temperature);
  lcd.setCursor(8,1);
  lcd.print (" F");  
                                  //delay(100);
}
                       // This lcd prints 'Set Temperature' when S=1 
                      //and increments DOWN button with (x > 100 && x < 200) or UP x > 200 && x < 400
if (S == 1) { 
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Temerature ");
  lcd.setCursor(6,1);
  lcd.print (setPoint);
    lcd.setCursor(8,1);
  lcd.print (" F   "); 
  if (x > 100 && x < 200) {
   setPoint++;
                                   //delay(500);
  }
  if (x > 200 && x < 400) {
    setPoint--;
                                 //delay(500);
  }  
}
                         //This lcd prints 'Set Water Cycle' when S=2 
                        //and increments UP Button with (x > 100 && x < 200)or UP with x > 200 && x < 400
if (S == 2) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Water Cycle ");
  lcd.setCursor(5,1);
  lcd.print (H2OcycleVis);
  lcd.setCursor(8,1);
  lcd.print ("hr(s)");
  if (x > 100 && x < 200) {
    H2OcycleVis++;
    H2OcycleReal = H2OcycleReal + H2Oc;
                          //delay(100);
  }
  if (x > 200 && x < 400) {
    H2OcycleVis--;
    H2OcycleReal = H2OcycleReal - H2Oc;
                          //delay(100);
  }  
}
                        //This lcd prints 'Set Shower Time' if S=3 
                        //and increments DOWN Button (x > 100 && x < 200) or UP with x > 200 && x < 400
if (S == 3) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Shower Time:");
  lcd.setCursor(3,1);
  lcd.print (H2OtimeVis);
  lcd.setCursor(7,1);
  lcd.print ("seconds");
  if (x > 100 && x < 200) {
   H2OtimeVis = H2OtimeVis + 5;
   H2OtimeReal = H2OtimeReal + H2Ot;
                          //delay(100);
  }
  if (x > 200 && x < 400) {
    H2OtimeVis = H2OtimeVis - 5;
    H2OtimeReal = H2OtimeReal - H2Ot;
                           //delay(100);
  }  
}
// Internal Clock counting down Hourly cycle
if(currentTime - previousTime > H2OcycleReal) {
  previousTime = currentTime;
}
// this resets currentTime when internal clock hits maximum count.
if (currentTime < 2000) {
  previousTime = currentTime;
}
                       // If 'Set Water Cycle' time is reached turn on Pump
if (currentTime - previousTime < H2OtimeReal){
    digitalWrite(11, HIGH);
   }
   else {
     (digitalWrite(11, LOW));
   }
                           // Turns heater off if temp reaches SetPoint, 
if ( temperature >= (setPoint)){
  digitalWrite(12, LOW);
}
if ( temperature <= (setPoint)){
  digitalWrite(12, HIGH);
}
//delay(50);
}

Where do you think you are reading the state of a button? Usually that is done with a digitalRead function but I don't see that being done anywhere. Is your button connected to Pin 3?

Sorry, I'm using a 1602 Keypad shield. The buttons are connected to a resistor ladder and each button outputs a different Voltage, it is connected to the A0 pin.
Thanks, Douger

You have a medium complexity timing schedule. Please explain the sequence clearly. A diagram is often helpful.

Apart from that, I can see some obvious millis() blunders. Here

// this resets currentTime when internal clock hits maximum count.
if (currentTime < 2000) {
  previousTime = currentTime;
}

This will only be executed during the first 2 seconds after boot. If it's intentional, the reason should be documented.

This is above my level, but as understand it, the Uno has an internal counter (currentTime), that runs 49.71 days, then it resets to zero.

// this resets previousTime to the new lower number when internal clock hits maximum count. 49.71 days
// it would seem this should be zero, but.. the internal counter is  always running and may have //passed zero, so to be safe 2000 was used.
if (currentTime < 2000) {
  previousTime = currentTime;

I have no way to know that this works without running it 49 days. It is not my code
Douger

I can tell you what it would do, regards the 49 days. The sequence will repeat - every 49 days it will do that for 2 seconds.

You haven't responded to my request for information about what it is supposed to do, so there is no way to say whether it "works" or not. If that is what it is intended to do, it works. But I doubt that is the case.

At this point, it seems like you are not pursuing this as a learning opportunity, rather leaning on chatGPT and forum suggestions. That always becomes tedious and is usually fruitless. So unless you want to engage as a genuine learner, I am out of this thread. If things are "above your level" then you need to start learning, or else go somewhere else for help. If you do want help, you have to at least follow the ball.

What I requested from you, is not special, it is described in the forum introductory guide.

What exactly do you want from this thread? If it's correcting every one of 100 bad guesses that you make, I will have no part of that, and most smart people here won't either.

If you want to learn Arduino, you are in the right place but you have to find your level and develop your skill there.

// this resets previousTime to the new lower number when internal clock hits maximum count. 49.71 days
// it would seem this should be zero, but.. the internal counter is  always running 

I'm not signed up for chatGPT, I looked it before I even got and Arduino, but they wanted to much information so I didn't signup, and I thought the note I wrote did describe what the code was supposed to do. As in " this resets previousTime to the new lower number when internal clock hits 49.71 days.

                        Douger

Not saying it's the answer but, this:

x = analogRead(0);

should be

x = analogRead(A0);

Add a Serial.print statement to monitor the value of x (not the best name for a variable BTW).

Please, a description of the timing sequence or you go on my permanent ignore list. It should be easy for you, requires no technical knowledge whatsoever...

Sorry about the chatGPT comment, I confused you with someone else.

Fine, Bye, I don't even know what a timing sequence looks like. I started looking at how to code 10 days ago. Save your attitude to use on others.
Douger

Well then it's unlikely that anyone anywhere would be able to help you write this. Because you would definitely need to know the target behaviour. Otherwise it's only a billions to one chance that the program would perform what it is (secretly) supposed to do. Good luck.

I don't have an "attitude". I have a sincere desire to help people, but when they don't respect my simple requests for information, I definitely have something to say about it. Because my time is valuable, and was wasted.

If you don't know what a timing sequence is, you can simply ask.

Those do the same thing:

You can call analogRead() with either the pin number or the analog channel number.

Which sneaks up on people, when they decide to change an analog input to a digital mode.

The delay(100) statements, which you have commented out, were presumably to debounce the button presses and probably necessary to prevent options from being skipped over.
The library <DallasTemperature.h> may be causing blocking and there are non blocking versions or simply read the temperature every say 10 seconds instead of every loop() iteration.

Maybe so, but I haven't seen that problem, even though a long button down time is required. about to 0.5 second or a bit less. I removed all the delay() hoping that would speed up my buttons, it didn't, but I didn't see that removing them caused any problem either.

What is timing sequence?

I added the 0 to make the pin A0.
I also removed this bit of code,

if (currentTime < 2000) {
  previousTime = currentTime;

The buttons are still slow. Programs works for now. I.E. I have an LED simulating the watering cycle and a relay connected tuning an LED simulating the heater.
Douger

Just as a test, try commenting out these two lines to see if the buttons are more responsive. It may help to identify the problem.

Looks like you are on to something here!! Button down time is reduced when those two lines are commented out. It seems sensors.requestTemperatures(); is causing the button problem.
I can leave, temperature = sensors.getTempFByIndex(0) in the code and the button is still faster.
So are we back to the comment about, "The library <DallasTemperature.h> may be causing blocking and there are non blocking versions or simply read the temperature every say 10 seconds instead of every loop() iteration." I did a search for non blocking DallasTemperature library, but didn't see anything right away.

I did need to add back in a delay(100) in this section of the code, otherwise it would skip options occasionally.

// This steps through the select button choices
94  if (S > 3){
95   S = 0; }
96    if (x > 600 && x < 800)
97    { S++; 
98  delay(100);

Thanks all for the input, I need to get up early in the morning. I'll check back in here about 11am and see what my next step is.
Thanks to all for your input and a special thanks to aarg for hanging in here with me :slight_smile:

You can try replacing those two lines with this code block. It reads the temperature every 15 seconds instead of every loop() iteration:

static uint32_t lastLoopAtMs = 0 ;  // static initialized once only
if ( millis() - lastLoopAtMs > 15000UL)  { // 15 seconds
   lastLoopAtMs = millis() ;
   sensors.requestTemperatures() ; 
   temperature = sensors.getTempFByIndex(0) ;
}

Or maybe you find something with this search phrase: "arduino dallas temperature sensor blocking"