Debounce button and delays

Hi Larry!
your post #120: I made the changes, it was for me in code line 266 and 267.

your post #121: first I set settemp and hyst. above room temp, : room temp 25,9, settemp 28, hystt 26,5

now i push thermostat on, nothing happens

now i push settemp down to 27, so hyst. is 25,5, room still was 25,9). suddenly swamp cooler and LED toggles endless, and at the same time room temp jumps between 24,5 and 25,9 up and down (like yesterday)

sorry i am not on your level to help, but I started to read through all your links

Hi Larry,
i reading through the "how to get the best out of this forum" I of course owe you proof of studying...
One thing caught my eye already last week: the void loop I know, but you close it and then open another loop checkswitches and so on. is this because you can write the code easier in segments? at the same time i realize in the "non void loop" you must refer back to the void loop with for example "setpoint()". am I right this means its a way of connecting the outcome of the code segments to each other??
in the setup you keep resetting the timer. does that mean there are different timers in this code? or is this one timer for the whole scetch ( more likely for me), but then would we not influence the other timer conditions like reading the temp or temp flag or check switches?

Hi Larry,
as I keep learning....
I had to accept one of the two: either live with the delay in reading the temp sensor +converting the signal into a celcius, or, as you suggested, let it do it by its own and keep doing something else in the meantime. (of course more sophisticated).
now, as i study your code, am i right, you didnt do too much coding on that, or lets say you did not have to trick the controller in anyway, since there are simple commands in the library such as

sensors.setWaitForConversion(false);
sensors.requestTemperatures();
sensors.setWaitForConversion(true); ???

if my assuption is true then that would be a kind of easy way of learning, if i run into such an issue in the future i reseach it and somebody tells me the library has such a "tricky " solution in it, i just have to find out the actual code line and write it in the scetch, is it that simple?

Hum . . .
I tried to emulate the same here.
It works like it should.

Is there a possibility that your wiring might be picking up noise on the temperature sensor OR other wires getting noise from somewhere ?

Until I can reproduce things here, it will be difficult to troubleshoot form my end.


You might have to put some serial prints in your sketch to track down what variable values are doing at your end as things work here.

You can then read those variables to see if those code lines are causing the problem.
Example:

//******************************************************************************************
//IR controls sent to Swamp Cooler
void  adjustTemperature()
{
  //************************
  //when the cooler is OFF and the temperature is too hot, turn ON the cooler
  if (unitOnOffFlag == OFF && currentTemperature > settemphyst)
  {
    Serial.println("unit comming ON");      // <-----<<<<<
    Serial.print("currentTemperature =");      // <-----<<<<<
    Serial.println(currentTemperature);      // <-----<<<<<
    Serial.print("settemphyst =");      // <-----<<<<<
    Serial.println(settemphyst);      // <-----<<<<<
    Serial.println("");      // <-----<<<<<
        
    unitOnOffFlag = ON;

    //turn ON the cooler LED
    digitalWrite(coolerOnOffLED, LEDon);

    sendIRcontrol();
  }

  //************************
  //when the cooler is ON and the temperature is cold enough, turn OFF the cooler  
  //0.5 is to add a small amount extra hysteresis
  if (unitOnOffFlag == ON && currentTemperature <= settemphyst - 0.5)
  {
    Serial.println("unit going OFF");      // <-----<<<<<
    Serial.print("currentTemperature =");      // <-----<<<<<
    Serial.println(currentTemperature);      // <-----<<<<<
    Serial.print("settemphyst =");      // <-----<<<<<
    Serial.println(settemphyst);      // <-----<<<<<
    Serial.println("");      // <-----<<<<<
    
    unitOnOffFlag = OFF;

    //turn OFF the cooler LED
    digitalWrite(coolerOnOffLED, LEDoff);

    sendIRcontrol();
  }

} //END of  adjustTemperature()


//******************************************************************************************

