Debounce button and delays

Hi larry.
Last weekend I could not upload your code, I had an ide error related to lcd display. I stopped late at night...
Now I am at work and glance over your code and try to learn and understand it, but I am failing... Could you elaborate on the code?
What all it does, the idea behind it and how it supposed to work? What are the commands meaning?

So far I learned that the sensor reading and calculating the actual temp takes 750ms, so either I accept this or in the meantime I let the code for something else. But how that actually work I have no clue.
Thanks Andre

How about you ask questions about the lines you do not understand and we can then answer them.

To start with:

  //*************************************
  //used to see if our code is blocking
  if (currentMillis - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = currentMillis;

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

New users often write code that is blocking.
This means the sketch stops what it is doing and waits :

  • for input
  • a delay interval
  • for a sensor input.

This is bad.
We should always write code so it is responsive and never freezes code execution.
For example we never (hardly ever) recommend the use of delay( ) as it stops for that amount of time.

The above code will toggle a LED every 500ms giving us a visual indication that code is not stopping somewhere.

Hi larry, thanks again for your help, it is very much appriciated. I hope i dont ask too many questions = ) I can pay back with knowledge about high voltage, 3phases, wind industry, civil engineering.
I try to wrap my head around your first detailed explanation. I assume currentMillis is a command to start internally a timer. I also understood the purpose of it. But logically this one is tough to comprehend:

  • I assume I give for the very first time counting command with the term millis(); -> written right after void loop{ ?
  • Is this command then actually named currentMillis because it is written as command currentMillis = millis(); ?
    -i used this millis before to learn about it. as i saw on the serial monitor, even we run a loop, this timing is only once initiated and runs indefinitly? what is the max number?
  • Are the ( ) after the wort millis actually represend an unknown value, like the count itself?
  • You wrote this whole timing thing into its own loop. I didnt know that is possible. what is the benefit for this? is it perhaps needed just for the fact we need to execute something which needs more time by itself as the rest of the programm?
    the toughest question in terms of how the timing works makes my brain smoking: after the command counting is executed ( i assume with currentMillis = millis(); ), it wants to subtract heartbeatMillis, which i guess for the very first time is zero. therefore any count at that time (lets assume a random number 56) minus zero is smaller than 500. Then, I assume, heartbeatMillis = currentMillis tells the program that the count currentMillis is now 56, wait a moment, is that forcing to correct the actual initial count to whatever number it is/was???? If so, i guess I explained this thing the very first time to myself as I am writing this...
    so setting the timer to 56 and come back in the next loop it would calculate 56 minus 56, which is zero, so the if comand would not be executed because its smaller than 500 and the LED doesnt come on?
    Should I be on the right track then by that logic the if comand gets executed when there is a delay in the code of 557milliseconds, since 557-56= 501.
  • what happens during the next loop? the timer started now at 501. Am I right the loop shoud delay again 557milliseconds, so the programm would calculate 557 minus 557 = 0, so the LED doesnt toggle. the following loop it calculates 0 minus 557, which is 0 again, so the led doesnt toggle again. so on and so on, actually the LED only toggled once?
  • I keep writing as a think: what if there is a delay of 2000 milliseconds? 2000 is then the new count. in the next loop there is another delay of 2000. 2000 minus 2000 is 0. so even there is a delay the difference is smaller 500 and the LED isnt toggled??
  • how you toggle the LED? I know digitalwrite tells it to do write to a pin. now within the bracket the hearbeatLED represents the location which was prior declared as a byte and pin 13?
  • the ! I believe means unequal, so i tell it to write the opposite of actually reading this pin?
  • I assume I give for the very first time counting command with the term millis(); -> written right after void loop{ ?

millis() is a function available to the user which returns the number of milliseconds since the Arduino was powered ON or reset.

If you were to print the value of millis(), you would see an incrementing number in the serial monitor. Serial.println(millis());

The data type that millis() returns is unsigned long.

This returned value has a range of 0 to 4,294,967,295 milli seconds. When there is an overflow, we reset to zero.

4,294,967,295ms is about 50 days.

  • Is this command then actually named currentMillis because it is written as command currentMillis = millis(); ?

currentMillis is just a variable we create; we could call it anything e.g., lastTimeWeDidThis

currentMillis = millis(); this says go get the returned value from the function name millis() and place this into the varraible currentMillis. Note, since we are getting an unsigned long value from millis() we need to make the data type of currentMillis unsigned long.

We place the line of code currentMillis = millis(); at the top of loop() and then use the variable currentMills in subsequent lines of code.

However we could just use millis() rather than currentMillis in our calculations.

  • i used this millis before to learn about it. as i saw on the serial monitor, even we run a loop, this timing is only once initiated and runs indefinitly?

Yes, mill() runs in the background all the time where it is constantly update.

-what is the max number?

0 to 4,294,967,295

  • Are the ( ) after the wort millis actually represend an unknown value, like the count itself?

( ) is a designation the compiler needs for syntax and really just means function

millis(); says go to the millis function, the ( ) is necessary.

  • You wrote this whole timing thing into its own loop. I didnt know that is possible. what is the benefit for this? is it perhaps needed just for the fact we need to execute something which needs more time by itself as the rest of the programm?

The following code is not a loop, it’s just a code segment whose lines pertain to each other.

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

//used to see if our code is blocking

if (currentMillis - heartbeatMillis >= 500) //asks have we reached our target of 500ms

{

//restart the TIMER

heartbeatMillis = currentMillis; //says update the heartbeat time to the current time

//toggle the LED

digitalWrite(heartbeatLED, !digitalRead(heartbeatLED))

}

  • the toughest question in terms of how the timing works makes my brain smoking: after the command counting is executed ( i assume with currentMillis = millis(); ), it wants to subtract heartbeatMillis, which i guess for the very first time is zero.

Correct, at power up, currentMillis is zero and so is heartbeatMillis 0 – 0 = 0

  • therefore any count at that time (lets assume a random number 56) minus zero is smaller than 500.

Yes

Let’s say we are at 0.45 seconds after powerup, currentMillis will be 450. Since heartbeatMillis at power up is zero (0) we have currentMillis – heartbeatMillis i.e. 450 – 0 which is 450

  • Then, I assume, heartbeatMillis = currentMillis tells the program that the count currentMillis is now 56, wait a moment, is that forcing to correct the actual initial count to whatever number it is/was???? If so, i guess I explained this thing the very first time to myself as I am writing this...

Let’s assume curentMillis was 523. our math will be 523 – 0 = 523

The following line of code will now be true since 523 is greater than 500

if (currentMillis - heartbeatMillis >= 500)

if (523 - 0 >= 500) //Yes this is true

  • so setting the timer to 56 and come back in the next loop it would calculate 56 minus 56, which is zero, so the if comand would not be executed because its smaller than 500 and the LED doesnt come on?

Yes. Dosen’t toggle.

  • Should I be on the right track then by that logic the if comand gets executed when there is a delay in the code of 557milliseconds, since 557-56= 501.

YES you got it !

  • what happens during the next loop? the timer started now at 501. Am I right the loop shoud delay again 557milliseconds, so the programm would calculate 557 minus 557 = 0,

YES

  • so the LED doesnt toggle. the following loop it calculates 0 minus 557, which is 0 again, so the led doesnt toggle again. so on and so on, actually the LED only toggled once?

No, if at a period of time, currentMillis was 1058 and our heartbeatMillis is 557, we have 1058 – 557 = 501 therefore the if( ) will again evaluate to true and we again will toggle the LED. Hence the LED toggles every 1/2 second (500ms).

  • I keep writing as a think: what if there is a delay of 2000 milliseconds? 2000 is then the new count. in the next loop there is another delay of 2000. 2000 minus 2000 is 0. so even there is a delay the difference is smaller 500 and the LED isnt toggled??

When we write our sketches in a non-blocking fashion, there will never (should never be) at time when currentMillis is greater than 500 difference from heartbeatMillis since we update the value of heartbeatMilli.

However, let’s say currentMillis was 2000 and heartbeatMillis was 57.

The math will be 2000- 57 = 1943 where 1943 is >= 500; in this case there will be a STUTTER in the regular flashing of our heartbeat LED.

Hence if we see the LED not flashing in a regular fashion, we know somewhere in our sketch something is blocking operation. We may want to troubleshoot to see why this is happening.

  • how you toggle the LED? I know digitalwrite tells it to do write to a pin. now within the bracket the hearbeatLED represents the location which was prior declared as a byte and pin 13?

Then pin number 13.

  • the ! I believe means unequal, so i tell it to write the opposite of actually reading this pin?

! says take the opposite level.

If digitalRead(heartbeatLED) was HIGH then the ! says LOW

If digitalRead(heartbeatLED) was LOW then the ! says HIGH

Therefore, if we write to our pin the opposite value that the pin is in, the LED toggles.

Great questions !

OMG, i just ran through your reply without comprehend everything yet...
I dont remember when i felt such a big appreciation for somebody. I guess its because you help for free and cut away so many endless hours of researching....
I also just uploaded your code, i didnt work before (last weekend when you posted it), because it complained about some lcd lines. I just guessed and removed some lines, and : DENG, it works!
Amazing, you are a sharp guy, thousand thanks. I seriously want to give something in return. Are you living in southern california???

  • for now, i need to find out how to add my infrared sending part into the code, after these last two years i forgot so much i did before, also a new IDE complaint so much about my old code. (the thermostat quit one day).Initially my thermostat wasnt great, it turned my swamp cooler on and off, but the buttons were slow (as you fixed), and for whatever reason, when i plugged my arduino in, it turned the swamp cooler on without i actually pushed the button on. then, i had to enter the set temp (including the hysterises) over the actual temp and then back down to the desired set temp, to actual let the thermostat do its job.... LOL. I hope I find that issue by myself, otherwise I ask you 5000 additional questions.
    but if you dont mind, from what you send me, there are more questions left I desire to ask you about. Please let me help back in any way. I also build stuff in my leasure, I weld, lathe, mill, I 3d print and you eventually have a question for me. sincerely, Andre

"Are you living in southern california???"
Way up north in Canada.

BTW, you might enjoy going through this thread (900+ posts):


Lots of volunteers here ready to help with project questions.

We learn lots too !


You can read what's below if you want.
OR
Ignore what's below and just be confident the stuff just works like a charm.


Now there is one more important thing about what has been discussed.

unsigned long says the value has no sign i.e. always positive.

Integer math on the Arduino is done an unsigned calculation.

Let’s say currentMillis has overflowed and is now at a value of 100

Let’s say the value of heartbeatMillis was 4294967195

Our math will be:

currentMillis – heartbeatMillis

100 – 4294967196 = -4,294,967,096 however, the result is negative which it cannot be.

The Arduino drops negative part of -4,294,967,096 and we are left with = 200.

i.e. 100 – 4294967196 = -4,294,967,096 which converts to +200

200 >= 500 is not true so our LED will not toggle yet as we still need 300ms to go.


For a better explanation of this, read this discussion:

http://www.gammon.com.au/forum/?id=12127

OR

Take it as there is no overflow problem in our timing calculations if we adhere to subtraction.


BTW you are now an expert in replacing delay( ) function with the BWD (Blink Without Delay) technique.

Hi Larry, i tried to include my final piece, the infrared sending. Of course I failed, since Im mostly guessing... I tried to use the storeState and go off from there. I thought I can use it to build in my hysterises and then send the code. This IR-code is used for turning the swamp cooler off as well as turning it on. But the swamp cooler doesnt act, i also dont see a infrared light looking through the cell phone camera towards the infrared emitter...
The sending part i checked earlier by itself with a seperate program I found from somebody. It worked. Maybe you want to help me again. First I attach my code from you with the IR part included, after that I attached the infrared code itself which worked.
What I also dont understand: I copied the missing IR code pieces in your code, but it complaint and said #include "PinDefinitionsAndMore.h" isnt defined (when i remember the error correctly). so i had to take your code with my IR changes and actually put it in the IR code, then in compiled without errors...?

#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 pullup
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 20, 4);

#define CLOSED HIGH
#include <IRremote.h>
#include "PinDefinitionsAndMore.h"
IRsend irsend;

float settemp = 25;
float settemphyst;

const byte heartbeatLED = 13;
const byte buttonUp = 10;
const byte buttonOnOff = 9;
const byte buttonDown = 8;

byte storedState = LOW;
byte lastButtonState;
byte lastbuttonUp;
byte lastbuttonDown;
byte currentstate;
byte triggercoolingon = LOW; //= Intrared state off state
byte lastcoolingstate; //stores state of Infrared state
//Timing stuff
unsigned long currentMillis;
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long tempMillis;

//***************************************************************************
void setup()
{

pinMode(LED_BUILTIN, OUTPUT);
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);
Serial.begin(9600);
sensors.begin();
lcd.begin();

pinMode(heartbeatLED, OUTPUT);

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

lcd.backlight();
lcd.print("Hello Guys");
lcd.setCursor(0, 1);
lcd.print("My Invention");
delay(2000);
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);
lcd.print("C");
lcd.setCursor(18, 2);
lcd.print((char) 223);
lcd.print("F");
lcd.setCursor(17, 1);
lcd.print("OFF");