“One thing caught my eye already last week: the void loop I know, but you close it and then open another loop checkswitches and so on. is this because you can write the code easier in segments? at the same time i realize in the "non void loop" you must refer back to the void loop with for example "setpoint()". am I right this means its a way of connecting the outcome of the code segments to each other??”

  • The loop() function starts at the opening brace {.

  • Code between the { and } is run until the closing brace }; at which time the program goes back the loop() function opening brace { once more.

  • This goes on forever.

  • The checkSwitches() function never runs by itself.

  • Code in loop() must call the checkSwitches() function when its time to do so.

  • When the checkSwitches() function finishes, a return to the loop() function occurs.

  • A call to a function looks like this checkSwitches();

  • This is a call to setpoint(); within that function, the setpoint changes are updated to the LCD.

“in the setup you keep resetting the timer. does that mean there are different timers in this code? or is this one timer for the whole scetch ( more likely for me), but then would we not influence the other timer conditions like reading the temp or temp flag or check switches?”

These are the timers in the sketch:

  • if (currentMillis - heartbeatMillis >= 500) For flashing the heartbeat LED

  • if (currentMillis - switchMillis >= 50) For switch sampling

  • if (currentMillis - tempMillis >= 1000) For temperature reading

  • if (temperatureControlFlag == ENABLED && currentMillis - controlMillis >= 1000) For turning the cooler on/off

“I had to accept one of the two: either live with the delay in reading the temp sensor +converting the signal into a celcius, or, as you suggested, let it do it by its own and keep doing something else in the meantime. (of course more sophisticated).
now, as i study your code, am i right, you didnt do too much coding on that, or lets say you did not have to trick the controller in anyway, since there are simple commands in the library such as”

sensors.setWaitForConversion(false);
sensors.requestTemperatures();
sensors.setWaitForConversion(true); ???

  • The above code tells the 18B20 software not to block code execution while the 18B20 is converting the temperature.

  • The code executes in a TIMER that runs every 1000ms. Therefore, when a full second goes by, the 18B20 will have finished with its conversion, we can then read the temperature with the Arduino

“if my assuption is true then that would be a kind of easy way of learning, if i run into such an issue in the future i reseach it and somebody tells me the library has such a "tricky " solution in it, i just have to find out the actual code line and write it in the scetch, is it that simple?”

  • You ask for help.

  • Actually there usually are examples with every Library that show how things are done. You can access these examples in the Arduino IDE.




Also

Version 1.26 with changes we talked about in post #120

//https://forum.arduino.cc/t/debounce-button-and-delays/902601

// Version    YY/MM/DD  Description
// 1.00       21/09/06  Running sketch
// 1.01       21/09/06  Some comments added
// 1.02       21/09/06  Slowed the sampling of the 18B23
// 1.03       21/09/06  Now updating set-points only when the UP or Down switches are pushed
// 1.04       21/09/06  Some comments added
// 1.20       21/09/12  IR controls being added
// 1.21       21/09/12  IR ON/OFF control is sent when the power ON/OFF switch is pressed
// 1.22       21/09/12  added temperature control feature
// 1.23       21/09/12  Functional sketch, to be tested           
// 1.24       21/09/12  reversed the temperature controls
// 1.25       21/09/12  added 0.5 degrees hysteresis to the temperature level where the unit turns OFF
//                      changed delay(1000) to delay(50)
// 1.26       21/09/12  Misplaced semicolon bug.  AND, commented line: IRsend irsend; 
//                      AND added a return; in   adjustTemperature()
// 
//

#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>         //library from temp sensor 18b20
#include <OneWire.h>                   //library communication from temp sensor 18b20

#define ONE_WIRE_BUS              2    //DS18B20 connected to this pin, add a 4.7K pull-up
OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 20, 4);

//******************************************************************************************
//remove the // at the 'beginning' of the next line to incorporate future IR code stuff
//#define  tarabas05  //                                                          <-----<<<<<<<

#ifdef tarabas05

#include <IRremote.h>               //use version 3.3.0
#include "PinDefinitionsAndMore.h"  //should be in the same folder as this file
//IRsend irsend;

#endif

//change the next line of code as needed i.e. to the way your switches are wired  <-----<<<<<<<
#ifdef tarabas05

//External +5V---[Switch]---[10k]---GND
//yours
#define CLOSED                    HIGH

#else

//Internal +5V---[50k Internal Pull-up]---[Switch]---GND
//mine
#define CLOSED                    LOW

#endif
//******************************************************************************************

#define OPEN                      !CLOSED

#define ON                        HIGH
#define OFF                       LOW

#define PUSHED                    LOW
#define NotPUSHED                 HIGH

#define ENABLED                   true
#define DISABLED                  false

#define RUNNING                   true
#define notRUNNING                false

#define LEDon                     HIGH
#define LEDoff                    LOW


float settemp                   = 25;
float settemphyst;
float currentTemperature;
float hysteresis                = 1.5;     //set this to what every you need

bool temperatureControlFlag     = DISABLED;
bool unitOnOffFlag              = OFF;

//*************************************
//I/O pins used:
//Note: pin 13 is used byte IR library as a feedback LED
const byte coolerOnOffLED       = 12;
const byte buttonUp             = 10;
const byte buttonOnOff          = 9;
const byte buttonDown           = 8;
const byte heartbeatLED         = 6;
//Note: pin 3 is the IR LED pin
//Note: pin 2 is the 18B20 temperature sensor connection


byte OnOffState                 = OFF;
byte lastButtonState;
byte lastbuttonUp;
byte lastbuttonDown;
byte currentstate;

//Timing stuff
unsigned long currentMillis;
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long tempMillis;
unsigned long controlMillis;


//******************************************************************************************
void setup()
{
  Serial.begin(9600);

#ifdef tarabas05

  //yours
  pinMode(LED_BUILTIN, OUTPUT);
  //IR_SEND_PIN = pin 2
  IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);

  //lcd.begin();

#else

  //mine
  lcd.begin(20, 4);
  lcd.init();

#endif

  pinMode(heartbeatLED, OUTPUT);

  pinMode(coolerOnOffLED, OUTPUT);
  digitalWrite(coolerOnOffLED, OFF);

  pinMode(buttonDown,  INPUT_PULLUP);
  pinMode(buttonUp,    INPUT_PULLUP);
  pinMode(buttonOnOff, INPUT_PULLUP);

  sensors.begin();

  lcd.backlight();

  //                   1111111111
  //         01234567890123456789
  lcd.print("Hello guys");
  lcd.setCursor(0, 1);
  lcd.print("MY Invention");
  
  delay(1000);

  lcd.clear();
  lcd.print("Swamp Cooler");
  
  lcd.setCursor(0, 1);
  lcd.print("Thermostat");
  
  lcd.setCursor(0, 2);
  lcd.print("Room");
  
  lcd.setCursor(19, 2);
  lcd.print('C');
  
  lcd.setCursor(0, 3);
  lcd.print("Set T.");
  
  lcd.setCursor(10, 2);
  lcd.print((char) 223);  // ° degree
  lcd.print('C');
  
  lcd.setCursor(18, 2);
  lcd.print((char) 223);  // ° degree
  lcd.print('F');
  
  lcd.setCursor(17, 1);
  lcd.print("OFF");

  //update the LCD
  setpoint();
}


//******************************************************************************************
void loop()
{
  //get the current time since the Arduino was powered ON
  currentMillis = millis();

  //*************************************
  //used to see if our code is blocking
  //the heartbeat LED should regularly toggle, every 1/2 second
  //is it time to toggle the LED ?
  if (currentMillis - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = currentMillis;

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************
  //is it time to check the switches ?
  if (currentMillis - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = currentMillis;

    checkSwitches();
  }

  //*************************************
  //is it time to read the temperature ?
  if (currentMillis - tempMillis >= 1000)
  {
    //restart the TIMER
    tempMillis = currentMillis;

    //the last conversion request will be finished by now
    //get the temperature
    lcd.setCursor(5, 2);
    currentTemperature = sensors.getTempCByIndex(0);
    lcd.print(currentTemperature, 1);

    //lcd.print(sensors.getTempCByIndex(0), 1);
    lcd.setCursor(13, 2);
    lcd.print(sensors.getTempCByIndex(0) * 1.8 + 32, 1);

    //Serial.println(sensors.getTempCByIndex(0), 1);

    //start a new conversion request
    sensors.setWaitForConversion(false);
    sensors.requestTemperatures();
    sensors.setWaitForConversion(true);
  }

  //*************************************
  //if enabled, is it time to check to see if the temperature should be adjusted ?
  if (temperatureControlFlag == ENABLED && currentMillis - controlMillis >= 1000)
  {
    //restart the TIMER
    controlMillis = currentMillis;

    adjustTemperature();

  }

  //*************************************
  // Other non blocking code goes here
  //*************************************

} //END of loop()


//*******************************************************************************************
//scan the switches to see if there was a change in state
void checkSwitches()
{
  //*************************************              b u t t o n O n O f f
  currentstate = digitalRead(buttonOnOff);

  //was there a switch change in state ?
  if (lastButtonState != currentstate)
  {
    //update to the new state
    lastButtonState = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      //toggle the thermostat condition
      OnOffState = !OnOffState;

      lcd.setCursor(17, 1);

      if (OnOffState == ON)
      {
        lcd.print(" ON");

        //allow the temperature to be controlled
        temperatureControlFlag = ENABLED;
      }

      else
      {
        lcd.print("OFF");

        //controller is now OFF make sure the cooler is OFF
        if (unitOnOffFlag == ON)
        {
          unitOnOffFlag = OFF;
          
          //turn OFF the cooler LED
          digitalWrite(coolerOnOffLED, LEDoff);

          //turn OFF the cooler 
          sendIRcontrol();
        }

        //disallow the temperature to be controlled
        temperatureControlFlag = DISABLED;
      }
    }

  } //END of  buttonOnOff

  //*************************************              b u t t o n U p
  currentstate = digitalRead(buttonUp);

  //was there a switch change in state ?
  if (lastbuttonUp != currentstate)
  {
    //update to the new state
    lastbuttonUp = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      settemp++;

      //update the LCD
      setpoint();
    }

  } //END of  buttonUp

  //*************************************              b u t t o n D o w n
  currentstate = digitalRead(buttonDown);

  //was there a switch change in state ?
  if (lastbuttonDown != currentstate)
  {
    //update to the new state
    lastbuttonDown = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      settemp--;

      //update the LCD
      setpoint();
    }

  } //END of  buttonDown

  //*************************************              n e x t   s w i t c h

} //END of checkSwitches()