setpoint();
}

//***************************************************************************
void loop()
{
currentMillis = millis();

//*************************************
//used to see if our code is blocking
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();

}

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

lcd.setCursor(5, 2);
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
sensors.setWaitForConversion(false);
sensors.requestTemperatures();
sensors.setWaitForConversion(true);

}

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

} //END of loop()

//***************************************************************************
void checkSwitches()
{
//************************************************** buttonOnOff
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
  storedState = !storedState;

  lcd.setCursor(17, 1);
  if (storedState == HIGH)
  {
    lcd.print("ON ");
  }

  else
  {
    lcd.print("OFF");
  }
}

} //END of buttonOnOff

//************************************************** buttonUp
//up settemp
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 ++;
  
  setpoint();
}

} //END of buttonUp

//************************************************** buttonDown
//down settemp
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 --;

  setpoint();
}

} //END of buttonDown

//************************************************** Next switch

} //END of checkSwitches()

//***************************************************************************
void setpoint()
{
lcd.setCursor(7, 3);
lcd.print (settemp, 0);
lcd.setCursor(10, 3);
lcd.print((char) 223);
lcd.print ("C");

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

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

} //END of setpoint()
//*************************************************
void Infrared()
{
if (storedState == HIGH){ //stored state means the display says Thermostat "on"
if (sensors.getTempCByIndex(0) > settemp) {
triggercoolingon = HIGH;
if (triggercoolingon !=lastcoolingstate){
lastcoolingstate= triggercoolingon;
if (triggercoolingon == HIGH){
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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
                 }
    }
}
 
if (sensors.getTempCByIndex(0) < settemphyst){
 triggercoolingon == LOW;
                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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
                 }

}
}
++++++++++++
IR Code itself:
++++++++++++