//******************************************************************************************
//update the LCD with the set-point information
void setpoint()
{
  lcd.setCursor(7, 3);
  lcd.print (settemp, 0);
  
  lcd.setCursor(10, 3);
  lcd.print((char) 223);  // ° degree
  lcd.print ('C');

  lcd.setCursor(15, 3);
  lcd.print(settemp * 1.8 + 32, 0);
  
  lcd.setCursor(18, 3);
  lcd.print((char) 223);  // ° degree
  lcd.print('F');

  settemphyst = (settemp - hysteresis);
  lcd.setCursor(13, 0);
  lcd.print (settemphyst, 1);
  
  lcd.setCursor(18, 0);
  lcd.print((char) 223);  // ° degree
  lcd.print('C');

} //END of setpoint()


//******************************************************************************************
//IR controls sent to Swamp Cooler
void  sendIRcontrol()
{
#ifdef tarabas05

  const uint8_t NEC_KHZ = 38; // 38kHz carrier frequency for the NEC protocol

  const uint16_t irSignal[] = { 8600, 4280, 520, 1620, 520, 560, 520, 540, 560, 520, 520, 540, 520, 560, 520, 560, 520, 540, 520, 560, 520, 540, 580, 1580, 520, 1620, 520, 1620, 520, 1640, 520, 1620, 560, 1580, 580, 1560, 580, 500, 580, 1560, 580, 500, 560, 1580, 520, 560, 520, 1620, 580, 500, 520, 540, 540, 1600, 580, 500, 520, 1620, 580, 500, 520, 1640, 500, 560, 560, 1580, 520, 40200, 8660, 2120, 560, 26664, 8660, 2120, 520, 26704, 8640, 2120, 560}; // Using exact NEC timing
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.

  delay(50); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal

#endif

} //END of sendIRcontrol()


//******************************************************************************************
//IR controls sent to Swamp Cooler
void  adjustTemperature()
{
  //************************
  //when the cooler is OFF and the temperature is too hot, turn ON the cooler
  if (unitOnOffFlag == OFF && currentTemperature > settemphyst)
  {
    unitOnOffFlag = ON;

    //turn ON the cooler LED
    digitalWrite(coolerOnOffLED, LEDon);

    sendIRcontrol();

    //we just turned the unit ON, no use checking if we should turn it OFF right away
    return;
  }

  //************************
  //when the cooler is ON and the temperature is cold enough, turn OFF the cooler  
  //0.5 is to add a small amount extra hysteresis
  if (unitOnOffFlag == ON && currentTemperature <= settemphyst - 0.5)
  {
    unitOnOffFlag = OFF;

    //turn OFF the cooler LED
    digitalWrite(coolerOnOffLED, LEDoff);

    sendIRcontrol();
  }

} //END of  adjustTemperature()


//******************************************************************************************


As test, change the above to:
//*************************************
//if enabled, is it time to check to see if the temperature should be adjusted ?
if (temperatureControlFlag == ENABLED && currentMillis - controlMillis >= 5000) // <———<<<<<<

hi larry, thank you for your continous help.
your post #125: "picking up noise". i uploaded my very old code i programmed years ago (slown bottons, incorrect behaviour coming on the very first time, currently doesnt send IR)
with my code the room temp is always stable, it doesnt matter how often i adjust settemp up or down. the hysterises works correct ( i can verify with my regular on/off ;LED)
on your code the hysterises dont work, because the swamp cooler always comes on once the room temp is over the hysterises, which shouldnt be the case. the swamp cooler should come on only when the room temp is above the settemp. then the cooler cools so long until the room temp reaches the hysterises temp., then the cooler goes off until settemp is hit again
to confirm that i really dont have noise influencing my temp sensor i ordered all parts to create a brand new hardware thermostat on a bread board to see if there is a difference. the parts i will get on the weekend.

btw, eveytime i use your code i have to remove at line 128 the numbers out of lcd.begin(20, 4); otherwise it says exit status 1
no matching function for call to 'LiquidCrystal_I2C::begin(int, int)'

i also remove at line 129 lcd.init(); otherwise it says
exit status 1
'class LiquidCrystal_I2C' has no member named 'init'
i am pretty sure that isnt the problem we keep having.

your last suggestion at post #127 if (temperatureControlFlag == ENABLED && currentMillis - controlMillis >= 5000)
i believe it creates a reaction delay, but it wouldnt change the behavior. the room temp i saw bouncing around once, also the issue with the hysterises wouldnt change.
please allow me to ask you another time, in your code is there perhaps a stored stage missing? that means once the room temp goes over the settemp then the swamp cooler supposed to come on ; it stores the on state until UNTIL hysterises is met.
hysterises alone should not be able to make the swamp cooler come one.

testing your serial print in:
i added it in the code and i uploaded it. i tried it twice: the swam cooler comes on by itself after upload, even the thermostat says off.
once i got everything to be syncronisized ( state thermostat is off and swamp cooler is off), i played with the settings. basically the serial monitor tells me the same what the thermostat display tells me, there is no hint of a diviating actual state versus an expected state.
during playing with the temps the room temps bounces and the swamp cooler gets toggles on /on repeatedly

Sounds like you may have hardware/voltage/wiring problems.


The sketch here is rock stable, however, I cannot check the IR portion.


My LCD library is different than yours, hence I need different initializing.




Version 1.27
I added some time delay when a IR message is sent. Might help if there is electrical noise.

Show us a good image of different views of the actual wiring.


Remember to delete the // comment marks.

//https://forum.arduino.cc/t/debounce-button-and-delays/902601

// Version    YY/MM/DD  Description
// 1.00       21/09/06  Running sketch
// 1.01       21/09/06  Some comments added
// 1.02       21/09/06  Slowed the sampling of the 18B23
// 1.03       21/09/06  Now updating set-points only when the UP or Down switches are pushed
// 1.04       21/09/06  Some comments added
// 1.20       21/09/12  IR controls being added
// 1.21       21/09/12  IR ON/OFF control is sent when the power ON/OFF switch is pressed
// 1.22       21/09/12  added temperature control feature
// 1.23       21/09/12  Functional sketch, to be tested
// 1.24       21/09/12  reversed the temperature controls
// 1.25       21/09/12  added 0.5 degrees hysteresis to the temperature level where the unit turns OFF
//                      changed delay(1000) to delay(50)
// 1.26       21/09/12  Misplaced semicolon bug.  AND, commented line: IRsend irsend;
//                      AND added a return; in   adjustTemperature()
// 1.27       21/09/15  Added 'adjustInterval' for possible electrical noise problems
//

#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>         //library from temp sensor 18b20
#include <OneWire.h>                   //library communication from temp sensor 18b20

#define ONE_WIRE_BUS              2    //DS18B20 connected to this pin, add a 4.7K pull-up
OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 20, 4);

//******************************************************************************************
//remove the // at the 'beginning' of the next line to incorporate future IR code stuff
//#define  tarabas05  //                                                          <-----<<<<<<<

#ifdef tarabas05

#include <IRremote.h>               //use version 3.3.0
#include "PinDefinitionsAndMore.h"  //should be in the same folder as this file
//IRsend irsend;

#endif