#include <IRremote.h>
#include "PinDefinitionsAndMore.h"
IRsend irsend;
void setup(){

pinMode(LED_BUILTIN, OUTPUT);

IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); 

}
void loop () {
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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
     }

Please edit your post:

In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.


#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 pullup
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 20, 4);

#define CLOSED                    HIGH
#include <IRremote.h>
#include "PinDefinitionsAndMore.h"
IRsend irsend;

float settemp                   = 25;
float settemphyst;

const byte heartbeatLED         = 13;
const byte buttonUp             = 10;
const byte buttonOnOff          = 9;
const byte buttonDown           = 8;

byte storedState                = LOW;
byte lastButtonState;
byte lastbuttonUp;
byte lastbuttonDown;
byte currentstate;
byte triggercoolingon = LOW; //= Intrared state off state
byte lastcoolingstate;  //stores state of Infrared state
//Timing stuff
unsigned long currentMillis;
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long tempMillis;


//***************************************************************************
void setup()
{
  
  pinMode(LED_BUILTIN, OUTPUT);
   IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);
  Serial.begin(9600);
  sensors.begin();
  lcd.begin();

  pinMode(heartbeatLED, OUTPUT);

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

  
  lcd.backlight();
  lcd.print("Hello Guys");
  lcd.setCursor(0, 1);
  lcd.print("My Invention");
  delay(2000);
  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);
  lcd.print("C");
  lcd.setCursor(18, 2);
  lcd.print((char) 223);
  lcd.print("F");
  lcd.setCursor(17, 1);
  lcd.print("OFF");
  
  setpoint();
}