//change the next line of code as needed i.e. to the way your switches are wired  <-----<<<<<<<
#ifdef tarabas05

//External +5V---[Switch]---[10k]---GND
//yours
#define CLOSED                    HIGH

#else

//Internal +5V---[50k Internal Pull-up]---[Switch]---GND
//mine
#define CLOSED                    LOW

#endif
//******************************************************************************************

#define OPEN                      !CLOSED

#define ON                        HIGH
#define OFF                       LOW

#define PUSHED                    LOW
#define NotPUSHED                 HIGH

#define ENABLED                   true
#define DISABLED                  false

#define RUNNING                   true
#define notRUNNING                false

#define LEDon                     HIGH
#define LEDoff                    LOW


float settemp                   = 25;
float settemphyst;
float currentTemperature;
float hysteresis                = 1.5;     //set this to what every you need

bool temperatureControlFlag     = DISABLED;
bool unitOnOffFlag              = OFF;

//*************************************
//I/O pins used:
//Note: pin 13 is used byte IR library as a feedback LED
const byte coolerOnOffLED       = 12;
const byte buttonUp             = 10;
const byte buttonOnOff          = 9;
const byte buttonDown           = 8;
const byte heartbeatLED         = 6;
//Note: pin 3 is the IR LED pin
//Note: pin 2 is the 18B20 temperature sensor connection


byte OnOffState                 = OFF;
byte lastButtonState;
byte lastbuttonUp;
byte lastbuttonDown;
byte currentstate;

//Timing stuff
unsigned long adjustInterval    = 1000;  //changes between 1000ms and 5000ms

unsigned long currentMillis;
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long tempMillis;
unsigned long controlMillis;


//******************************************************************************************
void setup()
{
  Serial.begin(9600);

#ifdef tarabas05

  //yours
  pinMode(LED_BUILTIN, OUTPUT);
  //IR_SEND_PIN = pin 2
  IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);

  lcd.begin();

#else

  //mine
  lcd.begin(20, 4);
  lcd.init();

#endif

  pinMode(heartbeatLED, OUTPUT);

  pinMode(coolerOnOffLED, OUTPUT);
  digitalWrite(coolerOnOffLED, OFF);

  pinMode(buttonDown,  INPUT_PULLUP);
  pinMode(buttonUp,    INPUT_PULLUP);
  pinMode(buttonOnOff, INPUT_PULLUP);

  sensors.begin();

  lcd.backlight();

  //                   1111111111
  //         01234567890123456789
  lcd.print("Hello guys");
  lcd.setCursor(0, 1);
  lcd.print("MY Invention");

  delay(1000);

  lcd.clear();
  lcd.print("Swamp Cooler");

  lcd.setCursor(0, 1);
  lcd.print("Thermostat");

  lcd.setCursor(0, 2);
  lcd.print("Room");

  lcd.setCursor(19, 2);
  lcd.print('C');

  lcd.setCursor(0, 3);
  lcd.print("Set T.");

  lcd.setCursor(10, 2);
  lcd.print((char) 223);  // ° degree
  lcd.print('C');

  lcd.setCursor(18, 2);
  lcd.print((char) 223);  // ° degree
  lcd.print('F');

  lcd.setCursor(17, 1);
  lcd.print("OFF");

  //update the LCD
  setpoint();
}