//***************************************************************************
void loop()
{
  currentMillis = millis();

  //*************************************
  //used to see if our code is blocking
  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();
  }

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

    lcd.setCursor(5, 2);
    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
    sensors.setWaitForConversion(false);
    sensors.requestTemperatures();
    sensors.setWaitForConversion(true);

  }

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

} //END of loop()


//***************************************************************************
void checkSwitches()
{
  //**************************************************  buttonOnOff
  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
      storedState = !storedState;

      lcd.setCursor(17, 1);
      if (storedState == HIGH)
      {
        lcd.print("ON ");
      }

      else
      {
        lcd.print("OFF");
      }
    }

  } //END of  buttonOnOff

  //**************************************************  buttonUp
  //up settemp
  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 ++;
      
      setpoint();
    }

  } //END of  buttonUp

  //**************************************************  buttonDown
  //down settemp
  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 --;

      setpoint();
    }

  } //END of  buttonDown

  //**************************************************  Next switch

} //END of checkSwitches()


//***************************************************************************
void setpoint()
{
  lcd.setCursor(7, 3);
  lcd.print (settemp, 0);
  lcd.setCursor(10, 3);
  lcd.print((char) 223);
  lcd.print ("C");

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

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

} //END of setpoint()
//*************************************************
void Infrared()
 {
  if (storedState == HIGH){  //stored state means the display says Thermostat "on"
    if (sensors.getTempCByIndex(0) > settemp) {
    triggercoolingon = HIGH;
        if (triggercoolingon !=lastcoolingstate){
           lastcoolingstate= triggercoolingon;
                  if (triggercoolingon == HIGH){
                    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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
                     }
        }
    }
     
    if (sensors.getTempCByIndex(0) < settemphyst){
     triggercoolingon == LOW;
                    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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
                     }
 
 
 }
 }
infrared code itself


#include <IRremote.h>
#include "PinDefinitionsAndMore.h"
IRsend irsend;
void setup(){
  
                                                                                                                    
  pinMode(LED_BUILTIN, OUTPUT);
  
    IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); 
  }
void loop () {
                    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(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
         }
 
 
 

Are you using the TSOP4838 receiver ?

image

no. I am using an LED as a sender. my whole project is using my thermostatcode to create an IR sending signal towards my swamp cooler.
Unless you are asking me which receiver is used in the swamp cooler, i wouldnt know that. but using the IR sending code by itself it definitly makes the swamp cooler coming on and off

Are you using an IR LED ?


Draw a schematic how you have connected the LED to the Arduino then show it to us.

yes, i use an IR LED.
i use the arduino pin and go into a transistor base. I would need to butcher my housing apart to get you the schematics, i dont have old drawings. but i do it if you want me to. the schematics i dont doubt at all, since the led is clearly working with the IR code itself. i can see the signal through my cell phone camera and the swamp cooler toggles on/off with the IR code.

Is this the way you have it wired ?

If so, what is the value of R1, R2 ad what is the part number of the transistor ?

pin 3 (PWM) goes straight into the base of the transistor. it is an npn. the number i cant read for certain, i believe i can read at least three times a 2 followed by an A. the collector goes straight to the IR LED, i wanted to enhance the signal strength. (a permant transistor switch on would blow the LED). no other resistors are involved for that IR circuit. the transistor takes its 5 volt from the arduino.

You need a resistor between the Arduino pin and the transistor base !
You may have damaged the Arduino pin #3 and/or the transistor with no base resistor.


You need a LED current limiting resistor !
You may have blown the IR LED and/or the transistor with no current limiting LED resistor.

:sob:


" i believe i can read at least three times a 2 followed by an A"
2N2222 ?

Just to be sure, are you saying this is your circuit, i.e. no resistor ?

i.e. you are using Arduino pin #3 not the #13 as shown ?

with the transistor you very likely are right. -
your concern with the base current makes sense. however, i just did upload the infrared code again and walked in the swamp cooler area. the IR LED worked, the swamp cooler toggles with the code, i did try that multiple times today, just to rule out your or any other concern.
i know my coding sucks, and i am sure the thermostat hysterisis AND the actual IR sending must be wrong, dont you think?

Here are two sketches that I have used to test out IR LEDs and TSOP4838 receivers.

//Sender

#include <IRremote.h>

IRsend irsend;

void setup() {
}

void loop() {
    irsend.sendNEC(0xFF6897, 28);

    delay(1000);
}

AND

//TSOP4838 receiver
#include <IRremote.h>

const int RECV_PIN = 3;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  irrecv.blink13(true);
}

void loop()
{
  if (irrecv.decode(&results))
  {
    if (results.decode_type == NEC)
    {
      Serial.print("NEC: ");
    }
    else if (results.decode_type == SONY)
    {
      Serial.print("SONY: ");
    }
    else if (results.decode_type == RC5)
    {
      Serial.print("RC5: ");
    }
    else if (results.decode_type == RC6)
    {
      Serial.print("RC6: ");
    }
    else if (results.decode_type == UNKNOWN)
    {
      Serial.print("UNKNOWN: ");
    }
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}