//******************************************************************************************
void loop()
{
  //get the current time since the Arduino was powered ON
  currentMillis = millis();

  //*************************************                   heartbeat TIMER
  //used to see if our code is blocking
  //the heartbeat LED should regularly toggle, every 1/2 second
  //is it time to toggle the LED ?
  if (currentMillis - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = currentMillis;

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                   switch TIMER
  //is it time to check the switches ?
  if (currentMillis - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = currentMillis;

    checkSwitches();
  }

  //*************************************                   temp TIMER
  //is it time to read the temperature ?
  if (currentMillis - tempMillis >= 1000)
  {
    //restart the TIMER
    tempMillis = currentMillis;

    //the last conversion request will be finished by now
    //get the temperature
    lcd.setCursor(5, 2);
    currentTemperature = sensors.getTempCByIndex(0);
    lcd.print(currentTemperature, 1);

    lcd.setCursor(13, 2);
    lcd.print(currentTemperature * 1.8 + 32, 1);

    Serial.println(currentTemperature, 1);

    //start a new conversion request
    sensors.setWaitForConversion(false);
    sensors.requestTemperatures();
    sensors.setWaitForConversion(true);
  }

  //*************************************                   control TIMER
  //if enabled, is it time to check to see if the 
  //temperature should be adjusted ?
  if (temperatureControlFlag == ENABLED && currentMillis - controlMillis >= adjustInterval)
  {
    //return to a 1 second TIMER
    adjustInterval = 1000;

    //restart the TIMER
    controlMillis = currentMillis;

    adjustTemperature();

  }

  //*************************************
  // Other non blocking code goes here
  //*************************************

} //END of loop()


//*******************************************************************************************
//scan the switches to see if there was a change in state
void checkSwitches()
{
  //*************************************              b u t t o n O n O f f
  currentstate = digitalRead(buttonOnOff);

  //was there a switch change in state ?
  if (lastButtonState != currentstate)
  {
    //update to the new state
    lastButtonState = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      //toggle the thermostat condition
      OnOffState = !OnOffState;

      lcd.setCursor(17, 1);

      if (OnOffState == ON)
      {
        lcd.print(" ON");

        //allow the temperature to be controlled
        temperatureControlFlag = ENABLED;
      }

      else
      {
        lcd.print("OFF");

        //controller is now OFF make sure the cooler is OFF
        if (unitOnOffFlag == ON)
        {
          unitOnOffFlag = OFF;

          //turn OFF the cooler LED
          digitalWrite(coolerOnOffLED, LEDoff);

          //turn OFF the cooler
          sendIRcontrol();
        }

        //disallow the temperature to be controlled
        temperatureControlFlag = DISABLED;
      }
    }

  } //END of  buttonOnOff

  //*************************************              b u t t o n U p
  currentstate = digitalRead(buttonUp);

  //was there a switch change in state ?
  if (lastbuttonUp != currentstate)
  {
    //update to the new state
    lastbuttonUp = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      settemp++;

      //update the LCD
      setpoint();
    }

  } //END of  buttonUp

  //*************************************              b u t t o n D o w n
  currentstate = digitalRead(buttonDown);

  //was there a switch change in state ?
  if (lastbuttonDown != currentstate)
  {
    //update to the new state
    lastbuttonDown = currentstate;

    //did the switch close ?
    if (currentstate == CLOSED)
    {
      settemp--;

      //update the LCD
      setpoint();
    }

  } //END of  buttonDown

  //*************************************              n e x t   s w i t c h

} //END of checkSwitches()


//******************************************************************************************
//update the LCD with the set-point information
void setpoint()
{
  lcd.setCursor(7, 3);
  lcd.print (settemp, 0);

  lcd.setCursor(10, 3);
  lcd.print((char) 223);  // ° degree
  lcd.print ('C');

  lcd.setCursor(15, 3);
  lcd.print(settemp * 1.8 + 32, 0);

  lcd.setCursor(18, 3);
  lcd.print((char) 223);  // ° degree
  lcd.print('F');

  settemphyst = settemp - hysteresis;
  lcd.setCursor(13, 0);
  lcd.print (settemphyst, 1);

  lcd.setCursor(18, 0);
  lcd.print((char) 223);  // ° degree
  lcd.print('C');

} //END of setpoint()


//******************************************************************************************
//IR controls sent to Swamp Cooler
void  sendIRcontrol()
{
#ifdef tarabas05

  const uint8_t NEC_KHZ = 38; // 38kHz carrier frequency for the NEC protocol

  const uint16_t irSignal[] = { 8600, 4280, 520, 1620, 520, 560, 520, 540, 560, 520, 520, 540, 520, 560, 520, 560, 520, 540, 520, 560, 520, 540, 580, 1580, 520, 1620, 520, 1620, 520, 1640, 520, 1620, 560, 1580, 580, 1560, 580, 500, 580, 1560, 580, 500, 560, 1580, 520, 560, 520, 1620, 580, 500, 520, 540, 540, 1600, 580, 500, 520, 1620, 580, 500, 520, 1640, 500, 560, 560, 1580, 520, 40200, 8660, 2120, 560, 26664, 8660, 2120, 520, 26704, 8640, 2120, 560}; // Using exact NEC timing
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.

  delay(100); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal

#endif

} //END of sendIRcontrol()


//******************************************************************************************
//IR controls sent to Swamp Cooler
void  adjustTemperature()
{
  //************************
  //when the cooler is OFF and the temperature is too hot, turn ON the cooler
  if (unitOnOffFlag == OFF && currentTemperature > settemphyst)
  {
    unitOnOffFlag = ON;

    //turn ON the cooler LED
    digitalWrite(coolerOnOffLED, LEDon);

    sendIRcontrol();

    //lengthen the timing to settle out possible electrical noise in the system
    adjustInterval = 5000;

    //we just turned the unit ON, no use checking if we should turn it OFF right away
    return;
  }

  //************************
  //when the cooler is ON and the temperature is cold enough, turn OFF the cooler
  //0.5 is to add a small amount extra hysteresis
  if (unitOnOffFlag == ON && currentTemperature <= settemphyst - 0.5)
  {
    unitOnOffFlag = OFF;

    //turn OFF the cooler LED
    digitalWrite(coolerOnOffLED, LEDoff);

    sendIRcontrol();

    //lengthen the timing to settle out possible electrical noise in the system
    adjustInterval = 5000;

  }

} //END of  adjustTemperature()


//******************************************************************************************

Hi Larry!
In case you wonder, I didnt give up. I just had to wait until saturday to get all my parts in to rebuild the whole project on the bread board. today after some other work i had to do, i finished it.

  • the rebuild should take care of any noise or touching wires i perhaps have or had in my initial project.
  • i also put all the resistors in place at the IR Led circuit.

so far the overall behaviour is unfortunately exact the same. the hysterises isnt really a hysterises. the swamp cooler always comes on as soon the hysterises setting is under the room temp.
for clarificationon that i was asking you a few times if there should not be a stored state in between ( you didnt reply): the swamp cooler is only triggered on by the settemp. itself ,then, for my understanding, the programm should memorize this and doesnt do anything until the hysterises is reached. hysterises itself wont be able to turn the swamp cooler on.
i also saw the room temp a few times bouncing on the display during playing with the settemp.

what a bummer. i still study your code and the sources you gave me. thank you again. hopefully i can modify sucessfully your code. unfortunately i dont have any clue about the temp bouncing.

are you sure your setup doenst trigger the IR led on once hysterises is below room temp?

The room temperature is read from the 18B20 and stored in a variable that is not changed by code.

If you are seeing bouncing, the hardware is suspect.

The sendIRcontrol() function is what sends your IR signal to the cooler. The adjustTemperature() function calls sendIRcontrol(). Feel free to examine the sketch to see how the function is called.


Show us a good image of different views of the actual wiring.



When you unplug the Swamp Cooler, do things settle down ?

i actually never unplug the swamp cooler. the room temp stabilize once i dont change any input state.
just for curiosity, could i please get you to answer my question, is your hysterises also able to turn the swamp cooler on?

and regarding the temp bouncing: the hardware is 100% changed out, i purposly did not use any part from the original project. and the bouncing only occures during using the input buttons.

The adjustTemperature() is where it is determined if an IR signal is sent.

if (unitOnOffFlag == ON && currentTemperature <= settemphyst - 0.5)
This above line of code is the comparison line.
That line of code is rock solid.


You could try changing these two lines from:


#define ON                        HIGH
#define OFF                       LOW

To:

#define ON                        true
#define OFF                       false

Once again I see no intermittent issues here.


I highly urge you not rely on pugging wires into the Arduino header; use proper Dupont male connector terminated wires.

  • What is the value of the resistors on the 3 switches ?

  • What is the value of the pull-up resistor on the 18B20 ?

  • What are the values of the resistors on the NPN transistor ?

If you have DVM measure the resistor values.

Also what voltage do you measure on the 5v pin ?

hi larry, as you see, my actual project uses dupont male connectors. i can see you being concerned about bouncing temps with bad wire connections.

-i had a look at void adjusttemp., the line you pointed out. however, everytime hysterises is below room temp the swampcooler comes on... i can video record it if you would like

-the resistors at the switches and 18b20 are all 4,7 kilo ohm, i just measured them again

  • on the transistor: i looked up your sent drawing, the base has a 220ohm and towards the led your drawing showed 3x220ohm parallel. so i calculated a single resistor value of 71 ohm . so i used an 47 ohm i had available

Let’s add more hysteresis.

Change to:

if (unitOnOffFlag == ON && currentTemperature <= settemphyst - 1)


You can then try changing this line:

if (unitOnOffFlag == OFF && currentTemperature > settemphyst)

To:
if (unitOnOffFlag == OFF && currentTemperature > settemp)